Compare commits

...

1716 Commits

Author SHA1 Message Date
Adam Hathcock
daacb93902 more pooling 2026-01-14 16:49:34 +00:00
Adam Hathcock
eb2f60fb53 rar byte[] better 2026-01-14 16:38:57 +00:00
Adam Hathcock
bd0439c424 change byte[] to memory using pool 2026-01-14 15:55:14 +00:00
Adam Hathcock
b935bcfaef reduce memory usage on headers 2026-01-14 15:33:08 +00:00
Adam Hathcock
56c22cee78 Merge branch 'copilot/add-performance-benchmarking' into adam/async-again 2026-01-14 14:53:17 +00:00
Adam Hathcock
5c4b83e501 Merge remote-tracking branch 'origin/master' into copilot/add-performance-benchmarking
# Conflicts:
#	tests/SharpCompress.Performance/packages.lock.json
2026-01-14 14:52:21 +00:00
Adam Hathcock
84b5b5a717 add more tests 2026-01-14 14:33:20 +00:00
Adam Hathcock
ebfa16f09f more test fixes 2026-01-14 14:12:53 +00:00
Adam Hathcock
c1d240b516 Fix more tests 2026-01-14 14:06:39 +00:00
Adam Hathcock
5c4719f4a9 missing extensions 2026-01-14 13:39:11 +00:00
Adam Hathcock
95d2278d8b fmt 2026-01-14 12:13:29 +00:00
Adam Hathcock
e63ee57ef0 same for writers 2026-01-14 09:29:44 +00:00
Adam Hathcock
775efa1b26 Reader open factories 2026-01-14 09:23:18 +00:00
Adam Hathcock
3677b4b193 add default interfaces to enforce consistency 2026-01-14 08:57:12 +00:00
Adam Hathcock
c32f4b4f2a fix test reference 2026-01-14 08:33:49 +00:00
Adam Hathcock
8d34f88ca6 fix up gitignore 2026-01-13 16:42:54 +00:00
Adam Hathcock
ca4cf25a1f clean up lazy readonly collections and add tests 2026-01-13 16:39:55 +00:00
Adam Hathcock
4fa976b478 remove unused ref 2026-01-13 15:29:02 +00:00
Adam Hathcock
767f3a4985 fix up extensions to more like polyfills 2026-01-13 15:26:45 +00:00
Adam Hathcock
ddc08e068e fix async error 2026-01-13 15:16:38 +00:00
Adam Hathcock
a1a86cdde8 fmt 2026-01-13 14:29:10 +00:00
Adam Hathcock
fc85f1fa2c more tar async fixes 2026-01-13 14:28:45 +00:00
Adam Hathcock
0b8081f320 gzip fixes 2026-01-13 14:24:36 +00:00
Adam Hathcock
0b5371d986 more async fixing 2026-01-13 14:06:14 +00:00
Adam Hathcock
cdca909d84 fmt 2026-01-13 13:58:31 +00:00
Adam Hathcock
ec7d2e357d fix lock? 2026-01-13 13:58:03 +00:00
Adam Hathcock
1c0183ef11 force async tests 2026-01-13 13:56:56 +00:00
Adam Hathcock
9cf2b3129c fixed up async writer 2026-01-13 13:54:15 +00:00
Adam Hathcock
9a4e864f5e fix usage of ArchiveFactory 2026-01-13 13:49:35 +00:00
Adam Hathcock
4df952db1b split out factories for archive 2026-01-12 16:32:26 +00:00
Adam Hathcock
1b4cedfa13 misc fixes 2026-01-12 16:21:20 +00:00
Adam Hathcock
6d6103afd6 update docs 2026-01-12 16:08:16 +00:00
Adam Hathcock
d727d76299 Merge remote-tracking branch 'origin/master' into adam/async-interface 2026-01-12 15:02:19 +00:00
Adam Hathcock
0502ff545e test fixes and fmt 2026-01-12 15:01:29 +00:00
Adam Hathcock
fce4a96718 make Writable interfaces for archive 2026-01-12 14:57:13 +00:00
Adam Hathcock
38203fb950 Fix async reader variable types - Remove double await on ReaderFactory.OpenAsync and use IAsyncReader
- Removed 'await' keyword before ReaderFactory.OpenAsync() calls since the method returns IAsyncReader directly (not Task)
- Changed ZipReader.Open() to ReaderFactory.OpenAsync() in Zip64AsyncTests.ReadForwardOnlyAsync()
- Changed TarReader.Open() to ReaderFactory.OpenAsync() in TarReaderAsyncTests.Tar_BZip2_Entry_Stream_Async()
- Fixed EntryStream disposal from 'await using' to 'using' since EntryStream doesn't implement IAsyncDisposable
- These changes fix compilation errors where async methods were being called on IReader (synchronous) instead of IAsyncReader (asynchronous)
2026-01-12 14:14:46 +00:00
copilot-swe-agent[bot]
80ac10a5fe Merge latest master branch and resolve conflicts
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-12 14:11:57 +00:00
Adam Hathcock
65dba509e0 Merge pull request #1121 from adamhathcock/adam/async
More async for ZipReader and ZipWriter
2026-01-12 14:07:37 +00:00
Adam Hathcock
0615d17b8b fix async interfacing for open 2026-01-12 13:45:21 +00:00
Adam Hathcock
c1f8580d89 Remove unnecessary ValueTask wrappers from async factory methods
Change return types from ValueTask<T> to direct interface types (IAsyncArchive, IAsyncReader, IWriter) for wrapper methods that don't perform async work. This eliminates unnecessary async state machine allocations while maintaining the same public API behavior.

Changes:
- Interface definitions: Updated IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory
- Concrete factories: Updated archive factories (Zip, Tar, Rar, GZip, SevenZip) and reader-only factories (Ace, Arc, Arj)
- Static factory methods: Updated ReaderFactory, ArchiveFactory, WriterFactory to use new signatures
- Archive classes: Updated static OpenAsync methods in ZipArchive, TarArchive, RarArchive, SevenZipArchive, GZipArchive
- Supporting changes: Updated Factory.cs and async polyfills

Performance benefit: Reduced GC pressure by eliminating unnecessary state machine overhead for non-async wrapper methods.
2026-01-12 13:16:44 +00:00
Adam Hathcock
c5a6f900df Merge branch 'adam/async' into adam/async-interface 2026-01-12 13:02:51 +00:00
Adam Hathcock
3807c3ce2a Merge pull request #1127 from adamhathcock/copilot/sub-pr-1121-yet-again
Fix async test method naming in ZipArchiveAsyncTests
2026-01-12 12:10:51 +00:00
Adam Hathcock
d2f328af01 Merge pull request #1126 from adamhathcock/copilot/sub-pr-1121-another-one
Fix typo in TestBase.cs comment
2026-01-12 12:10:11 +00:00
Adam Hathcock
c3ffcf4fe8 Merge pull request #1125 from adamhathcock/copilot/sub-pr-1121-again
[WIP] Update ZipReader and ZipWriter based on review feedback
2026-01-12 12:09:42 +00:00
copilot-swe-agent[bot]
95c409d979 Change File.Create to File.OpenWrite in TarReaderAsyncTests for consistency
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-12 12:09:12 +00:00
Adam Hathcock
dadf9e71bb Merge pull request #1124 from adamhathcock/copilot/sub-pr-1121
[WIP] Address feedback on async implementation for ZipReader and ZipWriter
2026-01-12 12:09:10 +00:00
Adam Hathcock
05ebf22009 Start using the interface to draw distinction between async and sync 2026-01-12 12:08:25 +00:00
copilot-swe-agent[bot]
f4b1780d8a Rename async test methods to use _Async suffix instead of _Sync
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-12 12:08:23 +00:00
copilot-swe-agent[bot]
921cff00a5 Fix async test method naming: rename Sync to Async
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-12 12:08:09 +00:00
copilot-swe-agent[bot]
64a09eb0f8 Fix typo in TestBase.cs comment: 'akways' -> 'always'
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-12 12:06:47 +00:00
copilot-swe-agent[bot]
3a636531e8 Initial plan 2026-01-12 12:05:34 +00:00
copilot-swe-agent[bot]
292da90184 Initial plan 2026-01-12 12:05:22 +00:00
copilot-swe-agent[bot]
90c8ff8650 Initial plan 2026-01-12 12:05:11 +00:00
copilot-swe-agent[bot]
0f37049aad Initial plan 2026-01-12 12:05:04 +00:00
Adam Hathcock
3fb07d129f Use async dispose always 2026-01-12 10:19:01 +00:00
Adam Hathcock
8d0ac5062f Merge pull request #1123 from adamhathcock/adam/add-more-docs
Add more documentation
2026-01-11 12:20:55 +00:00
Adam Hathcock
b2d1505e5c remove section on allocations 2026-01-11 12:20:40 +00:00
Adam Hathcock
a35e65ee42 use ifdefs for creating files? 2026-01-08 16:52:23 +00:00
Adam Hathcock
d1fcf31f7e fmt 2026-01-08 16:31:11 +00:00
Adam Hathcock
17cd934b5b use async methods where we can 2026-01-08 16:24:11 +00:00
Adam Hathcock
ae614cd3fe update references 2026-01-08 16:14:40 +00:00
Adam Hathcock
47037a4b9d docs: Add explicit guideline that agents should never commit to git
Agents should stage files and leave committing to the user. Only create
commits when the user explicitly requests them.
2026-01-08 15:49:10 +00:00
Adam Hathcock
507b1e35d8 docs: Remove broken references to non-existent files
- Remove CONTRIBUTING.md reference from ARCHITECTURE.md
- Remove ERRORS.md reference from API.md
- Remove TROUBLESHOOTING.md reference from ENCODING.md
- Remove TROUBLESHOOTING.md reference from PERFORMANCE.md

All markdown files now reference only existing documentation.
2026-01-08 15:47:57 +00:00
Adam Hathcock
2839e1d33f Update docs/ENCODING.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-08 15:39:47 +00:00
Adam Hathcock
ef0b9d525c merge conflicts 2026-01-08 15:37:55 +00:00
Adam Hathcock
01e6e04a78 Merge branch 'master' into adam/async
# Conflicts:
#	src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs
#	src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs
2026-01-08 15:36:41 +00:00
Adam Hathcock
8c876c70af Add more documentation 2026-01-08 15:34:48 +00:00
Adam Hathcock
a7d6d6493e add version numbers again to get them 2026-01-08 14:22:54 +00:00
Adam Hathcock
b6cc95af73 Merge pull request #1122 from adamhathcock/adam/netstandard-20-readd
Readd netstandard 2.0
2026-01-08 14:03:30 +00:00
Adam Hathcock
bdcc1d32c2 fix scratch dir creation 2026-01-08 14:01:35 +00:00
Adam Hathcock
90d91cc7c2 Merge pull request #1117 from adamhathcock/adam/rework-archive-encoding
Change ArchiveEncoding to interface.
2026-01-08 13:39:30 +00:00
Adam Hathcock
ec83cf588f Readd netstandard 2.0 2026-01-08 13:33:36 +00:00
Adam Hathcock
4f0a2e3c95 disable zip64 tests 2026-01-08 12:55:16 +00:00
Adam Hathcock
3747a27109 Task to ValueTask 2026-01-08 12:35:12 +00:00
Adam Hathcock
b501bac54a better names for new interfaces 2026-01-08 12:02:26 +00:00
Adam Hathcock
7aec98d652 read async interface for reader 2026-01-08 11:28:15 +00:00
Adam Hathcock
406b198e0e can't dispose before returning 2026-01-08 10:24:33 +00:00
Adam Hathcock
8e42296c3a switch Task to ValueTask 2026-01-08 10:22:53 +00:00
Adam Hathcock
60e5220bd0 fmt 2026-01-08 09:41:48 +00:00
Adam Hathcock
0f37cbfd0b archive async path uses new async interface 2026-01-08 09:39:04 +00:00
Adam Hathcock
541fd136d5 IArchiveAsync 2026-01-08 09:14:46 +00:00
Adam Hathcock
60d42ca9c3 fmt 2026-01-07 16:38:48 +00:00
Adam Hathcock
5c947bccc7 Merge branch 'adam/update-docs' 2026-01-07 16:18:51 +00:00
Adam Hathcock
fbdefc17c1 updates from review 2026-01-07 16:18:27 +00:00
Adam Hathcock
1425c6ff0d Merge pull request #1120 from adamhathcock/adam/update-docs
Update docs
2026-01-07 16:12:51 +00:00
Adam Hathcock
e038aea694 move old changelog 2026-01-07 16:10:55 +00:00
Adam Hathcock
87ccbf329d moved examples to USAGE 2026-01-07 15:56:38 +00:00
Adam Hathcock
9dcf384263 update for progress reporting 2026-01-07 15:30:26 +00:00
Adam Hathcock
ac0716ddeb write testing 2026-01-07 15:01:04 +00:00
Adam Hathcock
b9792ca491 fix async zip decompression 2026-01-07 14:54:32 +00:00
Adam Hathcock
c3fd42057a Pass more Zip tests 2026-01-07 14:47:20 +00:00
Adam Hathcock
39d85ff4f6 conflicts from merge 2026-01-07 12:18:14 +00:00
Adam Hathcock
fbce3e77ba Merge branch 'master' into adam/async
# Conflicts:
#	src/SharpCompress/Utility.cs
2026-01-07 12:11:19 +00:00
Adam Hathcock
66e9de2685 fixed comment 2026-01-07 11:26:42 +00:00
Adam Hathcock
321520408b fmt 2026-01-07 11:12:02 +00:00
Adam Hathcock
68451bd75f Use explicit enum, add comments 2026-01-07 11:10:15 +00:00
Adam Hathcock
486fdf118b move to own files and refactor UTF8 usage 2026-01-07 10:39:18 +00:00
Adam Hathcock
bd3cda0617 Some restoring of functionality 2026-01-07 10:32:02 +00:00
Adam Hathcock
725503d1ce Change ArchiveEncoding to interface. Simplify class. Question what to do about Forced and complex access 2026-01-07 08:44:12 +00:00
Adam Hathcock
be045c4f15 Merge pull request #1114 from adamhathcock/copilot/fix-7z-file-decompression-error
Fix async decompression of .7z files by implementing Memory<byte> ReadAsync overload
2026-01-07 08:16:51 +00:00
Adam Hathcock
fd968b3f78 Update src/SharpCompress/IO/ReadOnlySubStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-06 16:33:03 +00:00
Adam Hathcock
833dd7b3a2 fix tests and fmt 2026-01-06 15:33:43 +00:00
Adam Hathcock
b9258ad496 use more ValueTask methods but types are still created because of state machine suspension 2026-01-06 15:26:49 +00:00
copilot-swe-agent[bot]
0678318dde Fix async decompression by implementing Memory<byte> ReadAsync overload
The issue was that .NET 10's ReadExactlyAsync calls the Memory<byte> overload of ReadAsync, which wasn't implemented in BufferedSubStream. This caused it to fall back to the base Stream implementation that uses synchronous reads, leading to cache state corruption.

Solution: Added ValueTask<int> ReadAsync(Memory<byte>, CancellationToken) overload for modern .NET versions.

All tests now passing including LZMA2 and Solid archives.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-06 14:18:15 +00:00
copilot-swe-agent[bot]
7116c0d098 Add async support to BufferedSubStream for 7zip decompression
- Implemented ReadAsync and RefillCacheAsync methods in BufferedSubStream
- Added async test cases for SevenZipArchive (LZMA, LZMA2, Solid, BZip2, PPMd)
- Tests show LZMA, BZip2, and PPMd working correctly
- LZMA2 and Solid archives still failing with Data Error - investigating cache state management

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-06 14:13:48 +00:00
copilot-swe-agent[bot]
2fde8436fb Initial plan 2026-01-06 14:00:03 +00:00
Adam Hathcock
61ecd6475f Merge pull request #1113 from adamhathcock/adam/fix-readonly-dispose
Fix a usage of ReadOnly that use dispose in 7Zip
2026-01-06 13:22:50 +00:00
Adam Hathcock
64b209a772 add disposal tests and fix lzipstream 2026-01-06 13:13:34 +00:00
Adam Hathcock
48dbdbfed5 fmt 2026-01-06 12:49:26 +00:00
Adam Hathcock
cf50311b9c Skip should use framework stuff 2026-01-06 12:45:13 +00:00
Adam Hathcock
e4d8582a2a 7zip streams always want to be disposed 2026-01-06 12:42:48 +00:00
copilot-swe-agent[bot]
a92ce90252 Fix path validation and add iteration cleanup to prevent file reuse
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-05 17:38:17 +00:00
copilot-swe-agent[bot]
e519f61f0f Address code review feedback: fix exception handling and initialization order
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-05 17:36:08 +00:00
copilot-swe-agent[bot]
49f2271253 Format code with CSharpier
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-05 17:33:06 +00:00
copilot-swe-agent[bot]
5b1d11bc1d Add WriteBenchmarks, BaselineComparisonBenchmarks, and comprehensive documentation
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-05 17:31:32 +00:00
copilot-swe-agent[bot]
aa3a40d968 Add BenchmarkDotNet integration with Archive and Reader benchmarks
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-05 17:27:50 +00:00
Adam Hathcock
b825e15406 Merge pull request #1100 from adamhathcock/copilot/fix-read-method-implementations
Consolidate stream extension methods and simplify with framework methods
2026-01-05 17:24:54 +00:00
copilot-swe-agent[bot]
6125654b2e Initial plan 2026-01-05 17:21:29 +00:00
Adam Hathcock
b8e5ee45eb Merge pull request #1109 from adamhathcock/dependabot/nuget/build/SimpleExec-13.0.0
Bump SimpleExec from 12.1.0 to 13.0.0
2026-01-05 17:17:55 +00:00
Adam Hathcock
9f20a9e7d2 Merge pull request #1110 from TwanVanDongen/master
Formats.md updated to reflect additions of Ace, Arc and Arj
2026-01-05 17:14:26 +00:00
Twan
201521d814 Merge branch 'adamhathcock:master' into master 2026-01-05 18:09:55 +01:00
Twan van Dongen
18bb3cba11 Added descriptions for archives Ace, Arc and Arj 2026-01-05 18:08:53 +01:00
Adam Hathcock
af951d6f6a Merge pull request #1102 from TwanVanDongen/master
Add support for ACE archives
2026-01-05 16:37:35 +00:00
Adam Hathcock
e5fe92bf90 Merge pull request #1108 from adamhathcock/dependabot/nuget/dot-config/csharpier-1.2.5
Bump csharpier from 1.2.4 to 1.2.5
2026-01-05 16:15:12 +00:00
dependabot[bot]
b1aca7c305 Bump SimpleExec from 12.1.0 to 13.0.0
---
updated-dependencies:
- dependency-name: SimpleExec
  dependency-version: 13.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 09:32:51 +00:00
dependabot[bot]
c0a0cc4a44 Bump csharpier from 1.2.4 to 1.2.5
---
updated-dependencies:
- dependency-name: csharpier
  dependency-version: 1.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 09:32:17 +00:00
Twan van Dongen
7a49eb9e93 Archives containing encrypted content throws exception. 2026-01-04 19:10:57 +01:00
Adam Hathcock
5aa0610882 Merge pull request #1104 from adamhathcock/copilot/fix-invalidoperationexception-rar
Fix InvalidOperationException when RAR uncompressed size exceeds header value
2026-01-04 12:18:38 +00:00
copilot-swe-agent[bot]
41ed4c8186 Add negative test case for premature stream termination
Added Rar_StreamValidation_ThrowsOnTruncatedStream test that verifies InvalidOperationException IS thrown when a RAR stream ends prematurely (position < expected length). Created TruncatedStream mock to simulate corrupted/truncated RAR files. This test validates the exception condition (_position < Length) works correctly.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-04 11:47:57 +00:00
copilot-swe-agent[bot]
90a33ce6b0 Remove duplicate test that doesn't verify exception case
Removed Rar_StreamValidation_CorrectExceptionBehavior test as it duplicated the validation in Rar_StreamValidation_OnlyThrowsOnPrematureEnd without actually testing the exception case. The remaining test adequately validates that the fix works correctly across multiple RAR formats.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-04 11:36:25 +00:00
copilot-swe-agent[bot]
12574798e1 Update test to document exception behavior for RAR stream validation
Renamed and enhanced the test to better document the fix. Added second test (Rar_StreamValidation_CorrectExceptionBehavior) that explicitly validates the difference between old and new behavior. Tests verify that InvalidOperationException is only thrown when position < expected length (premature termination), not when position >= expected length (which can be valid for some RAR files).

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-04 09:55:18 +00:00
copilot-swe-agent[bot]
83b11254db Add test for InvalidOperationException fix in RAR extraction
Added Rar_ExtractionCompletesWithoutInvalidOperationException test that verifies RAR extraction completes successfully without throwing InvalidOperationException when reading streams to EOF. The test validates the fix works across RAR, RAR5, RAR4, and RAR2 formats by reading all entries completely and ensuring no exceptions are thrown.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-04 09:33:31 +00:00
copilot-swe-agent[bot]
b25493fd29 Fix InvalidOperationException when RAR unpacks more data than header specifies
Changed validation condition from `_position != Length` to `_position < Length` in RarStream.Read() and RarStream.ReadImplAsync() to only throw when unpacking ends prematurely, not when more data is unpacked than the header specifies. This allows successful extraction of RAR files where the actual uncompressed size exceeds the header size.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-04 09:23:47 +00:00
copilot-swe-agent[bot]
bb66100486 Initial plan 2026-01-04 09:10:50 +00:00
copilot-swe-agent[bot]
9bd86f64c9 Replace manual TransferTo implementation with Stream.CopyTo framework methods
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 18:41:02 +00:00
Twan van Dongen
3ebf97dd49 MultiVolume not supported, tests provided by split archive. 2026-01-03 19:09:43 +01:00
Twan van Dongen
bfcdeb3784 Ace largefile test added 2026-01-03 18:48:54 +01:00
copilot-swe-agent[bot]
77015224f6 Add input validation for ReadBytesAsync count parameter
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 17:19:55 +00:00
copilot-swe-agent[bot]
372ecb77d0 Use threshold-based ArrayPool strategy for BinaryReaderExtensions
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 17:17:59 +00:00
copilot-swe-agent[bot]
05642cbdc6 Use ArrayPool for temporary buffers in BinaryReaderExtensions
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 17:12:43 +00:00
Twan van Dongen
feece3d788 Missed some CSharpier edits 2026-01-03 18:08:01 +01:00
Twan van Dongen
94adb77e9e Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2026-01-03 18:01:13 +01:00
Twan van Dongen
909d36c237 more subtle check of magic bytes for ARJ archives 2026-01-03 17:59:17 +01:00
Twan van Dongen
e1c8aa226d Add ACE archive support (read-only, stored entries) 2026-01-03 17:18:00 +01:00
copilot-swe-agent[bot]
1a71c01fd4 Consolidate ReadExact and ReadFully methods into Utility.cs
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 15:58:27 +00:00
Adam Hathcock
54640548ed Consolidate reads 2026-01-03 15:47:10 +00:00
Adam Hathcock
2327679f23 Merge pull request #1098 from adamhathcock/adam/remove-old-release
remove old release
2026-01-03 14:27:13 +00:00
Adam Hathcock
574d9f970c Merge pull request #1099 from adamhathcock/copilot/sub-pr-1098
Configure nuget-release workflow to validate PRs without publishing
2026-01-03 14:22:13 +00:00
copilot-swe-agent[bot]
235096a2eb Configure nuget-release.yml to run on PRs without publishing
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 14:15:50 +00:00
copilot-swe-agent[bot]
a739fdc544 Initial plan 2026-01-03 14:13:34 +00:00
Adam Hathcock
6196e26044 also remove from sln 2026-01-03 13:57:42 +00:00
Adam Hathcock
46a4064989 remove old bulid 2026-01-03 13:54:51 +00:00
Adam Hathcock
72b3948f43 Merge pull request #1095 from adamhathcock/copilot/add-github-action-nuget-release
Add GitHub Actions workflow for automated NuGet releases with multi-platform builds
2026-01-03 13:49:38 +00:00
copilot-swe-agent[bot]
5d47bfaeb6 Add tag push trigger to workflow
- Workflow now triggers on tag pushes in addition to branch pushes
- Tags must match pattern: [0-9]+.[0-9]+.[0-9]+ (e.g., 0.43.0)
- Updated documentation to explain both triggering methods
- Allows publishing by pushing tags directly without requiring branch push

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 13:36:19 +00:00
Adam Hathcock
b2f2ea65ba fmt 2026-01-03 13:31:15 +00:00
Adam Hathcock
7afa468e15 Update build/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-03 13:29:29 +00:00
Adam Hathcock
29cb1fed12 Update build/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-03 13:29:05 +00:00
Adam Hathcock
29f8b512c4 Potential fix for code scanning alert no. 7: Workflow does not contain permissions
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-01-03 13:23:13 +00:00
copilot-swe-agent[bot]
9794c8ba72 Remove GitHub release creation - will be done manually
- Removed create-release build target from build/Program.cs
- Removed CreateRelease constant
- Removed "Create GitHub Release" step from workflow
- Removed permissions: contents: write since no longer creating releases
- Updated NUGET_RELEASE.md to remove all references to GitHub release creation
- Updated TESTING.md to remove GitHub release verification steps
- GitHub releases will now be created manually instead of automatically

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 13:19:23 +00:00
copilot-swe-agent[bot]
f1b305f682 Add matrix build and master branch support to release workflow
- Workflow now triggers on both master and release branches
- Added matrix strategy for windows-latest and ubuntu-latest
- Both OS platforms build and test the project
- Only Windows build publishes to NuGet and creates GitHub releases
- Upload artifacts are now OS-specific (windows-latest-nuget-package, ubuntu-latest-nuget-package)
- Updated documentation to reflect multi-platform builds and master branch support

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 12:54:05 +00:00
Adam Hathcock
091a800c9d Potential fix for code scanning alert no. 6: Workflow does not contain permissions
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-01-03 12:36:50 +00:00
Adam Hathcock
975f5f4b4c make things async 2026-01-03 12:35:34 +00:00
copilot-swe-agent[bot]
9d6cd930ea Use next minor version with beta suffix for prereleases
- Changed prerelease versioning to increment minor version instead of using last tag
- Changed suffix from "preview" to "beta"
- Format is now {NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}
- Example: 0.43.0-beta.123 (if last tag is 0.42.x)
- Updated documentation in NUGET_RELEASE.md and TESTING.md

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-03 11:23:32 +00:00
copilot-swe-agent[bot]
ea02d31096 Add IsArchiveAsync overloads for Zip and GZip factories
- Added IsArchiveAsync interface method to IFactory
- Implemented async versions of IsZipFile, IsZipMulti, IsGZipFile
- Updated ZipFactory and GZipFactory to override IsArchiveAsync
- Updated ReaderFactory.OpenAsync to use IsArchiveAsync
- Fixed Zip_Reader_Disposal_Test2_Async to use ReaderFactory.OpenAsync
- Fixed TestStream to properly forward ReadAsync calls
- Removed BufferedStream wrapping from AsyncBinaryReader as it uses sync Read
- Added default implementation in Factory base class

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-02 18:10:54 +00:00
copilot-swe-agent[bot]
d5913e8371 Fix TESTING.md to use valid version tag format
- Changed example from 0.42.2-test to 0.42.2 to match regex pattern
- Added note that tags must be pure semantic versions (MAJOR.MINOR.PATCH)
- Addresses bot review feedback about documentation inconsistency

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-02 18:04:13 +00:00
copilot-swe-agent[bot]
7f71f76f6e Remove SHA from prerelease version, use only commit count
- Changed prerelease version format from {LAST_TAG}-preview.{COMMIT_COUNT}+{SHA} to {LAST_TAG}-preview.{COMMIT_COUNT}
- Updated documentation in NUGET_RELEASE.md and TESTING.md to reflect the change
- Removed git rev-parse call for short SHA since it's no longer needed

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-02 18:03:18 +00:00
Adam Hathcock
d04830ba90 Add some OpenAsync 2026-01-02 17:52:18 +00:00
copilot-swe-agent[bot]
caa82a6146 Remove duplicate entry in documentation
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 11:49:41 +00:00
copilot-swe-agent[bot]
bcf7137073 Fix code review issues: use cross-platform git execution
- Replaced bash-specific Process execution with SimpleExec's ReadAsync
- Fixed git command execution to work on Windows and Linux
- Added comment about API key handling in push-to-nuget target
- Removed unused System.Diagnostics import

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 11:48:25 +00:00
copilot-swe-agent[bot]
9238cf1128 Move bash logic to C# build targets
- Added determine-version, update-version, push-to-nuget, and create-release build targets
- All version detection and publishing logic now in build/Program.cs
- Workflow calls C# build targets instead of bash scripts
- Updated documentation to reflect C# implementation

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 11:44:20 +00:00
copilot-swe-agent[bot]
2f874ace51 Add comment clarifying sort -V usage
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 10:48:32 +00:00
copilot-swe-agent[bot]
2feabed297 Remove redundant NUGET_API_KEY environment variable
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 10:47:04 +00:00
copilot-swe-agent[bot]
9001e28b36 Add GitHub Actions workflow for NuGet releases
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-01 10:44:59 +00:00
copilot-swe-agent[bot]
24d651d7ae Initial plan 2026-01-01 10:37:43 +00:00
Adam Hathcock
8533b09091 start of implementing zip reading async 2025-12-31 14:53:55 +00:00
Adam Hathcock
44b7955d85 reader tests 2025-12-31 14:43:15 +00:00
Adam Hathcock
038b9f18c6 Merge remote-tracking branch 'origin/master' into copilot/add-buffered-stream-async-read 2025-12-31 14:24:31 +00:00
Adam Hathcock
5667595587 Merge pull request #1091 from adamhathcock/adam/update-deps2
Update dependencies
2025-12-31 14:23:58 +00:00
copilot-swe-agent[bot]
6e0e20ba6e Fix zip64_locator to use ReadUInt32Async instead of ReadUInt16Async
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-30 11:50:41 +00:00
copilot-swe-agent[bot]
ec31cb9987 Fix Zip headers to support both sync and async reading
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-30 11:47:31 +00:00
Adam Hathcock
32d5b61c4a Merge pull request #1093 from adamhathcock/copilot/sub-pr-1091 2025-12-30 11:32:05 +00:00
copilot-swe-agent[bot]
128c9e639f Add back System.Buffers and System.Memory packages
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-30 11:30:12 +00:00
copilot-swe-agent[bot]
5e3f01dc03 Initial plan 2025-12-30 11:26:39 +00:00
copilot-swe-agent[bot]
39a0b4ce78 Use BufferedStream for async reading in AsyncBinaryReader
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-30 11:23:55 +00:00
Adam Hathcock
af719707bf Merge branch 'adam/async-binary-reader' into copilot/add-buffered-stream-async-read 2025-12-30 11:17:16 +00:00
copilot-swe-agent[bot]
8415a19912 Initial plan 2025-12-30 11:15:28 +00:00
Adam Hathcock
1607d2768e Merge branch 'master' into adam/async-binary-reader 2025-12-30 11:13:14 +00:00
Adam Hathcock
c97c05a3a7 Update dependencies 2025-12-30 11:11:40 +00:00
Adam Hathcock
b2beea9c4e Merge pull request #1077 from adamhathcock/copilot/provide-interface-for-entries
Remove ExtractAllEntries restriction for non-SOLID archives
2025-12-23 15:47:52 +00:00
Adam Hathcock
41fbaa1c28 Merge pull request #1085 from adamhathcock/adam/edit-md-files
add some markdown files for planning
2025-12-23 15:38:56 +00:00
Adam Hathcock
d9274cf794 Update tests/SharpCompress.Test/ExtractAllEntriesTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-23 15:38:17 +00:00
Adam Hathcock
583b048046 Update USAGE.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-23 15:38:00 +00:00
Adam Hathcock
ead5916eae Update USAGE.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-23 15:37:28 +00:00
Adam Hathcock
d15ab92da3 add some markdown files for planning 2025-12-23 15:37:04 +00:00
Adam Hathcock
1ab30f2af5 Merge pull request #1084 from adamhathcock/copilot/fix-handled-system-exception
Avoid NotSupportedException overhead in SharpCompressStream for non-seekable streams
2025-12-23 15:15:15 +00:00
Adam Hathcock
4dbe0b91f1 Update src/SharpCompress/IO/SharpCompressStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-23 15:06:24 +00:00
Adam Hathcock
a972d3784e Merge pull request #1082 from adamhathcock/dependabot/nuget/JetBrains.Profiler.SelfApi-2.5.15
Bump JetBrains.Profiler.SelfApi from 2.5.14 to 2.5.15
2025-12-23 15:04:17 +00:00
copilot-swe-agent[bot]
6991900eb0 Remove try/catch blocks, just check CanSeek as requested
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-23 15:01:41 +00:00
copilot-swe-agent[bot]
d614beb9eb Add explanatory comments for CanSeek checks and try-catch blocks
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-23 14:41:44 +00:00
copilot-swe-agent[bot]
253a46d458 Fix NotSupportedException in SharpCompressStream by checking CanSeek
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-23 14:38:11 +00:00
copilot-swe-agent[bot]
32b1ec32c6 Initial plan 2025-12-23 14:32:38 +00:00
Adam Hathcock
eb2cba09b2 update usage 2025-12-23 09:34:55 +00:00
Adam Hathcock
e79dceb67e check should be there 2025-12-23 09:31:51 +00:00
Adam Hathcock
87c38d6dab fix ordering and token passing 2025-12-23 09:22:38 +00:00
dependabot[bot]
9e98d9c45c Bump JetBrains.Profiler.SelfApi from 2.5.14 to 2.5.15
---
updated-dependencies:
- dependency-name: JetBrains.Profiler.SelfApi
  dependency-version: 2.5.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 09:39:01 +00:00
Adam Hathcock
0e9a4b0511 Merge remote-tracking branch 'origin/master' into copilot/provide-interface-for-entries
# Conflicts:
#	src/SharpCompress/Archives/AbstractArchive.cs
2025-12-19 15:41:51 +00:00
Adam Hathcock
eae25aff64 Merge pull request #1076 from adamhathcock/adam/extract-all-test
add extract all test
2025-12-19 14:58:33 +00:00
Adam Hathcock
b8c06ff36e oops 2025-12-19 14:39:37 +00:00
Adam Hathcock
6cf2e054bf fmt 2025-12-19 14:33:24 +00:00
Adam Hathcock
95749234f5 Use proper polyfill for net48 2025-12-19 14:33:06 +00:00
Adam Hathcock
b976961434 Merge fixes 2025-12-19 14:22:09 +00:00
Adam Hathcock
e1aa727513 Merge remote-tracking branch 'origin/master' into adam/extract-all-test
# Conflicts:
#	src/SharpCompress/Archives/IArchiveExtensions.cs
2025-12-19 14:16:29 +00:00
Adam Hathcock
1f71ce1be2 Merge pull request #1080 from adamhathcock/copilot/refactor-write-to-directory-consistency
Standardize extraction API to WriteToDirectory with IProgress support
2025-12-19 14:15:43 +00:00
Adam Hathcock
cf13de6ac1 Merge pull request #1081 from adamhathcock/copilot/sub-pr-1076-again
Fix async LZMA extraction bug for 7Zip archives
2025-12-19 14:14:16 +00:00
Adam Hathcock
c2e01798f8 refactor archive extensions 2025-12-19 14:09:01 +00:00
copilot-swe-agent[bot]
8fc8295a89 Add TODO and explanation for SyncOnlyStream workaround
The SyncOnlyStream wrapper is necessary because the LZMA decoder has bugs in its async implementation that cause state corruption (IndexOutOfRangeException, DataErrorException) even with fresh, non-shared streams.

Without this wrapper, async operations on LZMA streams fail. The proper fix would be to repair the async bugs in LzmaStream.ReadAsync, Decoder.CodeAsync, and OutWindow async operations, but that requires deep changes to the decoder state machine.

Added detailed comments explaining this is a workaround and where the real fix should go.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 13:47:49 +00:00
copilot-swe-agent[bot]
d392991764 Remove CancellationToken from synchronous WriteToDirectory overload
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 13:40:22 +00:00
copilot-swe-agent[bot]
e57e87090f Implement option 2: Avoid async LZMA state corruption for 7Zip extraction
- Each 7Zip file now gets a fresh decompression stream instead of reusing shared streams
- Added SyncOnlyStream wrapper to force async operations to use synchronous equivalents
- This avoids LZMA decoder state corruption bugs in async operations
- Performance trade-off: slower async extraction for 7Zip but correctness guaranteed
- Documented behavior and performance implications in FORMATS.md

All 14 ExtractAll tests now pass (both async and sync)

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 13:33:04 +00:00
copilot-swe-agent[bot]
c701bbbee3 Run CSharpier formatting and document check-format process
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 13:31:35 +00:00
copilot-swe-agent[bot]
2f0eb0bd4b Replace Action<double> with IProgress<ProgressReport> for progress reporting
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 13:25:36 +00:00
copilot-swe-agent[bot]
17bde8da8a Merge branch 'master' of https://github.com/adamhathcock/sharpcompress into copilot/refactor-write-to-directory-consistency 2025-12-19 13:10:33 +00:00
Adam Hathcock
99d355e6ca Merge remote-tracking branch 'origin/master' into copilot/sub-pr-1076-again 2025-12-19 13:05:33 +00:00
Adam Hathcock
c790fd21a4 reading a single byte shouldn't be async 2025-12-19 13:05:04 +00:00
Adam Hathcock
bee51af48b Merge pull request #1044 from adamhathcock/copilot/add-progress-reporting
Unified progress reporting for compression and extraction operations
2025-12-19 12:54:55 +00:00
Adam Hathcock
ca743eae22 fix for running net 10 tests 2025-12-19 12:17:08 +00:00
copilot-swe-agent[bot]
93504cf82f Add sync test and attempt to fix async LZMA extraction bug
- Restored original async ExtractAllEntries test with using statement
- Added new ExtractAllEntriesSync test (all tests pass)
- Fixed potential partial read bug in LzmaStream.DecodeChunkHeaderAsync
  - Added ReadFullyAsync helper to ensure complete reads
  - ReadAsync is not guaranteed to return all requested bytes
- Async tests for 7Zip still failing with Data Error
  - Issue appears related to LZMA2 stream state management
  - _needDictReset flag not being cleared correctly in async flow
  - Further investigation needed

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 12:15:54 +00:00
Adam Hathcock
6d3e4e842b Merge remote-tracking branch 'origin/master' into copilot/add-progress-reporting 2025-12-19 12:13:34 +00:00
copilot-swe-agent[bot]
54b64a8c3b Fix misleading variable name: emptyDirectory -> parentDirectory
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 12:06:36 +00:00
copilot-swe-agent[bot]
0e59bf39f4 Add test for IArchive.WriteToDirectoryAsync
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 12:04:47 +00:00
copilot-swe-agent[bot]
8b95e0a76d Standardize on WriteToDirectory naming and add async support
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 11:57:01 +00:00
copilot-swe-agent[bot]
48a2ad7b57 Fix ExtractAll test to use synchronous extraction methods for 7Zip archives
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 11:55:00 +00:00
copilot-swe-agent[bot]
cfc6651fff Update documentation to reflect ExtractAllEntries universal compatibility
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 11:49:35 +00:00
copilot-swe-agent[bot]
b23827a8db Initial plan 2025-12-19 11:48:49 +00:00
copilot-swe-agent[bot]
3f9986c13c Initial plan 2025-12-19 11:47:53 +00:00
copilot-swe-agent[bot]
224989f19b Remove restriction on ExtractAllEntries and add comprehensive tests
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 11:45:21 +00:00
Adam Hathcock
c7010b75c1 fix the test targets 2025-12-19 11:41:08 +00:00
Adam Hathcock
00cfeee56e Fix logic to match ExtractAllEntries 2025-12-19 11:37:04 +00:00
copilot-swe-agent[bot]
aaa97e2ce2 Merge master branch - add ZStandard compression support and TarHeaderWriteFormat
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-19 11:36:44 +00:00
copilot-swe-agent[bot]
1d52618137 Initial plan 2025-12-19 11:32:17 +00:00
Adam Hathcock
34309f17f4 fmt 2025-12-18 15:33:26 +00:00
Adam Hathcock
220ba67faa add extract all test 2025-12-18 15:26:35 +00:00
Adam Hathcock
230f96e8e8 Merge pull request #1052 from adamhathcock/copilot/move-zstdsharp-into-sharpcompress
Move ZstdSharp into SharpCompress - Complete Integration
2025-12-18 14:48:03 +00:00
Adam Hathcock
930c8899d2 Merge remote-tracking branch 'origin/master' into copilot/move-zstdsharp-into-sharpcompress
# Conflicts:
#	src/SharpCompress/packages.lock.json
#	tests/SharpCompress.Test/packages.lock.json
2025-12-18 12:43:19 +00:00
copilot-swe-agent[bot]
7c0cef7dd8 Clean up unused using statements in ZstandardConstants.cs
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:32:48 +00:00
copilot-swe-agent[bot]
951ebb3fa2 Complete ZstdSharp integration: Add all Unsafe implementation files and remove ZstdSharp.Port dependency
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
2a4d098b41 Initial plan 2025-12-18 12:30:38 +00:00
dependabot[bot]
5839b87f98 Bump csharpier from 1.2.1 to 1.2.3
---
updated-dependencies:
- dependency-name: csharpier
  dependency-version: 1.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-18 12:30:38 +00:00
dependabot[bot]
425a2bd680 Bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-18 12:30:38 +00:00
drone1400
939c2497c8 Reformatted modified files with csharpier 2025-12-18 12:30:38 +00:00
drone1400
8995ba56b8 Add alternative option for writing TAR archives with USTAR header format
- TarWriterOptions now has a property that allows the user to select writing the TAR using the USTAR header format
- if unspecified, will default to the original modern GNU TAR header format
- default behavior is unchanged
2025-12-18 12:30:38 +00:00
HeroponRikIBestest
e941ab60ca Csharpier 2025-12-18 12:30:38 +00:00
HeroponRikIBestest
48860f1349 Improve logic 2025-12-18 12:30:38 +00:00
HeroponRikIBestest
94b2c5c593 Add tests 2025-12-18 12:30:38 +00:00
HeroponRikIBestest
f1d8ae5a22 Add archive-level IsEncrypted flag 2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
e44d2093e5 Consolidate agent instructions into AGENTS.md
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
9fa1201a4c Initial plan 2025-12-18 12:30:38 +00:00
Adam Hathcock
7800808648 first pass of instructions...consolidate? 2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
2789e86d21 Update launch.json to use net10.0 instead of net8.0
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
afd1e39b88 Initial plan 2025-12-18 12:30:38 +00:00
Adam Hathcock
aec4c738ef add vscode config 2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
63ecc8c842 Apply code review feedback: improve documentation structure and add explicit DirectoryEntry case
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
Adam Hathcock
5f6d583521 Update tests/SharpCompress.Test/Zip/ZipReaderTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
0341984f10 Add documentation about ZipReader directory and central directory handling
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
fe757486ae Add multi-volume ZIP documentation to FORMATS.md
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
46d480c9a1 Changes before error encountered
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
8fe3cba7a8 Initial plan 2025-12-18 12:30:38 +00:00
Adam Hathcock
aa19f4da8b update dependencies 2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
a08f95326c Remove netstandard2.0 and net481 targets, keep net48, net8.0, net10.0
- Updated target frameworks to net48;net8.0;net10.0 only
- Removed netstandard2.0 and net481 package conditions
- Updated conditional compilation to use NETFRAMEWORK only
- Updated package description and README

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
b4c5437c92 Fix .NET 10.0 formatting in README
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
8680e3b39e Drop .NET 6 support and add .NET 10 support
- Updated SharpCompress.csproj target frameworks from net48;net481;netstandard2.0;net6.0;net8.0 to net48;net481;netstandard2.0;net8.0;net10.0
- Updated test and build projects to use .NET 10
- Updated global.json to .NET 10 SDK
- Updated CI workflow to use .NET 10
- Fixed deprecated Rfc2898DeriveBytes constructor for .NET 10 (SYSLIB0060)
- Updated package description and README to reflect new supported frameworks
- Updated package versions for .NET 10 compatibility

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-18 12:30:38 +00:00
copilot-swe-agent[bot]
1b3002c8df Initial plan 2025-12-18 12:30:38 +00:00
Adam Hathcock
394fd2e7db Merge pull request #1072 from adamhathcock/dependabot/nuget/dot-config/csharpier-1.2.3
Bump csharpier from 1.2.1 to 1.2.3
2025-12-15 11:02:17 +00:00
Adam Hathcock
d83af56d28 Merge pull request #1071 from adamhathcock/dependabot/github_actions/actions/upload-artifact-6
Bump actions/upload-artifact from 5 to 6
2025-12-15 10:58:08 +00:00
dependabot[bot]
28c93d6841 Bump csharpier from 1.2.1 to 1.2.3
---
updated-dependencies:
- dependency-name: csharpier
  dependency-version: 1.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 09:42:59 +00:00
dependabot[bot]
5f52fc2176 Bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 09:02:14 +00:00
Adam Hathcock
8fba579e3a Merge pull request #1063 from drone1400/tar-ustar-header-format-support
Add alternative option for writing TAR archives with USTAR header format
2025-12-09 08:37:18 +00:00
drone1400
40b1aadeb2 Reformatted modified files with csharpier 2025-12-08 17:49:58 +02:00
Adam Hathcock
40e72ad199 fix AI edit 2025-12-08 11:11:51 +00:00
Adam Hathcock
618b4bbb83 try to tell agents to format 2025-12-08 11:04:08 +00:00
Adam Hathcock
1eaf3e6294 format with csharpier 2025-12-08 11:00:29 +00:00
Adam Hathcock
fd453e946d Update src/SharpCompress/IO/ProgressReportingStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-08 10:55:24 +00:00
Adam Hathcock
c294071015 Update src/SharpCompress/Archives/IArchiveEntryExtensions.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-08 10:55:06 +00:00
Adam Hathcock
c2f6055e33 format 2025-12-08 10:26:45 +00:00
drone1400
5161f4df33 Add alternative option for writing TAR archives with USTAR header format
- TarWriterOptions now has a property that allows the user to select writing the TAR using the USTAR header format
- if unspecified, will default to the original modern GNU TAR header format
- default behavior is unchanged
2025-12-06 17:33:01 +02:00
copilot-swe-agent[bot]
3396f8fe00 Refactor to use ProgressReportingStream for progress tracking
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-05 11:55:29 +00:00
copilot-swe-agent[bot]
9291f58091 Merge master and add comprehensive tests for archive and reader progress
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-12-05 11:44:17 +00:00
copilot-swe-agent[bot]
85f3b17c42 Merge remote-tracking branch 'origin/master' into copilot/add-progress-reporting 2025-12-05 11:33:39 +00:00
Adam Hathcock
2a3086a0d7 Merge pull request #1060 from HeroponRikiBestest/rar-7z-password 2025-12-03 19:58:47 +00:00
HeroponRikIBestest
41c3cc1a18 Csharpier 2025-12-03 12:05:16 -05:00
HeroponRikIBestest
1b1df86a11 Improve logic 2025-12-02 10:02:49 -05:00
HeroponRikIBestest
e0660e7775 Add tests 2025-12-02 09:55:24 -05:00
HeroponRikIBestest
99a6c4de88 Add archive-level IsEncrypted flag 2025-12-02 09:47:06 -05:00
Adam Hathcock
ffa765bd97 Merge pull request #1057 from adamhathcock/adam/add-copilot-instructions 2025-11-30 13:48:55 +00:00
Adam Hathcock
b1696524b3 Merge pull request #1058 from adamhathcock/copilot/sub-pr-1057 2025-11-30 13:48:31 +00:00
copilot-swe-agent[bot]
14d432e22d Pass progress as parameter to WriteTo/WriteToAsync instead of storing on archive
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-30 13:04:40 +00:00
copilot-swe-agent[bot]
6a37c55085 Consolidate agent instructions into AGENTS.md
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-30 12:52:22 +00:00
copilot-swe-agent[bot]
9c1c6fff9f Initial plan 2025-11-30 12:49:36 +00:00
Adam Hathcock
db8c6f4bcb first pass of instructions...consolidate? 2025-11-30 12:47:57 +00:00
Adam Hathcock
ff17ecda7d Merge pull request #1055 from adamhathcock/adam/vscode-fixes
add vscode config
2025-11-30 12:47:16 +00:00
Adam Hathcock
692058677c Merge pull request #1056 from adamhathcock/copilot/sub-pr-1055
Fix launch.json debug configurations to use net10.0
2025-11-30 12:41:38 +00:00
copilot-swe-agent[bot]
1e90d69912 Update launch.json to use net10.0 instead of net8.0
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-30 12:22:31 +00:00
copilot-swe-agent[bot]
64a1cc68e1 Initial plan 2025-11-30 12:20:37 +00:00
copilot-swe-agent[bot]
0fdf9c74a8 Address code review: Replace dynamic with IArchiveProgressInfo interface
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-30 12:07:17 +00:00
Adam Hathcock
20353f35ff add vscode config 2025-11-30 12:05:08 +00:00
copilot-swe-agent[bot]
e2df7894f9 Remove IArchiveExtractionListener and add IProgress support to Archive Entry extraction
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-30 12:00:54 +00:00
copilot-swe-agent[bot]
7af029b5de Address code review: properly handle zero-sized entries in progress reporting
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 17:48:50 +00:00
copilot-swe-agent[bot]
8fc5ca5a71 Unify progress reporting: remove IExtractionListener and add IProgress support for reading
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 17:40:10 +00:00
copilot-swe-agent[bot]
aa0356de9f Changes before error encountered
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 15:55:21 +00:00
Adam Hathcock
e44a43d2b1 Merge pull request #1054 from adamhathcock/copilot/fix-zipreader-directory-entry
Document ZipReader DirectoryEntry behavior and add verification test
2025-11-29 15:46:51 +00:00
Adam Hathcock
8997f00b9b Merge pull request #1049 from adamhathcock/copilot/drop-dotnet-6-support
Drop .NET 6, .NET Standard 2.0, .NET 4.8.1, add .NET 10 support
2025-11-29 15:46:27 +00:00
copilot-swe-agent[bot]
c5da416764 Apply code review feedback: improve documentation structure and add explicit DirectoryEntry case
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 15:39:36 +00:00
Adam Hathcock
840e58fc03 Update tests/SharpCompress.Test/Zip/ZipReaderTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-29 15:36:46 +00:00
copilot-swe-agent[bot]
7f911c5219 Add documentation about ZipReader directory and central directory handling
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 15:29:07 +00:00
copilot-swe-agent[bot]
a887390c23 Add multi-volume ZIP documentation to FORMATS.md
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 15:25:35 +00:00
copilot-swe-agent[bot]
f4dddcec8e Changes before error encountered
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 14:06:03 +00:00
copilot-swe-agent[bot]
0d9d82d7e6 Initial plan 2025-11-29 13:42:43 +00:00
copilot-swe-agent[bot]
3a6d24b1d9 Add ZStandard frame and dictionary types
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 13:36:01 +00:00
copilot-swe-agent[bot]
b9b159be4c Add ZStandard compression parameter types and enums
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 13:34:18 +00:00
copilot-swe-agent[bot]
40212083a5 Add core ZStandard infrastructure: UnsafeHelper, ThrowHelper, and Unsafe Methods
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 13:28:16 +00:00
copilot-swe-agent[bot]
d3428b066e Fix XML documentation comments in buffer structs
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 13:14:52 +00:00
copilot-swe-agent[bot]
94c64b2a45 Add initial ZStandard infrastructure types for ZstdSharp integration
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 13:11:19 +00:00
copilot-swe-agent[bot]
0d671a0bb2 Initial plan 2025-11-29 13:03:20 +00:00
Adam Hathcock
d34a47c148 update dependencies 2025-11-29 11:56:20 +00:00
copilot-swe-agent[bot]
5aa216bd21 Remove netstandard2.0 and net481 targets, keep net48, net8.0, net10.0
- Updated target frameworks to net48;net8.0;net10.0 only
- Removed netstandard2.0 and net481 package conditions
- Updated conditional compilation to use NETFRAMEWORK only
- Updated package description and README

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 11:42:05 +00:00
copilot-swe-agent[bot]
8af47548fe Fix .NET 10.0 formatting in README
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 11:04:54 +00:00
copilot-swe-agent[bot]
131bd2b7b8 Drop .NET 6 support and add .NET 10 support
- Updated SharpCompress.csproj target frameworks from net48;net481;netstandard2.0;net6.0;net8.0 to net48;net481;netstandard2.0;net8.0;net10.0
- Updated test and build projects to use .NET 10
- Updated global.json to .NET 10 SDK
- Updated CI workflow to use .NET 10
- Fixed deprecated Rfc2898DeriveBytes constructor for .NET 10 (SYSLIB0060)
- Updated package description and README to reflect new supported frameworks
- Updated package versions for .NET 10 compatibility

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-29 11:03:48 +00:00
copilot-swe-agent[bot]
1993673a22 Initial plan 2025-11-29 10:42:07 +00:00
Adam Hathcock
30e036f9ec Mark for 0.42.0 2025-11-28 13:24:03 +00:00
copilot-swe-agent[bot]
0f374b27cf Address code review: ProgressReportingStream now throws on writes
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-27 19:17:10 +00:00
copilot-swe-agent[bot]
0d487df61b Add IProgress support for compression operations with tests
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-27 19:15:10 +00:00
copilot-swe-agent[bot]
c082d4203b Changes before error encountered
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-27 16:58:32 +00:00
copilot-swe-agent[bot]
d4380b6bb6 Initial plan 2025-11-27 16:48:09 +00:00
Adam Hathcock
095c871174 Merge pull request #1043 from adamhathcock/copilot/fix-divide-by-zero-exception
Fix DivideByZeroException when compressing empty files with BZip2
2025-11-27 16:47:39 +00:00
copilot-swe-agent[bot]
6d73c5b295 Fix DivideByZeroException when using BZip2 with empty files
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-27 15:59:39 +00:00
copilot-swe-agent[bot]
cc4d28193c Initial plan 2025-11-27 15:53:13 +00:00
Adam Hathcock
fb76bd82f2 first commit of async reader 2025-11-26 08:09:20 +00:00
Adam Hathcock
3bdaba46a9 fmt 2025-11-25 15:39:43 +00:00
Adam Hathcock
9433e06b93 Merge pull request #1023 from adamhathcock/copilot/fix-zip64-validation-issue
Fix version mismatch between Local File Header and Central Directory File Header in Zip archives
2025-11-25 15:30:48 +00:00
copilot-swe-agent[bot]
a92aaa51d5 Remove ZipCompressionMethod.None from version 63 check
None (stored) compression only requires version 10/20, not version 63.
Version 63 is specifically for advanced compression methods like LZMA,
PPMd, BZip2, and ZStandard.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-25 14:54:13 +00:00
Adam Hathcock
7c3c94ed7f Add ArcReaderAsync tests 2025-11-25 14:44:03 +00:00
Adam Hathcock
d41908adeb fixes for clarity 2025-11-25 14:25:58 +00:00
Adam Hathcock
81ca15b567 Update src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 14:13:10 +00:00
Adam Hathcock
b81d0fd730 Merge pull request #1009 from adamhathcock/dependabot/nuget/AwesomeAssertions-9.3.0
Bump AwesomeAssertions from 9.2.1 to 9.3.0
2025-11-25 11:55:41 +00:00
Adam Hathcock
3a1bb187e8 Merge pull request #1031 from adamhathcock/dependabot/github_actions/actions/checkout-6
Bump actions/checkout from 5 to 6
2025-11-25 11:55:21 +00:00
Adam Hathcock
3fee14a070 Merge pull request #1035 from adamhathcock/adam/update-csharpier
Update csharpier and reformat
2025-11-25 11:54:56 +00:00
Adam Hathcock
5bf789ac65 Update csharpier and reformat 2025-11-25 11:50:21 +00:00
dependabot[bot]
be06049db3 Bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 09:20:23 +00:00
Adam Hathcock
a0435f6a60 Merge pull request #1030 from TwanVanDongen/master
Added buffer boundary tests.
2025-11-23 15:53:36 +00:00
Twan van Dongen
2321e2c90b Added buffer boundaty tests. Changed largefile to Alice29.txt as it's sufficient for the tests. 2025-11-22 12:32:25 +01:00
Adam Hathcock
97e98d8629 Merge pull request #1028 from TwanVanDongen/master
Buffer boundary tests
2025-11-21 08:35:54 +00:00
Twan van Dongen
d96e7362d2 Buffer boundary test for ARC's Squeezed method 2025-11-20 21:56:07 +01:00
Twan van Dongen
7dd46fe5ed More buffer boundary tests 2025-11-20 19:43:07 +01:00
Adam Hathcock
04c044cb2b Update tests/SharpCompress.Test/Zip/Zip64VersionConsistencyTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-19 15:49:55 +00:00
Adam Hathcock
cc10a12fbc Update tests/SharpCompress.Test/Zip/Zip64VersionConsistencyTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-19 15:49:27 +00:00
Adam Hathcock
8b0a1c699f Update tests/SharpCompress.Test/Zip/Zip64VersionConsistencyTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-19 15:49:17 +00:00
Adam Hathcock
15ca7c9807 Merge pull request #1025 from adamhathcock/copilot/fix-exception-disposing-rararchive
Fix ArgumentNullException when disposing RarArchive with damaged archives
2025-11-19 15:48:44 +00:00
Adam Hathcock
2b4da7e39b Merge pull request #1024 from adamhathcock/copilot/fix-memory-exhaustion-bug
Fix memory exhaustion in TAR header auto-detection
2025-11-19 15:33:52 +00:00
copilot-swe-agent[bot]
31f81f38af Fix null reference exception in UnpackV1.Unpack.Dispose()
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-19 15:16:18 +00:00
copilot-swe-agent[bot]
72cf77b7c7 Initial plan 2025-11-19 15:09:19 +00:00
copilot-swe-agent[bot]
0fe48c647e Enhance fix to handle LZMA/PPMd/BZip2/ZStandard compression methods
Also fixes pre-existing version mismatch for advanced compression methods that require version 63. Added tests for LZMA and PPMd to verify version consistency.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-19 11:29:43 +00:00
copilot-swe-agent[bot]
7b06652bff Add validation to prevent memory exhaustion in TAR long name headers
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-19 11:20:59 +00:00
copilot-swe-agent[bot]
434ce05416 Fix Zip64 version mismatch between LFH and CDFH
When UseZip64=true but files are small, ensure Central Directory File Header uses version 45 to match Local File Header. This fixes validation failures in System.IO.Packaging and other strict readers.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-11-19 11:14:06 +00:00
copilot-swe-agent[bot]
0698031ed4 Initial plan 2025-11-19 11:04:50 +00:00
copilot-swe-agent[bot]
51237a34eb Initial plan 2025-11-19 11:02:28 +00:00
Adam Hathcock
b8264a8131 Merge pull request #1004 from adamhathcock/adam/async-xz
Async XZ
2025-11-19 10:53:24 +00:00
Adam Hathcock
cad923018e Merge remote-tracking branch 'origin/master' into adam/async-xz 2025-11-19 09:56:01 +00:00
Adam Hathcock
db94b49941 fix mispellings 2025-11-19 09:55:43 +00:00
Adam Hathcock
72d15d9cbf Merge pull request #1019 from TwanVanDongen/master
ARJ's methods 1, 2 and 3 implemented for streaming
2025-11-18 13:41:49 +00:00
Twan van Dongen
e0186eadc0 Add buffer boundary tests for streaming decompression. Methods 1,2,3 still need fixing full streaming; exception now thrown to prevent corrupt output 2025-11-18 08:14:34 +01:00
Twan van Dongen
4cfa5b04af Included ARC and ARJ in readme 2025-11-14 15:57:22 +01:00
Twan van Dongen
f2c54b1f8b Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-11-14 15:43:51 +01:00
Twan van Dongen
d7d0bc6582 Missed formatting FilePart. 2025-11-14 15:43:47 +01:00
Twan
dd9dc2500b Merge branch 'adamhathcock:master' into master 2025-11-14 15:40:36 +01:00
Twan van Dongen
4efb109da8 Arj's methods CompressedMost (1), Compressed (2) and CompressedFaster (3) implemented. 2025-11-14 15:39:58 +01:00
Adam Hathcock
bcf9a6bdf1 Merge pull request #1017 from Morilli/fix-streamstack
Fix some IStreamStack and SharpCompressStream functions
2025-11-14 08:33:38 +00:00
Morilli
e3a25ecdc0 make formatting worse with csharpier 2025-11-14 03:54:26 +01:00
Morilli
783521928d fix SharpCompressStream BufferSize setter and Seek as well
the BufferSize setter was completely broken and trashed the `_internalPosition` value on set, for `Seek` this is just an off-by-one fix allowing seeking to immediately past the last byte in the buffer
2025-11-14 03:37:08 +01:00
Morilli
9a876abd31 fix IStreamStack.StackSeek with buffering streams 2025-11-14 03:37:08 +01:00
Morilli
97f58b412e Add test for StackSeek behavior 2025-11-14 03:37:08 +01:00
dependabot[bot]
4c61628078 Bump AwesomeAssertions from 9.2.1 to 9.3.0
---
updated-dependencies:
- dependency-name: AwesomeAssertions
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 11:57:30 +00:00
Adam Hathcock
99a8b0f750 Merge pull request #1007 from TwanVanDongen/master
ArjReader throws exception for password protected archives.
2025-11-06 09:58:24 +00:00
Twan van Dongen
a9017d7c25 ArjReader throws exception for password protected archives. 2025-11-06 09:32:12 +01:00
Adam Hathcock
d9e4b26648 Merge pull request #1006 from TwanVanDongen/master
ARJ multi-part archive handling improved
2025-11-05 08:37:54 +00:00
Twan van Dongen
0d03bafe49 Merg conflicts resolved 2025-11-05 08:19:30 +01:00
Twan
fee15a31f9 Merge branch 'adamhathcock:master' into master 2025-11-05 08:12:53 +01:00
Twan van Dongen
997d3910d4 CSharpier appliedArjReader thrown exception for multi-part archives. Method4 (decodefastest) refactored to support Stream. 2025-11-05 08:05:30 +01:00
Twan van Dongen
a3918cc0d7 ArjReader thrown exception for multi-part archives. Method4 (decodefastest) refactored to support Stream. 2025-11-05 08:02:20 +01:00
Adam Hathcock
f056986b07 Merge pull request #1005 from TwanVanDongen/master
Refactor SqueezeStream for CLS Compliance, Streaming, and Generic Test Coverage
2025-11-04 15:50:36 +00:00
Twan van Dongen
59c1f02f98 Still difficult to run CSharpier... 2025-11-02 19:23:30 +01:00
Twan van Dongen
3a71a2b1f8 Ran CSharpier. 2025-11-02 19:22:01 +01:00
Twan van Dongen
2ef1215b49 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-11-02 19:20:47 +01:00
Twan van Dongen
130ac83076 Revert "CSharpier...Refactors the SqueezeStream class to ensure full CLS compliance and proper stream behavior. It replaces the previous one-shot decoding logic with a true streaming implementation by piping Huffman-decoded output into the existing RunLength90Stream, enabling real-time decompression."
This reverts commit dd606a0702.
2025-11-02 19:20:34 +01:00
Twan van Dongen
dd606a0702 CSharpier...Refactors the SqueezeStream class to ensure full CLS compliance and proper stream behavior. It replaces the previous one-shot decoding logic with a true streaming implementation by piping Huffman-decoded output into the existing RunLength90Stream, enabling real-time decompression. 2025-11-02 19:15:17 +01:00
Twan van Dongen
84cd772f50 Refactors the SqueezeStream class to ensure full CLS compliance and proper stream behavior. It replaces the previous one-shot decoding logic with a true streaming implementation by piping Huffman-decoded output into the existing RunLength90Stream, enabling real-time decompression. 2025-11-02 19:09:59 +01:00
Adam Hathcock
fa1d7af22f Merge remote-tracking branch 'origin/master' into adam/async-xz 2025-11-01 10:35:22 +00:00
Adam Hathcock
a771ba3bc0 async tests 2025-11-01 10:35:07 +00:00
Adam Hathcock
8b612c658d Merge pull request #1003 from adamhathcock/adam/async-lzma
async lzma
2025-11-01 10:34:54 +00:00
Adam Hathcock
7dd0da5fd7 Merge branch 'adam/async-lzma' into adam/async-xz 2025-11-01 10:28:27 +00:00
Adam Hathcock
f7b3525c4e fix tests and fmt 2025-11-01 10:25:14 +00:00
Adam Hathcock
de83bdae48 Merge remote-tracking branch 'origin/master' into adam/async-lzma 2025-11-01 10:21:25 +00:00
Adam Hathcock
d90b610767 Merge pull request #994 from TwanVanDongen/master
Adding the ARJ (Archived by Robert Jung) format
2025-11-01 10:20:54 +00:00
Adam Hathcock
2d41de6b72 add async tests 2025-11-01 09:57:26 +00:00
Adam Hathcock
f391c3caf3 make an async code 2025-11-01 09:42:17 +00:00
Twan van Dongen
9bdf150676 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-10-31 16:17:26 +01:00
Twan van Dongen
0c199609eb CSharpier...Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-10-31 16:17:23 +01:00
Twan van Dongen
6eff9d3753 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-10-31 16:15:51 +01:00
Twan
7ab16457c7 Added ARJ's compressmion method4 (compressed fastest).
Refactored TestBase to support archives with mixed compression algorithms.Merge branch 'adamhathcock:master' into master
2025-10-31 16:14:48 +01:00
Twan
e7ad8132b5 Merge branch 'adamhathcock:master' into master 2025-10-31 14:33:14 +01:00
Adam Hathcock
da87e45534 add async xzstream 2025-10-31 11:57:49 +00:00
Adam Hathcock
2ffaef5563 async xzblock 2025-10-31 11:47:27 +00:00
Adam Hathcock
55cb350d2c remove needless variable 2025-10-31 11:44:32 +00:00
Adam Hathcock
7fa271a1b4 fix ILLink 2025-10-31 11:43:35 +00:00
Adam Hathcock
c53ca372f2 don't use pools in tests 2025-10-31 11:39:57 +00:00
Adam Hathcock
75bc8501f4 Merge pull request #997 from adamhathcock/copilot/fix-ziparchive-linux-issue
Fix ArchiveFactory.Open double-wrapping causing "Cannot determine compressed stream type" on Linux
2025-10-31 11:24:59 +00:00
Adam Hathcock
1e22b47fe1 some fixes 2025-10-31 11:23:30 +00:00
Adam Hathcock
74e2dca207 fmt 2025-10-31 11:15:42 +00:00
Adam Hathcock
a669de24b7 Merge remote-tracking branch 'origin/master' into adam/async-lzma 2025-10-31 11:13:17 +00:00
Adam Hathcock
e1e9c449e9 use proper async versions 2025-10-31 11:12:46 +00:00
Adam Hathcock
60e1dc0239 review fixes 2025-10-31 11:10:55 +00:00
Adam Hathcock
10eb94fd82 Merge pull request #1002 from adamhathcock/adam/async-bzip2
async bzip2 and add
2025-10-31 11:09:39 +00:00
Adam Hathcock
ccc8587e5f review fixes 2025-10-31 10:55:33 +00:00
Adam Hathcock
53c96193c1 format 2025-10-30 16:40:59 +00:00
Adam Hathcock
d4f11e00b1 some more async changes 2025-10-30 16:31:45 +00:00
Adam Hathcock
321233b82c some async implementations 2025-10-30 15:08:57 +00:00
Adam Hathcock
eb188051d4 fmt 2025-10-30 14:53:11 +00:00
Adam Hathcock
a136084e11 add adc async 2025-10-30 14:52:51 +00:00
Adam Hathcock
bc06f3179d add basics for async bzip2 2025-10-30 14:42:46 +00:00
Adam Hathcock
ee84d971b2 Merge remote-tracking branch 'origin/master' into copilot/fix-ziparchive-linux-issue
# Conflicts:
#	src/SharpCompress/packages.lock.json
2025-10-30 14:30:31 +00:00
Twan
264d80ef4c Merge branch 'master' into master 2025-10-30 07:53:09 +01:00
Adam Hathcock
dba68187ac Merge pull request #996 from adamhathcock/adam/async-rar-ai 2025-10-29 14:26:15 +00:00
Adam Hathcock
ca4a1936b3 Merge remote-tracking branch 'origin/adam/async-rar-ai' into adam/async-rar-ai 2025-10-29 14:11:02 +00:00
Adam Hathcock
77c8d31a90 Merge pull request #1000 from adamhathcock/copilot/sub-pr-996
Fix Windows test failures due to ArrayPool buffer sizing
2025-10-29 14:10:39 +00:00
Adam Hathcock
ab7196f86c some review fixes 2025-10-29 14:07:12 +00:00
copilot-swe-agent[bot]
88b3a66bf9 Fix Windows test failures in SharpCompressStreamTests
ArrayPool.Rent() can return buffers larger than requested. The tests were using test.Length (the actual buffer size) instead of the requested size (0x1000), causing failures on Windows where ArrayPool returns larger buffers than on Linux.

Fixed by:
- Using explicit size (0x1000) instead of test.Length in Read() calls
- Using test.Take(0x1000) instead of test when comparing arrays

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-29 13:40:44 +00:00
copilot-swe-agent[bot]
ea77666b4a Final verification: All tests pass, no security issues
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-29 13:38:38 +00:00
copilot-swe-agent[bot]
db98e5f39b Fix ArchiveFactory.Open to avoid double-wrapping SharpCompressStream
Use SharpCompressStream.Create instead of constructor to properly handle
streams that are already wrapped. This prevents potential buffering issues
when opening ZIP files, particularly on Linux systems.

Added tests to verify both raw FileStream and pre-wrapped stream scenarios.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-29 13:34:53 +00:00
copilot-swe-agent[bot]
df59c5cb9d Plan: Fix potential ZipArchive.IsZipFile failure on Linux
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-29 13:26:00 +00:00
copilot-swe-agent[bot]
e786e95358 Initial plan 2025-10-29 13:25:48 +00:00
Adam Hathcock
75ada5623c add async tests for compress stream 2025-10-29 13:23:50 +00:00
copilot-swe-agent[bot]
ad5c655c45 Initial plan 2025-10-29 13:09:05 +00:00
Adam Hathcock
65e607454e add async for UnpWriteBufAsync and remove comments 2025-10-29 13:07:43 +00:00
Adam Hathcock
f238be6003 add arraypool usage in init 2025-10-29 10:35:03 +00:00
Adam Hathcock
dc31e4c5fa fmt 2025-10-29 10:27:30 +00:00
Adam Hathcock
665d8cd266 ran out of tokens, things work but need one more conversion 2025-10-29 10:23:57 +00:00
Adam Hathcock
8324114e84 remove unused code 2025-10-29 10:11:34 +00:00
Adam Hathcock
b83e6ee4ce fix async usage 2025-10-29 09:55:11 +00:00
Adam Hathcock
58bab0d310 async unpack2.0 2025-10-29 09:53:14 +00:00
Adam Hathcock
1af51aaaba async unpack1.5 2025-10-29 09:50:12 +00:00
Adam Hathcock
a09327b831 unpack50async 2025-10-29 09:46:10 +00:00
Adam Hathcock
16543bf74c async UnpReadBufAsync 2025-10-29 09:38:55 +00:00
Adam Hathcock
aa4cd373ac added more async methods 2025-10-29 09:28:34 +00:00
Adam Hathcock
351e294362 convert unpack15 and unpack20 2025-10-29 09:23:42 +00:00
Adam Hathcock
a0c5b1cd9d add archive tests 2025-10-29 09:08:08 +00:00
Adam Hathcock
df2ed1e584 fix RarStream 2025-10-29 09:00:23 +00:00
Adam Hathcock
b354f7a3a5 fix logic mistake 2025-10-29 08:47:18 +00:00
Adam Hathcock
bb53d1e1c6 entrystream fixes and fmt 2025-10-29 08:41:05 +00:00
Twan van Dongen
2aabd8d0e1 Initial implementation of the ARJ (Archived by Robert Jung) format, supporting 'store' for single file archives. Multi-file archives and all compression algorithms still require implementations. 2025-10-28 20:38:29 +01:00
Adam Hathcock
aca97c2c6c add rarcrc tests 2025-10-28 16:48:05 +00:00
Adam Hathcock
8e7d959cf4 add async creations 2025-10-28 16:07:16 +00:00
Adam Hathcock
b23f031db9 add async reads 2025-10-28 15:52:18 +00:00
Adam Hathcock
1ba529a9d5 first pass of async files 2025-10-28 15:29:41 +00:00
Adam Hathcock
3d29c183ef basic async usage 2025-10-28 15:00:11 +00:00
Adam Hathcock
8a108b590d Merge pull request #993 from adamhathcock/adam/macos-fixes
make test linux only
2025-10-28 14:52:05 +00:00
Adam Hathcock
bca0f67344 make test linux only 2025-10-28 12:18:05 +00:00
Adam Hathcock
f3dad51134 Merge pull request #991 from adamhathcock/async-reader-methods
Add more Async tests and complete Zip tests
2025-10-28 11:50:03 +00:00
Adam Hathcock
f51840829c Merge branch 'master' into async-reader-methods 2025-10-28 11:39:35 +00:00
Adam Hathcock
aa1c0d0870 Merge pull request #988 from adamhathcock/copilot/fix-file-write-error
Fix extraction failure on Windows due to case-sensitive path comparison
2025-10-28 11:39:17 +00:00
Adam Hathcock
dee5ee6589 Merge pull request #989 from adamhathcock/copilot/add-support-empty-directories
Add support for empty directory entries in archives
2025-10-28 11:38:41 +00:00
Adam Hathcock
b799f479c4 Merge branch 'master' into copilot/add-support-empty-directories 2025-10-28 11:35:56 +00:00
copilot-swe-agent[bot]
b4352fefa5 Fix code formatting per CSharpier standards
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 11:32:39 +00:00
Adam Hathcock
77d06fb60e Merge branch 'master' into copilot/fix-file-write-error 2025-10-28 11:32:05 +00:00
Adam Hathcock
00b647457c Merge pull request #990 from adamhathcock/copilot/add-common-exception-type
Make all library exceptions inherit from SharpCompressException
2025-10-28 11:31:32 +00:00
Adam Hathcock
153d10a35c add async to forward only streams 2025-10-28 11:30:12 +00:00
Adam Hathcock
06713c641e async deflate 64 2025-10-28 11:26:31 +00:00
copilot-swe-agent[bot]
210978ec2d Format code with CSharpier
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 11:13:51 +00:00
Adam Hathcock
42f7d43139 enable zip64 tests that pass 2025-10-28 11:07:53 +00:00
Adam Hathcock
19967f5ad7 allow forward only write 2025-10-28 11:01:27 +00:00
Adam Hathcock
a1de3eb47d add async tests and clean up deflate64stream 2025-10-28 11:01:12 +00:00
copilot-swe-agent[bot]
e88841bdec Add support for empty directory entries in archives
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:34:03 +00:00
copilot-swe-agent[bot]
c8e4915f8e Final progress report
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:29:36 +00:00
copilot-swe-agent[bot]
a93a3f0598 Address code review feedback - fix formatting
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:26:31 +00:00
copilot-swe-agent[bot]
084f81fc8d Format code with CSharpier 2025-10-28 10:23:57 +00:00
copilot-swe-agent[bot]
d148f36e87 Add support for empty directory entries in archives
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:22:58 +00:00
copilot-swe-agent[bot]
150d9c35b7 Complete fix for case-sensitive path comparison on Windows
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:22:56 +00:00
copilot-swe-agent[bot]
e11198616e Address code review feedback: use RuntimeInformation for platform detection
- Replace Environment.OSVersion.Platform with RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
- Clarify test comment about platform-specific behavior
- Add using System.Runtime.InteropServices for RuntimeInformation

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:20:05 +00:00
copilot-swe-agent[bot]
2f27f1e6f9 Complete exception hierarchy implementation
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:18:42 +00:00
copilot-swe-agent[bot]
5392ca9794 Fix case-sensitive path comparison on Windows for file extraction
- Add PathComparison property that uses OrdinalIgnoreCase on Windows and Ordinal on Unix
- Update all path comparison checks in ExtractionMethods to use PathComparison
- Add comprehensive tests for extraction with case-insensitive paths
- Ensure security check for path traversal still works correctly

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:16:07 +00:00
copilot-swe-agent[bot]
46672eb583 Update exceptions to inherit from SharpCompressException
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-28 10:15:40 +00:00
Adam Hathcock
79653eee80 Merge remote-tracking branch 'origin/master' into async-reader-methods 2025-10-28 10:11:11 +00:00
Adam Hathcock
16ad86c52a add async implementations to readonlysubstream 2025-10-28 10:09:46 +00:00
copilot-swe-agent[bot]
6b7c6be5f5 Initial plan 2025-10-28 10:02:58 +00:00
copilot-swe-agent[bot]
fda1c2cc79 Initial plan 2025-10-28 10:01:37 +00:00
copilot-swe-agent[bot]
ef2fee0ee3 Initial plan 2025-10-28 10:00:50 +00:00
Adam Hathcock
e287d0811d minor clean up 2025-10-28 09:58:01 +00:00
Adam Hathcock
a7164f3c9f Merge pull request #987 from adamhathcock/copilot/fix-gzip-extract-not-supported-exception
Fix GZip extraction NotSupportedException for non-seekable streams
2025-10-27 14:26:04 +00:00
Adam Hathcock
c55060039a Merge branch 'master' into copilot/fix-gzip-extract-not-supported-exception 2025-10-27 14:21:49 +00:00
Adam Hathcock
c68d8deddd add async tests 2025-10-27 12:34:24 +00:00
Adam Hathcock
f6eabc5db1 Merge remote-tracking branch 'origin/master' into async-reader-methods
# Conflicts:
#	src/SharpCompress/packages.lock.json
2025-10-27 12:24:14 +00:00
Adam Hathcock
72d5884db6 added async reader overloads 2025-10-27 12:23:54 +00:00
Adam Hathcock
3595c89c79 Merge pull request #983 from adamhathcock/copilot/set-up-copilot-instructions
Configure Copilot coding agent instructions for SharpCompress
2025-10-27 12:13:50 +00:00
Adam Hathcock
9ebbc718c5 Merge branch 'master' into copilot/fix-gzip-extract-not-supported-exception 2025-10-27 12:11:32 +00:00
Adam Hathcock
e862480b86 Merge branch 'master' into copilot/set-up-copilot-instructions 2025-10-27 12:09:55 +00:00
Adam Hathcock
1f3d8fe6f1 Merge pull request #986 from adamhathcock/copilot/fix-compressiontype-none-bug
Support CompressionType.None for uncompressed 7z files
2025-10-27 12:06:52 +00:00
Adam Hathcock
41ae036ab4 Merge branch 'master' into copilot/set-up-copilot-instructions 2025-10-27 12:04:58 +00:00
copilot-swe-agent[bot]
588d176b96 Final verification - all tests pass
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:15:16 +00:00
copilot-swe-agent[bot]
f8697120a0 Add support for CompressionType.None for uncompressed 7z files
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:11:38 +00:00
copilot-swe-agent[bot]
1a767105e6 Add explanatory comment for EntryStartPosition initialization
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:09:52 +00:00
copilot-swe-agent[bot]
4067b6ed2c Fix GZip extraction for non-seekable streams
- Modified GZipFilePart to only access stream.Position when stream.CanSeek is true
- Modified GZipArchiveEntry.OpenEntryStream to check CanSeek before accessing Position
- Added test case GZip_Archive_NonSeekableStream to verify non-seekable stream support
- All existing tests pass

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:08:38 +00:00
copilot-swe-agent[bot]
b272dbfd1f Clarify CSharpier should be run from project root
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:07:02 +00:00
copilot-swe-agent[bot]
48be7bbf86 Correct formatting instructions to use CSharpier
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:05:47 +00:00
copilot-swe-agent[bot]
51e22cea71 Initial plan for fixing GZip non-seekable stream support
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:02:53 +00:00
copilot-swe-agent[bot]
2241e27e68 Initial exploration: Understanding the issue
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:02:29 +00:00
copilot-swe-agent[bot]
11c90ae879 Update Copilot configuration to reflect actual project setup
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 11:00:02 +00:00
copilot-swe-agent[bot]
cf55125202 Initial plan 2025-10-27 10:58:07 +00:00
copilot-swe-agent[bot]
9cefb85905 Enhance AGENTS.md with SharpCompress-specific guidelines
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 10:57:22 +00:00
copilot-swe-agent[bot]
fc672da0e0 Initial plan 2025-10-27 10:55:53 +00:00
Adam Hathcock
25b297b142 Merge pull request #980 from adamhathcock/async-gzip-tests
adds more async tests and overloads to make things writable and async
2025-10-27 10:54:42 +00:00
Adam Hathcock
ab03c12fa8 add more tests 2025-10-27 10:52:03 +00:00
copilot-swe-agent[bot]
3095c805ad Initial plan 2025-10-27 10:48:24 +00:00
Adam Hathcock
9c18daafb8 Merge remote-tracking branch 'origin/async-gzip-tests' into async-gzip-tests 2025-10-27 10:46:15 +00:00
Adam Hathcock
16182417fb add tar specific tests 2025-10-27 10:46:08 +00:00
Adam Hathcock
9af35201e4 Merge branch 'master' into async-gzip-tests 2025-10-27 10:31:51 +00:00
Adam Hathcock
f21b982955 adds more async tests and overloads to make things writable and async 2025-10-27 10:31:10 +00:00
Adam Hathcock
b3a20d05c5 Merge pull request #978 from adamhathcock/copilot/enhance-stream-io-async-support
Add comprehensive async/await support for Stream I/O operations
2025-10-27 10:23:08 +00:00
Adam Hathcock
4cd024a2b2 Merge remote-tracking branch 'origin/master' into copilot/enhance-stream-io-async-support 2025-10-27 10:20:06 +00:00
Adam Hathcock
63d08ebfd2 update agents 2025-10-27 10:19:57 +00:00
Adam Hathcock
c696197b03 formatting 2025-10-27 10:19:24 +00:00
Adam Hathcock
738a72228b added fixes and more async tests 2025-10-27 10:15:06 +00:00
Adam Hathcock
90641f4488 Merge pull request #979 from adamhathcock/dependabot/github_actions/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-10-27 10:06:02 +00:00
Adam Hathcock
a4cc7eaf9b fully use async for zlibbase 2025-10-27 09:51:39 +00:00
Adam Hathcock
fdca728fdc add some dispose async 2025-10-27 09:47:15 +00:00
dependabot[bot]
d2c4ae8cdf Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 09:43:01 +00:00
Adam Hathcock
f3d3ac30a6 add gubbins 2025-10-27 09:39:08 +00:00
Adam Hathcock
f8cc4ade8a format 2025-10-27 09:37:00 +00:00
copilot-swe-agent[bot]
b3975b7bbd Add async tests for EntryStream and compression streams
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 09:28:34 +00:00
copilot-swe-agent[bot]
4f1b61f5bc Add async support to DeflateStream and GZipStream
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 09:20:37 +00:00
copilot-swe-agent[bot]
beeb37b4fd Add async support to EntryStream, ZlibStream, and ZlibBaseStream
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 09:11:29 +00:00
copilot-swe-agent[bot]
43aa2bad22 Integrate async/await support from PR #976 as baseline
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-27 09:00:38 +00:00
copilot-swe-agent[bot]
1b2ba921bb Initial plan 2025-10-27 08:48:01 +00:00
Adam Hathcock
f543da0ea8 Merge pull request #977 from adamhathcock/copilot/add-copilot-agent-config
Add Copilot agent manifest and usage documentation
2025-10-27 08:42:20 +00:00
copilot-swe-agent[bot]
e60c9efa84 Add copilot agent configuration and documentation
- Create .github/agents/copilot-agent.yml with agent manifest
- Replace AGENTS.md with agent usage and command documentation

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2025-10-25 18:16:47 +00:00
copilot-swe-agent[bot]
c52fc6f240 Initial plan 2025-10-25 18:12:45 +00:00
Adam Hathcock
ee136b024a Merge pull request #974 from adamhathcock/adam/enable-agent
chore: add Copilot coding agent config and CI workflow
2025-10-25 16:09:51 +01:00
Adam Hathcock
699bc5f34b chore: add Copilot coding agent config and CI workflow 2025-10-25 16:05:09 +01:00
Adam Hathcock
9eed8e842c Merge pull request #972 from TwanVanDongen/master
Handle vendor-specific and malformed ZIP extra fields safely
2025-10-25 13:53:10 +01:00
Twan van Dongen
6d652a12ee And again forgot to apply CSharpierAdds bounds checks to prevent exceptions when extra fields are truncated or non-standard (e.g., 0x4341 "AC"/ARC0). Stops parsing gracefully, allowing other fields to be processed. 2025-10-24 17:18:37 +02:00
Adam Hathcock
e043e06656 Merge pull request #969 from adamhathcock/adam/perf
Add JB perf testing project.
2025-10-23 14:34:43 +01:00
Adam Hathcock
14b52599f4 Update src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 14:20:54 +01:00
Adam Hathcock
e3e2c0c567 Update tests/SharpCompress.Performance/LargeMemoryStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 14:19:16 +01:00
Adam Hathcock
4fc5d60f03 reduce visibility 2025-10-23 14:16:39 +01:00
Adam Hathcock
c37a9e0f82 Merge remote-tracking branch 'origin/adam/perf' into adam/perf 2025-10-23 13:50:31 +01:00
Adam Hathcock
fed17ebb96 fmt 2025-10-23 13:50:07 +01:00
Adam Hathcock
eeac678872 More usage of pool and better copy 2025-10-23 13:49:54 +01:00
Adam Hathcock
f9ed0f2df9 Update tests/SharpCompress.Performance/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 11:47:42 +01:00
Adam Hathcock
0ddbacac85 Update src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-23 11:47:27 +01:00
Adam Hathcock
f0d28aa5cf fmt 2025-10-23 11:43:38 +01:00
Adam Hathcock
cc84f6fee4 more making rar faster 2025-10-23 11:43:21 +01:00
Adam Hathcock
00e6eef369 used AI to optimize some copys and shifting 2025-10-23 11:18:50 +01:00
Adam Hathcock
1ae71907bc don't need to clear everything 2025-10-23 10:53:54 +01:00
Adam Hathcock
3ff688fba2 clear and null check 2025-10-23 10:48:18 +01:00
Adam Hathcock
bb59b3d456 add pool to LZMA out window 2025-10-23 09:54:52 +01:00
Adam Hathcock
186ea74ada add some fixes for rar to pool memory 2025-10-23 09:40:15 +01:00
Adam Hathcock
c108f2dcf3 add perf testing project using JB memory and cpu 2025-10-23 09:39:57 +01:00
Adam Hathcock
4cca232d83 Merge pull request #959 from adamhathcock/adam/xz-wrapped-often
Removed wrappers that weren't needed (probably)
2025-10-22 11:54:47 +01:00
Adam Hathcock
1db511e9cb Merge branch 'master' into adam/xz-wrapped-often 2025-10-22 11:51:46 +01:00
Adam Hathcock
76afa7d3bf Merge pull request #968 from adamhathcock/adam/rework-deps
rework dependencies to be correct for frameworks and update
2025-10-22 11:51:30 +01:00
Adam Hathcock
3513f7b1cd Update src/SharpCompress/SharpCompress.csproj
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-22 10:51:12 +01:00
Adam Hathcock
4531fe39e6 Merge branch 'master' into adam/rework-deps 2025-10-22 10:48:16 +01:00
Adam Hathcock
8d276a85bc rework dependencies to be correct for frameworks and update 2025-10-22 10:47:43 +01:00
Adam Hathcock
5f0d042bc3 Merge pull request #967 from adamhathcock/adam/reduce-custom-utilities
Reduce custom utilities for arrays/bytes
2025-10-22 10:41:10 +01:00
Adam Hathcock
408f07e3c4 Merge branch 'master' into adam/reduce-custom-utilities 2025-10-22 10:38:01 +01:00
Adam Hathcock
d1a540c90c use windows instead of skippable fact 2025-10-22 10:32:47 +01:00
Adam Hathcock
00df8e930e add windows only compile constant 2025-10-22 10:30:40 +01:00
Adam Hathcock
3b768b1b77 Merge pull request #961 from adamhathcock/dependabot/nuget/AwesomeAssertions-9.2.1
Bump AwesomeAssertions from 9.2.0 to 9.2.1
2025-10-22 10:25:01 +01:00
Adam Hathcock
42a7ececa0 Merge branch 'master' into adam/xz-wrapped-often 2025-10-22 10:22:36 +01:00
Adam Hathcock
e8867de049 Merge branch 'master' into dependabot/nuget/AwesomeAssertions-9.2.1 2025-10-22 10:21:59 +01:00
Adam Hathcock
a1dfa3dfa3 xplat tests for path characters 2025-10-22 10:21:22 +01:00
Adam Hathcock
83917d4f79 Merge remote-tracking branch 'origin/master' into adam/reduce-custom-utilities 2025-10-22 10:17:20 +01:00
Adam Hathcock
513cd4f905 some AI suggestions 2025-10-22 10:16:45 +01:00
Adam Hathcock
eda0309df3 Merge pull request #966 from adamhathcock/adam/reduce-stackalloc
Remove a dynamically created stackalloc
2025-10-22 10:13:14 +01:00
Adam Hathcock
74e27c028e fix the span length 2025-10-22 10:10:07 +01:00
Adam Hathcock
36c06c4089 ugh, this is used because it shadows a field 2025-10-22 09:32:19 +01:00
Adam Hathcock
249b8a9cdd add AI generated tests 2025-10-22 09:28:07 +01:00
Adam Hathcock
62bee15f00 fmt 2025-10-22 09:19:30 +01:00
Adam Hathcock
d8797b69e4 remove do while 2025-10-22 09:19:09 +01:00
Adam Hathcock
084fe72b02 Consolidate not null 2025-10-22 09:17:13 +01:00
Adam Hathcock
c823acaa3f optimize ReadFully and Skip 2025-10-22 09:10:16 +01:00
Adam Hathcock
e0d6cd9cb7 Try to reduce custom functions for array/byte management 2025-10-22 09:00:21 +01:00
Adam Hathcock
01021e102b remove some extra stackallocs 2025-10-22 08:36:03 +01:00
Adam Hathcock
6de738ff17 reduce dynamic stackallocs in unpackv1 2025-10-22 08:32:19 +01:00
Adam Hathcock
c0612547eb Merge pull request #964 from adamhathcock/adam/extract-all-solid-only
Only allow extract all on archives that are solid (some rars and 7zip only)
2025-10-21 14:08:23 +01:00
Adam Hathcock
e960907698 Update src/SharpCompress/Archives/AbstractArchive.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-21 13:55:56 +01:00
Adam Hathcock
84e03b1b27 Allow 7zip files of all sizes? 2025-10-21 10:28:58 +01:00
Adam Hathcock
f1a80da34b fix tests that use extract all wrongly 2025-10-21 09:56:29 +01:00
Adam Hathcock
5a5a55e556 fmt 2025-10-21 09:22:35 +01:00
Adam Hathcock
e1f132b45b Only allow extract all on archives that are solid (some rars and 7zip only) 2025-10-21 09:21:46 +01:00
dependabot[bot]
087011aede Bump AwesomeAssertions from 9.2.0 to 9.2.1
---
updated-dependencies:
- dependency-name: AwesomeAssertions
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 10:44:17 +00:00
Adam Hathcock
1430bf9b31 fmt 2025-10-15 09:54:13 +01:00
Adam Hathcock
4e5de817ef Removed too many wrappers
# Conflicts:
#	src/SharpCompress/Compressors/Xz/XZIndex.cs
2025-10-15 09:53:46 +01:00
Adam Hathcock
5d6b94f8c3 Merge pull request #952 from adamhathcock/dependabot/github_actions/actions/checkout-5
Bump actions/checkout from 4 to 5
2025-10-14 08:25:53 +01:00
Adam Hathcock
8dfbe56f42 Merge branch 'master' into dependabot/github_actions/actions/checkout-5 2025-10-14 08:23:18 +01:00
Adam Hathcock
df79d983d7 Merge pull request #957 from adamhathcock/dependabot/github_actions/actions/setup-dotnet-5
Bump actions/setup-dotnet from 4 to 5
2025-10-14 08:22:47 +01:00
dependabot[bot]
6c23a28826 Bump actions/setup-dotnet from 4 to 5
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 16:21:25 +00:00
dependabot[bot]
f72289570a Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 16:12:51 +00:00
Adam Hathcock
51bc9dc20e Merge pull request #950 from adamhathcock/adamhathcock-patch-1
Configure Dependabot for NuGet updates
2025-10-13 16:52:07 +01:00
Adam Hathcock
e45ac6bfa9 Update .github/dependabot.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-13 16:48:55 +01:00
Adam Hathcock
44d1cbdb0c Configure Dependabot for NuGet updates
Added NuGet package ecosystem configuration for Dependabot.
2025-10-13 16:47:46 +01:00
Adam Hathcock
3fa7e854d3 Merge pull request #948 from adamhathcock/adam/update-0410
update to 0.41.0 and change symbols type
2025-10-13 12:32:54 +01:00
Adam Hathcock
0f5c080be6 update to 0.41.0 and change symbols type 2025-10-13 12:29:02 +01:00
Adam Hathcock
871009ef8d Merge pull request #947 from adamhathcock/adam/update-deps
Update dependencies and csharpier
2025-10-13 12:13:51 +01:00
Adam Hathcock
89a565c6c4 format 2025-10-13 12:10:42 +01:00
Adam Hathcock
6ed60e4d5f adjust Microsoft.NETFramework.ReferenceAssemblies 2025-10-13 12:08:39 +01:00
Adam Hathcock
4dab1df3ae adjust usage of sourcelink 2025-10-13 12:06:34 +01:00
Adam Hathcock
7b7aa2cdf0 Merge remote-tracking branch 'origin/master' into adam/update-deps 2025-10-13 11:56:50 +01:00
Adam Hathcock
d1e1a65f32 add agents file 2025-10-13 11:55:41 +01:00
Adam Hathcock
9d332b4ac5 add agents file 2025-10-13 11:52:18 +01:00
Adam Hathcock
fc2462e281 Update dependencies and csharpier 2025-10-13 10:40:43 +01:00
Adam Hathcock
fb2cddabf0 Merge pull request #945 from mitchcapper/archive_extension_hinting_pr
Extension hinting for ReaderFactory for better first try factory success
2025-09-29 09:02:11 +01:00
Mitch Capper
33481a9465 Extension hinting for ReaderFactory for better first try factory success
Also used by TarFactory to hint what compressiontype to attempt first
2025-09-24 00:04:07 -07:00
Adam Hathcock
45de87cb97 Merge pull request #943 from mitchcapper/zstandard_reading_pr
ZStandard tar support
2025-09-23 13:34:26 +01:00
Mitch Capper
553c533ada ZStandard tar support 2025-09-23 03:26:33 -07:00
Adam Hathcock
634e562b93 Merge pull request #935 from Nanook/bugfix/StreamBufferFix
Rewind buffer fix for directory extract.
2025-08-22 14:08:39 +01:00
Adam Hathcock
c789ead590 Merge branch 'master' into bugfix/StreamBufferFix 2025-08-22 14:05:35 +01:00
Adam Hathcock
d23560a441 Merge pull request #939 from Morilli/fix-winaescryptostream-dispose
Fix WinzipAesCryptoStream potentially not getting disposed
2025-08-22 14:03:06 +01:00
Morilli
9f306966db Adjust logic in CreateDecompressionStream to not wrap the returned stream
a ReadOnlySubStream never disposes its passes in stream which is problematic when that stream needs to be disposed. It's hard to tell who exactly has ownership over which stream here, but I'll just assume that whatever stream is passed in here should be disposed.
2025-08-21 20:08:57 +02:00
Morilli
8eea2cef97 add failing test 2025-08-21 20:08:34 +02:00
Nanook
3abbb89c2e Comment typo edit. 2025-08-01 21:50:36 +01:00
Nanook
76de7d54c7 Rewind buffer fix for directory extract. 2025-08-01 21:47:09 +01:00
Adam Hathcock
35aee6e066 Merge pull request #934 from Nanook/feature/zstd_zip_writing
Zip ZStandard Writing with tests. Level support.
2025-07-24 08:24:32 +01:00
Nanook
8a0152fe7c Fixed up test issue after copilot "fixes" :S. 2025-07-24 01:33:18 +01:00
Nanook
7769435fc8 CSharpier fixes after copilot tweaks. 2025-07-24 01:31:30 +01:00
Nanook
ae311ea66e Update tests/SharpCompress.Test/Zip/TestPseudoTextStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-24 01:28:56 +01:00
Nanook
d15816f162 Update tests/SharpCompress.Test/Zip/TestPseudoTextStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-24 01:28:40 +01:00
Nanook
5cbb31c559 Update tests/SharpCompress.Test/Zip/TestPseudoTextStream.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-24 01:28:23 +01:00
Nanook
b7f5b36f2b Update src/SharpCompress/Writers/Zip/ZipWriter.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-24 01:28:11 +01:00
Nanook
e9dd413de6 CSharpier formatting. 2025-07-24 00:46:09 +01:00
Nanook
c5de3d8cc1 Zip ZStandard Writing with tests. Level support. 2025-07-24 00:23:55 +01:00
Adam Hathcock
624c385e27 Merge pull request #930 from Nanook/feature/StreamStack
Added IStreamStack for debugging and configurable buffer management. …
2025-07-23 08:48:58 +01:00
Adam Hathcock
893890c985 Merge branch 'master' into feature/StreamStack 2025-07-23 08:46:16 +01:00
Adam Hathcock
e12efc8b52 Merge pull request #933 from Morilli/zipentry-attribute
Implement `Attrib` for `ZipEntry`
2025-07-23 08:45:04 +01:00
Morilli
015dfa41b1 implement Attrib for ZipEntrys 2025-07-22 20:12:22 +02:00
Morilli
5e72ce5fbe add failing test 2025-07-22 20:11:13 +02:00
Adam Hathcock
236e653176 Merge branch 'master' into feature/StreamStack 2025-07-22 11:55:57 +01:00
Adam Hathcock
3946c3ba03 Merge pull request #931 from SimonCahill/feat/add-throw-on-unseekable-stream
Added ArgumentException to Archive.Open implementations
2025-07-22 11:54:23 +01:00
Adam Hathcock
5bdd39e6eb Merge branch 'master' into feat/add-throw-on-unseekable-stream 2025-07-22 11:50:04 +01:00
Adam Hathcock
46267c0531 Merge pull request #929 from Morilli/fix-zipentry-comment
Fix zipentry comment implementation
2025-07-22 11:49:12 +01:00
Adam Hathcock
7b96eb7704 Merge pull request #928 from Morilli/fix-dotsettings
fix DotSettings options to conform to current code style and editorconfig
2025-07-22 11:47:36 +01:00
Nanook
60d5955101 Final tidy. 2025-07-22 00:12:30 +01:00
Nanook
587675e488 Fixed some missing features caused by merging an earlier branch than required. 2025-07-21 23:45:57 +01:00
Simon Cahill
c0ae319c63 Reverted debug change 2025-07-21 15:41:33 +02:00
Simon Cahill
d810f8d8db Reverted back; I don't know how this file changed 2025-07-21 15:38:14 +02:00
Simon Cahill
a88390a546 Added ArgumentException which is thrown when a non-seekable Stream instance is passed 2025-07-21 15:34:03 +02:00
Nanook
8575e5615d Formatting fix. 2025-07-20 19:18:31 +01:00
Nanook
5fe9516c09 Various copilot suggestions. Tests still passing. 2025-07-20 19:16:11 +01:00
Nanook
938775789d Formated with Sharpier. 2025-07-20 18:11:37 +01:00
Nanook
f37bebe51f Merge branch 'master' into feature/StreamStack 2025-07-20 17:46:28 +01:00
Nanook
21f14cd3f2 Added IStreamStack for debugging and configurable buffer management. Added SharpCompressStream to consolodate streams to help simplify debugging. All unit tests passing. 2025-07-20 17:35:22 +01:00
Morilli
4e7baeb2c9 fix zipentry comment being lost after reading local entry header 2025-07-19 19:56:41 +02:00
Morilli
d78a682dd8 add failing test 2025-07-19 19:56:38 +02:00
Morilli
44021b7abc fix DotSettings options to conform to current code style and editorconfig 2025-07-19 19:30:52 +02:00
Adam Hathcock
7f9e543213 Merge pull request #924 from Morilli/7zip-1block-solid-archive
Fix 7-zip solid archive detection
2025-07-14 09:12:43 +01:00
Morilli
c489e5a59b fix SevenZipArchive solid detection 2025-07-13 15:09:59 +02:00
Morilli
8de30db7f9 add failing test 2025-07-13 15:08:45 +02:00
Adam Hathcock
415f0c6774 Merge pull request #921 from Morilli/fix-volume-filename
Fix volume FileName property potentially missing
2025-07-07 09:22:45 +01:00
Morilli
aa9cf195a5 Fix volume FileName property potentially missing 2025-07-06 21:56:54 +02:00
Adam Hathcock
6412fc8135 Mark for 0.40 2025-06-03 08:48:34 +01:00
Adam Hathcock
8b1ba9a00c Merge pull request #914 from adamhathcock/update-deps
Update dependencies and csharpier
2025-06-03 08:33:18 +01:00
Adam Hathcock
b02584ef9e Update deps again 2025-06-03 08:30:28 +01:00
Adam Hathcock
88cd6bfd1a Merge remote-tracking branch 'origin/master' into update-deps 2025-06-03 08:13:41 +01:00
Adam Hathcock
89a3da14c9 Merge pull request #918 from Morilli/fix-bzip2-selector-oob
[bzip2] fix possible out of bounds access due to unsanitized nSelectors usage
2025-06-03 08:11:55 +01:00
Morilli
619d987492 fix possible out of bounds access due to unsanitized nSelectors usage 2025-06-02 21:24:38 +02:00
Adam Hathcock
744e410a1a Merge pull request #916 from Morilli/rar-multipart-reader
Implement multipart rar handling for ExtractAllEntries
2025-05-14 11:33:12 +01:00
Morilli
6e51967993 format 2025-05-14 11:42:52 +02:00
Morilli
7989ab2e28 modify now-broken test
This test tested that skipping over entries using the reader interface for an encrypted multi-volume rar archive worked.
However reading those entries doesn't work and the skipping was also not working properly so I believe it's fine to "break" this functionality.
2025-05-14 11:18:41 +02:00
Morilli
a3570a568d fix AbstractReader.Skip for multipart files 2025-05-14 10:27:58 +02:00
Morilli
c0cd998836 add failing test 2025-05-14 10:27:30 +02:00
Morilli
1a452acd1c implement ExtractAllEntries for multipart rar files 2025-05-14 10:27:18 +02:00
Adam Hathcock
6c54083b08 Merge remote-tracking branch 'origin/master' into update-deps 2025-04-28 16:30:40 +01:00
Adam Hathcock
76105ebdaf fix bullseye 2025-04-28 16:30:28 +01:00
Adam Hathcock
2c452201fa Merge pull request #854 from zgabi/patch-1
return Stream.Null when 7z entry has no stream
2025-04-28 16:26:58 +01:00
Adam Hathcock
9fc7fc73f9 Merge branch 'master' into patch-1 2025-04-28 16:21:20 +01:00
Adam Hathcock
e7417e35ba Update dependencies and csharpier 2025-04-28 16:18:01 +01:00
Adam Hathcock
19eb4c7cba Merge pull request #834 from adamhathcock/exception-normalization
Add SharpCompressException and use it or children in most places
2025-04-28 16:12:25 +01:00
Adam Hathcock
1f39a0c9da Merge remote-tracking branch 'origin/master' into exception-normalization
# Conflicts:
#	src/SharpCompress/Readers/ReaderFactory.cs
2025-04-28 16:08:08 +01:00
Adam Hathcock
a480a8893c format 2025-04-28 16:06:00 +01:00
Adam Hathcock
d3a9e341a5 Merge fixes 2025-04-28 16:05:31 +01:00
Adam Hathcock
95caffe607 Merge remote-tracking branch 'origin/master' into exception-normalization
# Conflicts:
#	src/SharpCompress/Common/Rar/RarVolume.cs
#	src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs
#	src/SharpCompress/Compressors/LZMA/LZipStream.cs
2025-04-28 15:59:34 +01:00
Adam Hathcock
fdeca61284 Merge pull request #913 from jdpurcell/pr-bss-fix
Fix regression with BufferedSubStream calculation
2025-03-26 09:00:38 +00:00
J.D. Purcell
45dc653191 Fix regression with size calculation 2025-03-25 20:43:14 -04:00
Adam Hathcock
6e48302b7b Merge pull request #912 from jdpurcell/pr-bss-optim
Optimize BufferedSubStream.ReadByte
2025-03-25 08:04:38 +00:00
J.D. Purcell
a7918d7b11 Optimize BufferedSubStream.ReadByte 2025-03-24 21:28:08 -04:00
Adam Hathcock
ec21253af9 Merge pull request #909 from Morilli/update-usage
Update USAGE.md to remove problematic extraction example
2025-03-24 08:20:17 +00:00
Adam Hathcock
97cdda8663 Merge branch 'master' into update-usage 2025-03-24 08:18:16 +00:00
Adam Hathcock
35ac2b9d71 Merge pull request #910 from jdpurcell/pr-rangedecoderoptim
Optimize LZMA range decoder
2025-03-24 08:17:28 +00:00
J.D. Purcell
14affd8ffa Optimize LZMA range decoder 2025-03-22 17:14:38 -04:00
Morilli
c48409c903 Update USAGE.md
added an explanatory comment to the ExtractAllEntries usage and removed the problematic previous code.

I've added a new example for iterating over entries that doesn't extract them.
2025-03-22 16:50:15 +01:00
Adam Hathcock
227f66f299 Merge pull request #907 from jdpurcell/pr-copyblockoptim
Optimize LZ OutWindow.CopyBlock
2025-03-20 08:24:39 +00:00
J.D. Purcell
c2d9bf94d1 Optimize LZ OutWindow.CopyBlock 2025-03-19 22:29:38 -04:00
Adam Hathcock
8f03841161 Merge pull request #906 from TwanVanDongen/master
Added ARC's crunched methods 5, 6, 7 & 8
2025-03-17 08:30:12 +00:00
Twan van Dongen
344a1ed912 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-03-14 19:09:56 +01:00
Twan van Dongen
ff71993b31 Trying to overcome differences in charpier versions... 2025-03-14 19:09:52 +01:00
Twan van Dongen
18bb773b2c Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-03-14 19:06:14 +01:00
Twan van Dongen
7f905c7940 More csharpier stuff 2025-03-14 19:06:10 +01:00
Twan van Dongen
8a4ba6fc56 Removed empty lineRemoved failing test 2025-03-14 19:03:54 +01:00
Twan van Dongen
e0b275c01c Removed empty line for CSharpier 2025-03-14 19:01:07 +01:00
Twan van Dongen
5926db85df Added ARC's crunched methods 5, 6, 7 & 8 2025-03-14 18:58:34 +01:00
Adam Hathcock
a4715a10e7 Merge pull request #905 from TwanVanDongen/master
ARC decompression methods 3 and 4 added
2025-03-12 08:21:57 +00:00
Twan van Dongen
de0f5c0fcb Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-03-11 20:20:45 +01:00
Twan van Dongen
88d85ce6ac Extra line removed for csharpier 2025-03-11 20:20:41 +01:00
Twan van Dongen
131c171d3e Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-03-11 20:16:24 +01:00
Twan van Dongen
c5ddef6ef7 An exception occurred in ReadOnlySubStream when attempting to set the position to the same value. 2025-03-11 20:15:53 +01:00
Twan van Dongen
f36486d006 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2025-03-11 18:57:52 +01:00
Twan van Dongen
eaf466c5c3 Implementation of squeezed and packed compression algorithms for .ARC archive format 2025-03-11 18:15:53 +01:00
Adam Hathcock
b41bcc349e Merge pull request #903 from TwanVanDongen/master
Base Reader implementation of .ARC format
2025-03-10 08:55:43 +00:00
Adam Hathcock
825c61bdcd Merge branch 'master' into master 2025-03-10 08:51:58 +00:00
Adam Hathcock
f13f49bd71 Merge pull request #904 from jdpurcell/pr-7zattr
Provide access to extended attributes for 7-zip
2025-03-10 08:49:33 +00:00
J.D. Purcell
88f5d4544b Add SevenZipEntry ExtendedAttrib property 2025-03-09 17:16:55 -04:00
J.D. Purcell
b7432a20f0 Remove some unused internal members 2025-03-09 17:16:55 -04:00
Twan van Dongen
ab57c85e66 Missing comma added for csharpier 2025-03-09 18:45:27 +01:00
Twan van Dongen
c7c41bc0d8 Missing comma added for csharpier checksBase Reader implementation of .ARC format 2025-03-09 18:40:43 +01:00
Twan van Dongen
c66f9b06a4 Base Reader implementation of .ARC format 2025-03-09 18:22:52 +01:00
Adam Hathcock
a3ac7e7ca7 Merge pull request #901 from ms264556/feature/sha256-quick-fix
Handle XZ CheckType SHA-256
2025-03-07 10:52:24 +00:00
ms264556
187b762f8a Corrected XZ BlockCheckSize formula 2025-03-07 19:53:49 +13:00
ms264556
3a7fbdfa52 Handle XZ CheckType SHA-256 2025-03-07 14:46:07 +13:00
Adam Hathcock
bbeb46b37f Merge pull request #900 from Morilli/WriteToDirectory-reader
make WriteToDirectory functions use ExtractAllEntries
2025-03-03 08:32:00 +00:00
Morilli
5450b9a700 make WriteToDirectory functions use ExtractAllEntries
for extracting files from solid archives this can be required to get acceptable extraction performance and should therefore always be called.
2025-02-28 21:46:04 +01:00
Adam Hathcock
353b28647c Merge pull request #897 from Morilli/bufferedsubstream-readbyte
Implement ReadByte for BufferedSubStream
2025-02-17 08:07:14 +00:00
Adam Hathcock
2411f4f870 Merge branch 'master' into bufferedsubstream-readbyte 2025-02-17 08:05:02 +00:00
Adam Hathcock
34cd059423 Merge pull request #898 from Morilli/lz-readbyte
Implement ReadByte for LzmaStream and LzOutWindow
2025-02-17 08:04:34 +00:00
Morilli
4b4ec12c87 Implement ReadByte for LzmaStream and LzOutWindow 2025-02-16 18:37:56 +01:00
Morilli
441147c0dc Implement ReadByte for BufferedSubStream 2025-02-16 13:41:46 +01:00
Adam Hathcock
08ceac9f46 Merge pull request #896 from adamhathcock/rar_unpack20_audio_fix
Rar2 v20,v26 Multimedia (Audio) decoder fix
2025-02-12 08:25:38 +00:00
Nanook
6bc690b50b Seriously? 2025-02-11 23:10:03 +00:00
Nanook
c41888b338 Rar2 v20,v26 Multimedia (Audio) decoder fix 2025-02-11 22:30:59 +00:00
Adam Hathcock
6d3c980b39 Merge pull request #894 from Morilli/fix-rare-solid-rar-failure
Fix condition in rar v3 code
2025-02-11 11:39:17 +00:00
Morilli
eb5db176fa revert change to rar5 code
... yeah... apparently the thing that fixes rar3 code breaks rar5 code
2025-02-11 11:21:51 +01:00
Morilli
a77c03fcaf add comment and change the same code in new Unpack50 2025-02-11 11:03:56 +01:00
Adam Hathcock
04b25011e9 Merge branch 'master' into fix-rare-solid-rar-failure 2025-02-11 08:31:49 +00:00
Adam Hathcock
96b34aec10 Merge pull request #895 from Morilli/fix-test-concurrency
use File.OpenRead instead of File.Open in tests to allow concurrent access
2025-02-11 08:30:12 +00:00
Morilli
d560b46c85 use File.OpenRead instead of File.Open to allow concurrent access 2025-02-11 03:31:49 +01:00
Morilli
94789ce455 Fix condition in rar v3 code 2025-02-11 03:04:18 +01:00
Adam Hathcock
55797e5873 Merge pull request #893 from adamhathcock/rar_unpack20
Fix for Rar4 v20 compression.
2025-02-10 09:27:27 +00:00
Nanook
675cab3074 Fix for Rar4 v20 compression. 2025-02-07 22:39:33 +00:00
Adam Hathcock
8d63ab646e Merge pull request #891 from Morilli/fix-zip-datadescriptor-header
Fix zip entry handling for entries with data descriptors
2025-01-28 08:12:40 +00:00
Adam Hathcock
37a2fa1cdc Merge branch 'master' into fix-zip-datadescriptor-header 2025-01-28 08:08:55 +00:00
Adam Hathcock
79ed9650b3 Merge pull request #892 from adamhathcock/fix-tests
don't run net48 on non-windows
2025-01-28 08:08:41 +00:00
Adam Hathcock
b6dc58164e don't run net48 on non-windows 2025-01-28 08:04:59 +00:00
Morilli
f9a974c1fe fix formatting 2025-01-28 02:24:42 +01:00
Morilli
91e672befb remove old hack trying to fix a similar thing
Introduced in af264cdc58c9d076bf83477cbdbfe7a5dad282b7; the test included in that commit passes still.
2025-01-28 02:12:16 +01:00
Morilli
c14d18b9df set local header data from directory header when flag is set
As described in section 4.4.7-4.4.9 of the zip specification when this flag is set the correct values will be in the data descriptor record and in the directory header.
2025-01-28 01:56:14 +01:00
Morilli
d2cfc1844c add failing test 2025-01-28 01:49:49 +01:00
Adam Hathcock
2fb3243a1a Tests also on net48 2025-01-16 08:38:11 +00:00
Adam Hathcock
6f3124a84f Mark for 0.39 2025-01-16 08:30:21 +00:00
Adam Hathcock
59eb5bd9c4 Merge pull request #888 from adamhathcock/updates
Update to support net48, net481, netstandard2.0, net6 and net8
2025-01-16 08:19:50 +00:00
Adam Hathcock
ad2b6bb4f7 Merge branch 'master' into updates 2025-01-16 08:17:25 +00:00
Adam Hathcock
51d64ee10e Merge pull request #889 from majorro/internal-helpers
Make helper classes internal
2025-01-16 08:15:02 +00:00
majorro
1159efc6cc formatting 2025-01-15 21:43:10 +03:00
Adam Hathcock
3cfb76a56f Add back net48 and net481 support 2025-01-15 16:35:05 +00:00
majorro
7a1ad6688a make helpers internal 2025-01-15 04:46:22 +03:00
majorro
4f4af6e3fd make test friend assembly 2025-01-15 04:46:07 +03:00
majorro
2736b79097 signed test assembly 2025-01-15 04:43:16 +03:00
Adam Hathcock
8da2ffa433 Update dependencies 2025-01-14 09:12:03 +00:00
Adam Hathcock
5bf3d6dc32 update csharpier 2025-01-14 09:07:40 +00:00
Adam Hathcock
30d4380afe update csproj 2025-01-14 09:06:03 +00:00
Adam Hathcock
c8b5aad482 Update to support only netstandard2.0, net6 and net8 2025-01-14 09:04:39 +00:00
Adam Hathcock
fa1d440947 Merge pull request #887 from majorro/improve-rar-memory-usage
Improve rar memory usage
2025-01-14 08:58:18 +00:00
Adam Hathcock
a89fc3a276 formatting 2025-01-14 08:55:09 +00:00
majorro
3875f62453 deps fix 2025-01-14 00:36:26 +03:00
majorro
23e1447ab6 stackalloc addvmcode 2025-01-13 23:31:33 +03:00
majorro
91364c6a7c stackalloc readtables 2025-01-13 23:28:26 +03:00
majorro
a070493fba window null checks 2025-01-13 23:26:49 +03:00
majorro
ca0a6ab72c rollback ILLink.Tasks downgrade 2025-01-12 16:38:30 +03:00
majorro
10e0562a82 stackalloc rar unpackv1 2025-01-12 16:02:49 +03:00
majorro
44998a2a2b pooled window for rar unpackv1 2025-01-12 16:01:59 +03:00
majorro
f8e033e560 add explicit System.Buffers, remove redundant code 2025-01-12 15:36:53 +03:00
Adam Hathcock
5842da84af Merge pull request #878 from Morilli/fix-xzblock-padding
Fix XZBlock padding calculation when its stream's starting position % 4 != 0
2024-12-20 08:50:46 +00:00
Adam Hathcock
10cc270170 Merge branch 'master' into fix-xzblock-padding 2024-12-20 08:47:40 +00:00
Morilli
f51bdd56aa expose Position getter in ForwardOnlyStream 2024-12-19 20:41:00 +01:00
Adam Hathcock
7f79c49f93 Merge pull request #884 from YoshiRulz/exports-unclutter
Exports unclutter
2024-12-19 14:06:48 +00:00
YoshiRulz
e4920255f0 Replace ReadOnlyCollection with the one in the BCL
I changed the param type of the helper, but the stronger constraint
didn't seem to matter in practice
2024-12-19 22:11:16 +10:00
YoshiRulz
f8e8273d39 Move utility classes to new namespace 2024-12-19 22:11:16 +10:00
Adam Hathcock
ceddab98d1 Merge pull request #877 from StarkDirewolf/master
Fixed bug in zip time header flags
2024-11-01 14:07:24 +00:00
Robb Pryde
0faa176791 Sharpier styling 2024-10-31 17:35:47 +00:00
Morilli
9b0e0ee536 Fix padding calculation when initial position % 4 != 0 2024-10-29 02:57:26 +01:00
Morilli
881d2756db Add failing test 2024-10-29 02:57:25 +01:00
Robb Pryde
ab5af40999 Fixed bug in zip time header flags, and failing to parse it no longer throws an exception. 2024-10-26 01:22:07 +01:00
Adam Hathcock
6aeef8dcf9 Merge pull request #876 from Morilli/fix-isarchive-stream-seek
Restore stream position in ArchiveFactory.IsArchive
2024-10-24 08:28:52 +01:00
Morilli
5d62196dde Restore stream position in ArchiveFactory.IsArchive 2024-10-23 17:01:55 +02:00
Adam Hathcock
7fe27ac310 Mark for 0.38 2024-09-02 09:09:57 +01:00
Adam Hathcock
1e300349ce Merge pull request #868 from kikaragyozov/patch-1
Fix small typo in USAGE.md
2024-09-02 07:43:30 +01:00
Kiril Karagyozov
6b01a7b08e Fix small typo in USAGE.md 2024-08-29 12:11:19 +03:00
Adam Hathcock
34d948df18 Merge pull request #866 from TwanVanDongen/master
Added shrink, reduce and implode to FORMATS
2024-08-22 16:07:23 +01:00
Twan
27091c4f1d Update FORMATS.md 2024-08-21 19:09:14 +02:00
Twan
970a3d7f2a Update FORMATS.md 2024-08-21 19:08:40 +02:00
Twan
2bedbbfc54 Update FORMATS.md 2024-08-21 19:06:14 +02:00
Adam Hathcock
8de33f0db3 Merge pull request #864 from adamhathcock/update-csproj
Update csproj to get green marks and update deps
2024-08-12 16:08:28 +01:00
Adam Hathcock
df4eab67dc Update csproj to get green marks and update deps 2024-08-08 08:41:51 +01:00
Adam Hathcock
2d13bc0046 Merge pull request #860 from lostmsu/7zSFX
Added support for 7zip SFX archives
2024-08-06 08:54:12 +01:00
Victor Nova
704a0cb35d added support for 7zip SFX archives by handling ReaderOptions.LookForHeader 2024-08-05 23:11:15 -07:00
Adam Hathcock
06a983e445 Merge pull request #859 from DineshSolanki/#858-fix-invalid-character-in-filename
Fix #858 - Replaces invalid filename characters
2024-07-30 08:22:01 +01:00
Dinesh Solanki
2d10df8b87 Fix #858 - Replaces invalid filename characters
Added a method to replace invalid characters in file names with underscores during file extraction. This prevents errors related to invalid file names.
2024-07-26 00:16:44 +05:30
Adam Hathcock
baf66db9dc format 2024-07-24 08:31:44 +01:00
GordonJ
3545693999 Added Tests and supporting Files. 2024-07-23 14:05:07 -05:00
gjefferyes
84fb99c2c8 Merge branch 'adamhathcock:master' into master 2024-07-23 13:58:48 -05:00
Adam Hathcock
21e2983ae1 Merge pull request #857 from alexprabhat99/master
Fix for missing empty directories when using ExtractToDirectory
2024-07-18 08:34:20 +01:00
Alex Prabhat Bara
004e0941d5 code formatted using csharpier 2024-07-16 20:12:01 +05:30
Alex Prabhat Bara
188a426dde fix for missing empty directories when using ExtractToDirectory 2024-07-16 16:20:04 +05:30
Adam Hathcock
6fcfae8bfe Merge pull request #855 from Erior/feature/Check-tar-crc-on-header
Check crc on tar header
2024-07-12 08:35:27 +01:00
Lars Vahlenberg
9515350f52 Remove using directive 2024-07-11 19:56:46 +02:00
Lars Vahlenberg
6b88f82656 Handle special case, empty file 2024-07-11 19:52:33 +02:00
Lars Vahlenberg
e42d953f47 Check crc on tar header 2024-07-10 19:53:32 +02:00
Zavarkó Gábor
471a3f63fe return Stream.Null when 7z entry has no stream 2024-07-07 00:14:00 +02:00
gjefferyes
9c257faf26 Merge branch 'master' into master 2024-06-26 06:28:55 -05:00
Adam Hathcock
d18cad6d76 Merge pull request #852 from LANCommander/fix-post-zip64-entry-subsequent-extractions
Fixed extractions after first ZIP64 entry is read from stream
2024-06-26 08:31:58 +01:00
GordonJ
061273be22 Added Export and (un)Reduce to sharpCompress 2024-06-25 11:35:11 -05:00
Pat Hartl
b89de6caad Fix formatting 2024-06-24 17:19:53 -05:00
Pat Hartl
9bc0a1d7c7 Null reference checking
Reorders this null reference check to avoid throwing a null reference exception.
2024-06-23 22:30:34 -05:00
Pat Hartl
eee518b7fa Reworked ZIP64 handling to separate block
The last commit made in this branch messed up some ZIP reading and caused a bunch of tests to fail. These changes branch off ZIP64 logic into its own block so that data is read correctly for 64 and non-64 entries.
2024-06-23 22:29:33 -05:00
Pat Hartl
b7b78edaa3 Fixed extractions after first ZIP64 entry is read from stream 2024-06-22 00:09:25 -05:00
Adam Hathcock
3eaac68ab4 Merge pull request #850 from Erior/feature/Issue-842
Issue 842
2024-06-18 13:45:53 +01:00
Adam Hathcock
a7672190e9 Merge branch 'master' into feature/Issue-842 2024-06-18 13:43:22 +01:00
Adam Hathcock
4e4e89b6eb Merge pull request #849 from Erior/develop
Fix for issue #844
2024-06-18 13:41:52 +01:00
Lars Vahlenberg
33dd519f56 Throw exception when bzip2 is corrupt 2024-06-08 18:26:12 +02:00
Lars Vahlenberg
5c1149aa8b #844 2024-06-08 17:22:20 +02:00
Adam Hathcock
9061e92af6 Merge pull request #848 from Morilli/fix-gzip-archivetype
Fix gzip archives having a `Type` of `ArchiveType.Tar` instead of `ArchiveType.Gzip`
2024-06-06 08:21:14 +01:00
Morilli
49f5ceaa9b Fix GZipArchive getting Type set to ArchiveType.Tar 2024-06-04 10:34:06 +02:00
Morilli
525b309d37 Add failing test 2024-06-04 10:33:32 +02:00
Adam Hathcock
bdb3a787fc Merge pull request #847 from DannyBoyk/846_tar_longlinkname
Tar: Add processing for the LongLink header type
2024-06-04 08:47:57 +01:00
Daniel Nash
a9601ef848 Tar: Add processing for the LongLink header type
Fixes #846
2024-06-03 12:54:19 -04:00
Adam Hathcock
6fc4b045fd mark for 0.37.2 2024-04-27 09:34:32 +01:00
Adam Hathcock
446852c7d0 really fix source link and central usage 2024-04-27 09:34:05 +01:00
Adam Hathcock
c635f00899 mark as 0.37.1 2024-04-27 09:12:17 +01:00
Adam Hathcock
1393629bc5 Mark sourcelink as PrivateAssets="All" 2024-04-27 06:15:29 +01:00
Adam Hathcock
49ce17b759 update zstdsharp.port and net8 is only trimmable 2024-04-25 08:35:52 +01:00
Adam Hathcock
74888021c8 Merge pull request #835 from Blokyk/fix-736
Prevent infinite loop when reading corrupted archive
2024-04-24 09:20:44 +01:00
Adam Hathcock
9483856439 fmt 2024-04-24 09:17:42 +01:00
blokyk
dbbc7c8132 fix(tar): prevent infinite loop when reading corrupted archive 2024-04-24 03:13:13 +02:00
Adam Hathcock
5d9c99508d fmt 2024-04-23 15:08:50 +01:00
Adam Hathcock
e4d5b56951 fix more nulls and tests 2024-04-23 15:08:32 +01:00
Adam Hathcock
e31238d121 fmt 2024-04-23 14:48:50 +01:00
Adam Hathcock
a283d99e1b compiles 2024-04-23 14:48:33 +01:00
Adam Hathcock
8cb621ebed Add SharpCompressException and use it or children in most places 2024-04-23 14:47:40 +01:00
Adam Hathcock
b203d165f5 Mark for 0.37.0 2024-04-23 10:25:32 +01:00
Adam Hathcock
c695e1136d Merge pull request #828 from adamhathcock/remove-netstandard20
Remove ~netstandard20~ just net7.0
2024-04-23 10:18:24 +01:00
Adam Hathcock
d847202308 add back net standard 2.0 2024-04-23 09:59:30 +01:00
Adam Hathcock
9d24e0a4b8 set package locks and central management 2024-04-23 09:37:25 +01:00
Adam Hathcock
745fe1eb9f references 2024-04-23 09:28:33 +01:00
Adam Hathcock
3e52b85e9d Merge remote-tracking branch 'origin/master' into remove-netstandard20
# Conflicts:
#	.config/dotnet-tools.json
2024-04-23 09:26:44 +01:00
Adam Hathcock
d26f020b50 Merge pull request #832 from adamhathcock/remove-ignored-nulls
Remove ignored nulls
2024-04-23 09:25:08 +01:00
Adam Hathcock
095b5f702c get rid of another null! 2024-04-23 09:20:20 +01:00
Adam Hathcock
9622853b8d fix and fmt 2024-04-23 09:16:05 +01:00
Adam Hathcock
b94e75fabe try to fix more tests 2024-04-23 09:06:49 +01:00
Adam Hathcock
23dd041e2e fix some tests 2024-04-23 08:52:10 +01:00
Adam Hathcock
c73ca21b4d fmt 2024-04-22 15:19:05 +01:00
Adam Hathcock
7ebdc85ad2 more null clean up 2024-04-22 15:17:24 +01:00
Adam Hathcock
99e2c8c90d more clean up 2024-04-22 15:10:22 +01:00
Adam Hathcock
f24bfdf945 fix tests 2024-04-22 14:57:08 +01:00
Adam Hathcock
7963233702 add missing usings 2024-04-22 14:18:41 +01:00
Adam Hathcock
b550df2038 get rid of more ! and update csharpier 2024-04-22 14:17:08 +01:00
Adam Hathcock
fb55624f5f add more null handling 2024-04-18 14:25:10 +01:00
Adam Hathcock
e96366f489 Entry can be null and remove other ! usages 2024-04-18 13:24:03 +01:00
Adam Hathcock
900190cf54 Merge pull request #829 from NeuroXiq/patch-1
Update README.md - Change API Docs to DNDocs
2024-04-15 08:14:16 +01:00
Marek Węglarz
2af744b474 Update README.md 2024-04-15 04:28:15 +02:00
Adam Hathcock
11153084e2 update csharpier 2024-04-11 15:47:39 +01:00
Adam Hathcock
4b9c814bfc remove .netstandard 2.0 and clean up 2024-04-11 15:46:43 +01:00
Adam Hathcock
1b5d3a3b6e Merge pull request #825 from adamhathcock/tar-corruption
Fix tar corruption when sizes mismatch
2024-04-11 13:11:29 +01:00
Adam Hathcock
373637e6a7 more logic fixes 2024-04-11 09:05:45 +01:00
Adam Hathcock
cb223217c1 actually, transfer block is different than overall transfer 2024-04-10 16:12:01 +01:00
Adam Hathcock
eab97a3f8b calculate remaining afterwards 2024-04-10 08:53:20 +01:00
Adam Hathcock
fdfaa8ab45 add max transfer size to tar 2024-04-09 15:35:15 +01:00
Adam Hathcock
2321d9dbee fix patch 2024-04-09 08:56:15 +01:00
Adam Hathcock
bf74dd887a Fix tar corruption when sizes mismatch 2024-04-09 08:19:23 +01:00
Adam Hathcock
3612035894 Merge pull request #823 from klimatr26/new-7z-filters
Add support for 7z ARM64 and RISCV filters
2024-04-08 09:56:07 +01:00
Adam Hathcock
6553e9b0cd formatting 2024-04-08 09:50:37 +01:00
klimatr26
09f2410170 Add support for 7z ARM64 and RISCV filters 2024-04-05 15:00:43 -05:00
Adam Hathcock
fb73d8c0a7 Merge pull request #819 from TwanVanDongen/master
Support added for TAR LZW compression (Unix 'compress' resulting in .…
2024-03-25 08:41:34 +00:00
Twan van Dongen
f2b0368078 CSharpier reformat missed 2024-03-24 16:29:29 +01:00
Twan van Dongen
02301ecf6d Support added for TAR LZW compression (Unix 'compress' resulting in .Z files) 2024-03-24 16:23:25 +01:00
Adam Hathcock
bcb61ee3e4 Merge pull request #817 from btomblinson/master
#809 Add README.md to csproj for NuGet
2024-03-18 08:34:20 +00:00
btomblinson
6a824429d0 #809 Add README.md to csproj for NuGet 2024-03-16 22:52:36 -06:00
Adam Hathcock
6a52f9097f Merge pull request #815 from adamhathcock/code-clean-up
Code clean up
2024-03-14 16:01:34 +00:00
Adam Hathcock
3fa85fc516 Merge branch 'master' into code-clean-up 2024-03-14 15:58:29 +00:00
Adam Hathcock
498d132d8a Merge pull request #816 from coderb/pullreq-rar-memusage
rar5 improve memory usage
2024-03-14 15:58:15 +00:00
root
b6340f1458 rar5 improve memory usage
use ArrayPool for stream buffer
  use stackalloc for methods on file decompression code path
2024-03-14 11:50:45 -04:00
Adam Hathcock
4afc7ae2e4 use complete namespace 2024-03-14 13:07:40 +00:00
Adam Hathcock
95975a4c33 even more clean up 2024-03-14 09:07:21 +00:00
Adam Hathcock
198a0673a2 more clean up 2024-03-14 09:00:44 +00:00
Adam Hathcock
94d1503c64 more clean up 2024-03-14 08:57:16 +00:00
Adam Hathcock
5f13e245f0 more clean up on tests 2024-03-14 08:53:08 +00:00
Adam Hathcock
2715ae645d use var 2024-03-14 08:38:12 +00:00
Adam Hathcock
0299232cb5 just using rider to clean up 2024-03-14 08:37:17 +00:00
Adam Hathcock
93e181cfd9 update csharpier 2024-03-14 08:29:30 +00:00
Adam Hathcock
8072eb1212 Merge pull request #814 from coderb/pullreq-rar5-redir
rar5 read FHEXTRA_REDIR and expose via RarEntry
2024-03-14 08:26:06 +00:00
root
226ce340f2 rar5 read FHEXTRA_REDIR and expose via RarEntry
NOTE: api user should skip entries where RarEntry.IsRedir is true and not call OpenEntryStream()
2024-03-14 04:17:31 -04:00
Adam Hathcock
ab5535eba3 Merge pull request #807 from TwanVanDongen/master
Support for decompressing Zip Shrink (Method:1)
2024-01-29 08:27:32 +00:00
Adam Hathcock
8da2499495 Merge pull request #805 from DannyBoyk/804_Fix_ZIP_Decryption
Zip: Use last modified time from basic header when validating zip decryption
2024-01-29 08:26:17 +00:00
Twan van Dongen
c057ffb153 Refrormatted using CSharpier 2024-01-27 18:59:56 +01:00
Twan van Dongen
fe13d29549 Merge branch 'master' of https://github.com/TwanVanDongen/sharpcompress 2024-01-27 18:31:13 +01:00
Twan van Dongen
225aaab4f4 Support for decompressing Zip Shrink (method:1) added 2024-01-27 18:28:46 +01:00
Daniel Nash
14c973558b Zip: Use last modified time from basic header when validating zip decryption
The last modified time used for zip decryption validation must be the
one from the basic header. If UnixTimeExtraFields are present, the
previous implementation was attempting to verify against that value
instead.
Fixed #804
2024-01-26 10:54:41 -05:00
Adam Hathcock
f515ff36b6 Mark for 0.36.0 2024-01-15 08:21:36 +00:00
Adam Hathcock
ed57cfd2f9 Merge pull request #803 from DannyBoyk/802_Add_UnixTimeExtraField_Support_Zips
Add support for the UnixTimeExtraField in Zip files
2024-01-15 08:19:29 +00:00
Daniel Nash
d69559e9c7 Add support for the UnixTimeExtraField in Zip files
Fixes #802
2024-01-12 09:34:13 -05:00
Adam Hathcock
396717efd1 Merge pull request #799 from Erior/feature/DataDescriptorStream-fix-report-size-position
Fix reporting size / position
2024-01-08 09:18:34 +00:00
Adam Hathcock
284fa24464 Merge pull request #800 from Erior/feature/Expose-file-attributes-for-rar-entries
Expose file attributes for rar
2024-01-08 09:17:53 +00:00
Adam Hathcock
0a20b9179a Merge pull request #798 from Erior/feature/Fix-crash-when-not-setting-password-for-rar5
Set Empty string for Rar5 password as default
2024-01-08 09:17:07 +00:00
Adam Hathcock
a0d5037885 Merge pull request #801 from Erior/feature/771
Issue 771, remove throw on flush for readonly streams
2024-01-08 09:13:39 +00:00
Lars Vahlenberg
4477833b1d Issue 771, remove throw on flush for readonly streams 2024-01-06 00:14:34 +01:00
Lars Vahlenberg
e0a5ed4bdb Expose file attributes 2024-01-05 09:50:58 +01:00
Lars Vahlenberg
46d4b26eba Fix testing under Linux 2024-01-05 00:35:24 +01:00
Lars Vahlenberg
f7c6edf849 Fix reporting size / position 2024-01-04 23:33:39 +01:00
Lars Vahlenberg
6c157def4b set empty string if password not set 2024-01-04 21:16:07 +01:00
Adam Hathcock
741712f89f Merge pull request #794 from Erior/feature/rar5-blake2
Feature/rar5 blake2
2024-01-03 08:34:54 +00:00
Lars Vahlenberg
4f749da628 Merge branch 'develop' into feature/rar5-blake2 2024-01-02 21:26:51 +01:00
Lars Vahlenberg
8b02795d69 CSharpier 2024-01-02 21:25:40 +01:00
Lars Vahlenberg
f8a0069a5d Calc checksum when encrypted is not working for RAR5, disable for now 2024-01-02 21:18:49 +01:00
Lars Vahlenberg
388bbe047e Blake2 Archive test OK 2024-01-02 20:46:55 +01:00
Adam Hathcock
2d4ce30e58 Merge pull request #792 from DannyBoyk/791_Correct_EOCD_ZipWriter
ZipWriter: Write correct EOCD record when more than 65,535 files
2023-12-27 08:55:02 +00:00
Daniel Nash
d4fb17cf66 ZipWriter: Write correct EOCD record when more than 65,535 files
0xFFFF will be written to the EOCD to signal to use the ZIP64
CentralDirectory record when the number of files is 65,535 or more.
Fixes #791
2023-12-22 11:26:01 -05:00
Adam Hathcock
372a2c8375 Mark for 0.35.0 2023-12-18 09:59:46 +00:00
Adam Hathcock
8f27121f21 Merge pull request #789 from adamhathcock/dotnet8
Dotnet8
2023-12-18 09:57:50 +00:00
Adam Hathcock
b986bf675f just remove readme 2023-12-18 09:31:33 +00:00
Adam Hathcock
80718a461b fix readme? 2023-12-18 09:24:00 +00:00
Adam Hathcock
2d14ecf58b add readme 2023-12-18 09:20:44 +00:00
Adam Hathcock
32aa9877c0 remove caching 2023-12-18 09:16:02 +00:00
Adam Hathcock
cee3a9c11d Revert "add lock files"
This reverts commit 30a31de45b.
2023-12-18 09:15:26 +00:00
Adam Hathcock
b78643f2d8 update upload artifact 2023-12-18 09:15:15 +00:00
Adam Hathcock
30a31de45b add lock files 2023-12-18 09:13:14 +00:00
Adam Hathcock
e4c4db534c build for dotnet 8 2023-12-18 09:09:31 +00:00
Adam Hathcock
4f7a0d3ad0 CI to dotnet 8 2023-12-18 09:08:06 +00:00
Adam Hathcock
ea3a96eead update and rerun csharpier 2023-12-18 09:04:04 +00:00
Adam Hathcock
c0e01ac132 Use dotnet 8 and update deps 2023-12-18 09:01:54 +00:00
Adam Hathcock
28ea50bca4 Merge pull request #788 from Erior/develop
RAR5 decryption support
2023-12-18 08:51:25 +00:00
Lars Vahlenberg
619e44b30f CSharpier fixes 2023-12-16 03:08:51 +01:00
Lars Vahlenberg
d678275dee Implement RAR5 decryption 2023-12-16 02:53:09 +01:00
Adam Hathcock
08eed53595 Merge pull request #787 from adamhathcock/dependabot/github_actions/actions/setup-dotnet-4
Bump actions/setup-dotnet from 3 to 4
2023-12-11 10:09:28 +00:00
dependabot[bot]
ff40f7d262 Bump actions/setup-dotnet from 3 to 4
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 09:35:30 +00:00
Adam Hathcock
3c1ae51dae Merge pull request #786 from Erior/feature/Issue-774
LZMA EOS marker detection
2023-12-11 08:46:20 +00:00
Adam Hathcock
8a59fc9aaf Merge pull request #785 from Erior/feature/Issue-782
Handle tar files generated with tar -H oldgnu that has large uid/gid values
2023-12-11 08:44:54 +00:00
Adam Hathcock
b7ea9dd841 Merge pull request #784 from Erior/feature/rar-comment
Dont crash on reading rar5 comment #783
2023-12-11 08:44:01 +00:00
Lars Vahlenberg
0320db6b4a LZMA EOS marker detection 2023-12-09 13:41:35 +01:00
Lars Vahlenberg
18c7f58093 Handle tar files generated with tar -H oldgnu that has large uid/gid values 2023-12-04 22:35:11 +01:00
Lars Vahlenberg
7f6f7b1436 Resharpier fix 2023-12-04 20:28:16 +01:00
Lars Vahlenberg
ca49176b97 Dont crash on reading rar5 comment 2023-12-04 20:19:11 +01:00
Adam Hathcock
67be0cd9d7 Mark for 0.34.2 2023-11-15 11:32:51 +00:00
Adam Hathcock
902fadef83 Merge pull request #780 from caesay/cs/revert-disable-strongname
Revert change disabling strong name signing in 92df1ec
2023-11-15 11:22:02 +00:00
Adam Hathcock
2777b6411f Merge branch 'master' into cs/revert-disable-strongname 2023-11-15 11:18:30 +00:00
Adam Hathcock
e3235d7f04 Merge pull request #781 from adamhathcock/fix-formatting
Update csharpier and fix formatting
2023-11-15 11:18:04 +00:00
Adam Hathcock
dc89c8858e comment out more C++ bits 2023-11-15 11:14:39 +00:00
Adam Hathcock
d28a278d63 Comment out flag to allow formatting 2023-11-15 11:10:05 +00:00
Adam Hathcock
7080c2abd0 Update csharpier and fix formatting 2023-11-15 11:05:30 +00:00
Caelan Sayler
43f86bcab8 Revert change disabling strong name signing in 92df1ec 2023-11-14 16:34:58 +00:00
Adam Hathcock
7d9c875c4d Merge pull request #778 from LANCommander/throw-cancelled-exception
Throw ReaderCancelledException on reader cancelled
2023-11-13 08:34:15 +00:00
Pat Hartl
ed4099eb12 Throw ReaderCancelledException on reader cancelled 2023-11-10 23:36:14 -06:00
Adam Hathcock
632b83f75d Mark for 0.34.1 2023-10-02 08:44:14 +01:00
Adam Hathcock
66c92637f9 Merge pull request #769 from Erior/feature/766
Update Zstd to 0.7.2
2023-09-25 09:01:51 +01:00
Adam Hathcock
6bcaebc471 Merge pull request #768 from Erior/feature/761
Feature/761
2023-09-25 09:01:20 +01:00
Lars Vahlenberg
7feee1027c Update Zstd to 0.7.2 2023-09-23 16:02:27 +02:00
Lars Vahlenberg
4fd8c77fa9 CSharpier cleanup 2023-09-23 14:52:39 +02:00
Lars Vahlenberg
bc3bb2d323 Set FilePart properties for directory type 2023-09-23 14:51:08 +02:00
Adam Hathcock
7764684c68 Release for 0.34 2023-09-18 09:53:05 +01:00
Adam Hathcock
feb2c38572 fmt update 2023-09-18 09:48:31 +01:00
Adam Hathcock
6a97e82a2e Merge pull request #763 from btomblinson/master
#751 Add .tar.7z support
2023-09-18 09:47:01 +01:00
btomblinson
57c0d19cde #751 Add .tar.7z support 2023-09-17 17:46:56 -06:00
Adam Hathcock
e14ed89f3d Merge pull request #759 from Erior/feature/748
Feature/748
2023-09-14 09:05:48 +01:00
Adam Hathcock
6a14893a23 Merge branch 'master' into feature/748 2023-09-14 09:00:50 +01:00
Lars Vahlenberg
0f19735d33 Cleanup 2023-09-11 19:31:27 +02:00
Lars Vahlenberg
6a859ac65d Adding Filters to 7z 2023-09-11 19:24:54 +02:00
Adam Hathcock
4d9c24244c Merge pull request #758 from adamhathcock/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-09-11 10:47:54 +01:00
dependabot[bot]
cdeb288c4f Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 09:38:10 +00:00
Adam Hathcock
7f8016497b Merge pull request #750 from FlsZen/master
Add fast `ExtractToDirectoryAsync` extension method on `IArchive`
2023-09-07 15:05:15 +01:00
FlsZen
ec01225225 It looks like build format wants this on one line 2023-08-13 12:52:14 -04:00
James Hood
4e23b84999 Remove Task aspect 2023-07-21 13:17:42 -04:00
James Hood
c7c143fed9 Add ExtractToDirectoryAsync extension method on IArchive that is very fast compared to WriteToDirectory. 2023-07-19 08:22:15 -04:00
Adam Hathcock
4932171834 update csharpier 2023-06-12 09:53:00 +01:00
Adam Hathcock
00fc6c8e2f formatting 2023-06-12 09:52:35 +01:00
Adam Hathcock
1b73dab341 Merge remote-tracking branch 'Nanook/fixes-zstd' 2023-06-12 09:52:17 +01:00
Adam Hathcock
99e99c1ccd Merge branch 'master' into fixes-zstd 2023-06-12 09:45:35 +01:00
Adam Hathcock
14ce479ab7 Merge pull request #746 from rodesfl/patch-1
Added simple example
2023-06-12 09:31:17 +01:00
Rodrigo Lotrário
e7e873a1b2 Added simple example
Had some difficult figuring this one out, as this is so straight forward and is the simplest use case, maybe should be included at the top of the docs ?
2023-06-09 19:38:42 -03:00
Adam Hathcock
5a57428ec0 Merge pull request #745 from Erior/feature/Issue-743
Skip if we know the size, set blank password if not set for rar
2023-06-07 09:44:36 +01:00
Lars Vahlenberg
18e8e6ee98 Sharpier 2023-06-06 22:43:12 +02:00
Lars Vahlenberg
6bf6e51740 Skip if we know the size, set blank password if not set for rar 2023-06-06 22:27:53 +02:00
Adam Hathcock
b52a899a18 Merge pull request #740 from AlissaSabre/issue_739
Make ArchiveFactory.IsArchive(Stream, ...) public. Fix #739
2023-05-10 09:56:50 +01:00
Alissa Sabre
cf722a7120 Make ArchiveFactory.IsArchive(Stream, ...) public. Fix #739 2023-05-10 15:49:44 +09:00
Adam Hathcock
33cd1f3db8 Merge pull request #737 from Erior/feature/TarHeaderFactory-Infinite-loop
Check for broken file #736
2023-03-30 11:35:20 +01:00
Lars Vahlenberg
b7d2715ffd Remove whitespace 2023-03-29 19:39:03 +02:00
Lars Vahlenberg
fe63466d67 CSharpier 2023-03-29 18:18:17 +02:00
Lars Vahlenberg
0fb63eea99 Check for broken file 2023-03-28 23:07:21 +02:00
Adam Hathcock
59552804f6 fix badge 2023-03-21 14:11:18 +00:00
Adam Hathcock
579d6d73f8 build tests 2023-03-21 13:56:51 +00:00
Adam Hathcock
f83e3022ba add no restore to build 2023-03-21 13:54:45 +00:00
Adam Hathcock
bf93bbf5f8 fix restore 2023-03-21 13:44:02 +00:00
Adam Hathcock
fa2a52ff41 add caching and some cleanup 2023-03-21 13:41:36 +00:00
Adam Hathcock
813d9eace3 update dependencies 2023-03-21 13:16:31 +00:00
Adam Hathcock
16e8dd447b update csharpier 2023-03-21 13:14:08 +00:00
Adam Hathcock
0129b31dec Merge pull request #735 from Erior/feature/Expand-Delta-distance-tests
Remove check for minimal distance and add test case generated by 7z as compatibility check
2023-03-21 10:06:10 +00:00
Adam Hathcock
9544960314 Merge branch 'master' into feature/Expand-Delta-distance-tests 2023-03-21 08:34:54 +00:00
Lars Vahlenberg
23a9ca3140 Delta distance 2023-03-19 12:37:12 +01:00
Adam Hathcock
dfa4bb6ca4 Merge pull request #733 from Erior/feature/Handle-split-rar-archive-above-100-parts
Increase character value to support rar file with more than 100 parts…
2023-03-13 09:01:22 +00:00
Lars Vahlenberg
8aac3320be Increase character value to support rar file with more than 100 parts old tyle 2023-03-11 02:41:50 +01:00
Adam Hathcock
42ddb0d5ed Merge pull request #727 from Erior/feature/UncompressedZipExtractall
Implement Searching Data Descriptor stream issue/pull #680
2023-03-02 09:47:44 +00:00
Lars Vahlenberg
f60728b537 ReadOnlySubStream span position bug 2023-03-01 20:17:43 +01:00
Lars Vahlenberg
9e6f9d50ef Sync with master 2023-03-01 20:13:13 +01:00
Adam Hathcock
d76a473324 Merge pull request #729 from TwanVanDongen/master
Fixed support for RAR 1.5 (algo15)
2023-03-01 08:56:40 +00:00
Adam Hathcock
5a2d2b86d5 Merge branch 'master' into master 2023-03-01 08:52:34 +00:00
Adam Hathcock
42e8f481d6 Merge pull request #726 from Erior/feature/7ZipDelta
Add support for 7ZipDelta decompress
2023-03-01 08:43:48 +00:00
Adam Hathcock
9ecf652745 Merge pull request #722 from Nanook/fixes-XZ-zip
Zip Multipart fix, XZ stream fix, XZ stream support added to zip/zipx
2023-03-01 08:36:21 +00:00
Twan van Dongen
8748314b5b Fixed support for RAR 1.5 (algo15) and added test archive for unit testing. Rar 1.5 archive created using DOS version, which only supports uppercase characters, thus resulting in amending base class with 'UseCaseInsensitiveToVerify' toggle. 2023-02-21 21:28:38 +01:00
Lars Vahlenberg
606923b374 Implement Searching Data Descriptor stream for supporting UncompressedZipExtractAll 2023-02-19 01:33:22 +01:00
Lars Vahlenberg
3ae830a637 Add support for 7ZipDelta decompress 2023-02-18 15:27:16 +01:00
Nanook
92df1ecd5f ZStandard support added to zip/zipx (WinZip) and 7zip (mcmilk 7zip) 2023-02-02 01:06:18 +00:00
Nanook
b9d019561f Added the XZ zipx unit test. 2023-02-02 00:39:34 +00:00
Nanook
48a341b79c Split archive handling fix. XZ stream decoding bug fix (in X64Convert filter). XZ stream support added to zip/zipx. 2023-02-02 00:18:37 +00:00
Adam Hathcock
d1ea8517d2 Merge pull request #717 from ds5678/lzma-improvements
Several improvements to the LZMA Compressor
2022-12-23 10:24:24 +00:00
Jeremy Pritts
cd23844e35 Several improvements to the LZMA compressor:
* Encapsulation and Immutability for LzmaEncoderProperties
* LzmaEncoderProperties.Default static property
* Encoding tests for LzmaStream
2022-12-23 00:00:04 -05:00
Adam Hathcock
3f24af3a99 Merge pull request #716 from itn3000/fix-reflection-aot-error
replace Activator.CreateInstance to Func for avoiding error in NativeAOT
2022-12-21 13:37:19 +00:00
itn3000
78421683fe remove redundant cast 2022-12-21 14:13:24 +09:00
itn3000
61bfbdb26e fix compilation error 2022-12-21 14:10:52 +09:00
itn3000
a7a5c41370 replace Activator.CreateInstance to Func for avoiding error in NativeAOT 2022-12-21 10:37:12 +09:00
Adam Hathcock
f0b4c13200 Merge pull request #715 from adamhathcock/net7
Update to dotnet 7.  Change net461 to net462.  Remove netcoreapp3.1
2022-12-20 16:00:31 +00:00
Adam Hathcock
b01e97b168 more clean up 2022-12-20 15:20:49 +00:00
Adam Hathcock
7da10795a1 csharpier 2022-12-20 15:14:22 +00:00
Adam Hathcock
959bbdcf1b big clean up 2022-12-20 15:06:44 +00:00
Adam Hathcock
970e31a1b1 cleanup and run csharpier 2022-12-20 13:45:47 +00:00
Adam Hathcock
2dae2b7984 update build targets and CI 2022-12-20 13:40:33 +00:00
Adam Hathcock
d6ac9a0363 Fix build 2022-12-20 13:09:16 +00:00
Adam Hathcock
18336c2b8e Update to dotnet 7. Change net461 to net462. Remove netcoreapp3.1 2022-12-20 11:17:45 +00:00
Adam Hathcock
fc02d32ac3 Merge pull request #709 from vpenades/master
Generalized factories to readers and writers.
2022-12-06 14:17:02 +00:00
vpenades
891d5d3c35 commented unsupported extensions 2022-12-06 10:13:09 +01:00
vpenades
17dab3df34 small refactor 2022-12-05 22:36:18 +01:00
vpenades
37c7251ec9 added additional TAR extensions 2022-12-05 22:29:28 +01:00
vpenades
a22393075f Generalized archive creation 2022-12-05 09:31:30 +01:00
Vicente Penades
ca3d088785 generalized multipart archive interface 2022-12-03 13:44:19 +01:00
vpenades
8775b65f58 Generalized factories to readers and writers. 2022-11-29 16:45:20 +01:00
Adam Hathcock
c1204a5efb Merge pull request #706 from andreas-eriksson/master
Use PackageLicenseExpression instead of PackageLicenseFile
2022-11-28 08:38:49 +00:00
Andreas Eriksson
941db572c7 Add Copyright. 2022-11-27 12:39:59 +01:00
Andreas Eriksson
addb7ca95d spaces 2022-11-27 12:37:28 +01:00
Andreas Eriksson
5a930930da Use PackageLicenseExpression instead of PackageLicenseFile 2022-11-27 12:36:19 +01:00
Adam Hathcock
df877e87bf Merge pull request #699 from adamhathcock/dependabot/github_actions/actions/setup-dotnet-3
Bump actions/setup-dotnet from 2 to 3
2022-10-03 12:31:33 +01:00
dependabot[bot]
adb200d885 Bump actions/setup-dotnet from 2 to 3
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 2 to 3.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 09:26:24 +00:00
Adam Hathcock
4f0840b8b8 Merge pull request #697 from IngBertolini/rar_comment
Added support for reading comment header for Rar v5 archives
2022-09-30 08:53:37 +01:00
IngBertolini
c37ea5c890 Forgot to consider the zero termination 2022-09-29 18:14:56 +02:00
IngBertolini
cac9366c86 Update RarVolume.cs 2022-09-29 17:44:15 +02:00
IngBertolini
1fc28f8cd1 Update RarVolume.cs 2022-09-29 17:42:43 +02:00
IngBertolini
2109643ec0 Update RarVolume.cs 2022-09-29 17:23:06 +02:00
Adam Hathcock
3caf5a5a6d Merge pull request #696 from stakira/master
Ignores UnicodePathExtra if forced encoding is specified
2022-09-15 10:16:18 +01:00
Sugita Akira
418c1256a8 Ignores UnicodePathExtra if forced encoding is specified 2022-09-14 21:45:41 -07:00
Adam Hathcock
3ae7ba89e8 Merge pull request #689 from Erior/master
64bit datadescriptors
2022-09-06 11:52:00 +01:00
Adam Hathcock
191bb9d916 Merge branch 'master' into master 2022-09-06 11:46:16 +01:00
Adam Hathcock
f1d8fadabf Merge pull request #671 from vpenades/master
Introduced IArchiveFactory
2022-09-05 09:46:24 +01:00
Erior
c898732739 Merge branch 'master' into master 2022-08-31 16:37:46 +02:00
Vicente Penades
6e4f54eaf6 Merge branch 'master' into master 2022-08-26 14:34:01 +02:00
Adam Hathcock
4ba2963cfe Merge pull request #690 from louis-michelbergeron/master
Access level to LzmaStream Decoder
2022-08-09 08:28:05 +01:00
Lars Vahlenberg
20e6209036 Merge 2022-08-04 21:24:27 +02:00
Lars Vahlenberg
44a5433af3 64bit DataDescriptor 2022-08-04 21:22:31 +02:00
Adam Hathcock
0f6f13ed3e Merge pull request #687 from Erior/feature/SourceStreamPositionCountingBug
SourceStream Position counting bug fix
2022-08-01 08:14:57 +01:00
Lars Vahlenberg
0ae75634b1 SourceStream Position counting bug fix 2022-07-30 16:28:43 +02:00
Vicente Penades
9458ea81da Merge branch 'adamhathcock:master' into master 2022-07-30 15:24:10 +02:00
louis-michel
9f539c1d08 Merge branch 'master' of https://github.com/louis-michelbergeron/sharpcompress 2022-07-29 14:07:17 -04:00
louis-michel
37b03c7d5a Accessibility of Decoder 2022-07-29 14:06:53 -04:00
Adam Hathcock
3009e6dcfd Mark for 0.32.2 2022-07-29 10:45:56 +01:00
Adam Hathcock
70343b17bc add more tests for uncompressed streaming zips 2022-07-29 09:47:35 +01:00
Adam Hathcock
3f6027ec2c Merge pull request #686 from Erior/477
Mitigation of problems
2022-07-29 09:41:24 +01:00
Lars Vahlenberg
5706732c55 Naive implementation of searching of DataDescriptor, not compatible with big archives (>32bit), but handles test cases. 2022-07-28 23:03:06 +02:00
Lars Vahlenberg
ad633a9dd0 missing test file from error report 2022-07-28 21:20:42 +02:00
Lars Vahlenberg
7c56df1237 Mitigation of problems 2022-07-28 20:36:28 +02:00
Adam Hathcock
c1110f2897 Merge pull request #683 from OwnageIsMagic/patch-1
WriteAll: use delegate instead of Expression
2022-07-27 10:13:50 +01:00
Adam Hathcock
647642578b Merge branch 'master' into patch-1 2022-07-27 09:49:13 +01:00
OwnageIsMagic
5ca4efac31 WriteAll: revert 109a7c1 2022-07-26 21:36:00 +03:00
Adam Hathcock
deddf12b70 Merge pull request #684 from daverant/nuget-license
Include license in nuget package
2022-07-26 16:21:41 +01:00
OwnageIsMagic
109a7c12ea WriteAll: update delegate type 2022-07-19 04:03:26 +03:00
David Rant
f955031e27 Hide license in IDE 2022-07-18 17:16:22 +01:00
David Rant
6a69c6cd02 Reference bundled package license file 2022-07-18 17:11:06 +01:00
David Rant
c1d4ac45ab Include license when packing 2022-07-18 17:10:36 +01:00
OwnageIsMagic
2946a35b0e WriteAll: use delegate instead of Expression 2022-07-18 04:36:31 +03:00
Adam Hathcock
c73a8cb18f Merge pull request #682 from adamhathcock/RarFileVolIdx_RarArcVer_GzCrc 2022-07-16 11:29:48 +01:00
Nanook
574a093038 Minor tweak that got missed in the last tidy. 2022-07-15 21:25:39 +01:00
Nanook
4eb1fe0b80 RarArchive has Min/MaxVersion. RarEntry has Volumne Indexes. GZ CRC fix. 2022-07-15 21:15:10 +01:00
Adam Hathcock
4c46cd725b Merge pull request #679 from louis-michelbergeron/master
Fix LZMADecoder Code function
2022-06-28 08:27:13 +01:00
Adam Hathcock
fdbd0e1fba Merge branch 'master' into master 2022-06-28 08:21:49 +01:00
louis-michel
5801168ce0 Merge branch 'master' of https://github.com/louis-michelbergeron/sharpcompress 2022-06-27 19:13:20 -04:00
louis-michel
d4c7551087 Fix LZMA Code function 2022-06-27 19:13:10 -04:00
Adam Hathcock
c9daf0c9f5 Merge pull request #675 from Erior/feature/#636
ReadOnlySubStream overrides and adds logic #636
2022-06-22 11:17:18 +01:00
Adam Hathcock
8cb566b031 Merge branch 'master' into feature/#636 2022-06-22 09:05:57 +01:00
Lars Vahlenberg
089b16326e ReadOnlySubStream overrides and adds logic to Read byte[], needs to have same logic for Span<byte> for consistency. 2022-06-21 19:30:07 +02:00
Adam Hathcock
c0e43cc0e5 Mark for 0.32.1 2022-06-20 10:32:47 +01:00
Adam Hathcock
514c3539e6 Merge pull request #672 from MartinDemberger/Task_477
Corrected skip-marker on skip of uncompressed ZIP file with missing size informations.
2022-06-20 10:31:31 +01:00
Adam Hathcock
62c94a178c Merge branch 'master' into Task_477 2022-06-20 10:26:45 +01:00
Adam Hathcock
9fee38b18d Merge pull request #674 from MartinDemberger/DeduplicateNonDisposing
Suppress nested NonDisposingStream
2022-06-20 10:25:25 +01:00
Adam Hathcock
cd3114d39e Merge branch 'master' into DeduplicateNonDisposing 2022-06-20 10:20:02 +01:00
Adam Hathcock
12b4e15812 Merge pull request #673 from Erior/feature/Malformed-zip-file-generated
Feature/malformed zip file generated
2022-06-20 10:19:41 +01:00
Martin Demberger
35336a0827 Suppress nested NonDisposingStream 2022-06-19 22:05:52 +02:00
Martin Demberger
ece7cbfec3 Set skip-marker when stream is skipped 2022-06-18 14:35:14 +02:00
Lars Vahlenberg
a00075ee0d Wrong flags set, we do not expose this in the interface 2022-06-17 15:07:07 +02:00
Lars Vahlenberg
b6c4e28b4d Generated test case, however, don't see any problems 2022-06-16 23:32:46 +02:00
Martin Demberger
8b55cce39a Better handling of uncompressed zip files. 2022-06-15 16:28:14 +02:00
vpenades
1db216e6ec Merge branch 'master' of https://github.com/vpenades/sharpcompress 2022-06-14 11:40:33 +02:00
vpenades
20142f91fd Added remaining Open method variants 2022-06-14 11:39:52 +02:00
Vicente Penades
b34be141b7 Merge branch 'master' into master 2022-06-13 17:15:22 +02:00
Adam Hathcock
6e99446ce5 Mark for 0.32 2022-06-13 15:28:54 +01:00
Adam Hathcock
20a09b4866 Drop net5 2022-06-13 15:24:53 +01:00
vpenades
8ea8dcde19 Added Archive Name 2022-06-13 13:34:21 +02:00
vpenades
b205e2a84f Introduced IArchiveFactory 2022-06-13 11:56:32 +02:00
Adam Hathcock
7f7db5eabd Merge pull request #669 from louis-michelbergeron/master
XZ decoding BCJ filters support
2022-06-13 08:37:28 +01:00
louis-michelbergeron
0651d064fc Update README.md 2022-06-10 15:32:41 -04:00
louis-michelbergeron
73ca7759d3 Update README.md
Contribution line.
2022-06-10 15:32:08 -04:00
louis-michel
0f112d0685 BCJ executable filter (only for decoding), used by XZ. 2022-06-10 13:29:42 -04:00
Adam Hathcock
fa5c91ecf6 Merge pull request #663 from Nanook/master
Align behavour of 7Zip exception with encrypted filenames arc with rar when no password provided
2022-05-04 08:21:39 +01:00
Nanook
3b2fd1b9fa Merge branch 'adamhathcock:master' into master 2022-05-04 01:36:58 +01:00
Craig
e424094fdf 7z encrypted filename exception with no password matches rar behaviour. 2022-05-04 01:35:58 +01:00
Adam Hathcock
bad9ab2c9d Merge pull request #662 from Nanook/master
Properly integrated zip multivolume and general split support.
2022-05-03 08:23:33 +01:00
Craig
61c01ce9b0 Properly integrated zip multivolume and split support. 2022-04-30 19:35:40 +01:00
Adam Hathcock
3de5df9f38 Merge pull request #661 from Nanook/master
Added multipart Zip support (z01...). Added IEntry.IsSolid
2022-04-29 13:43:37 +01:00
Craig
910aa1c22e Corrected the Crc exception as it was within a #DEBUG define 2022-04-27 14:12:00 +01:00
Craig
71c8f3129f RarStream Position fix, it was returning the file size. 7Zip CrcCheckStream always failed. Added a Solid Rar entry CRC test. 2022-04-27 13:16:05 +01:00
Craig
224614312f Added multipart Zip support (z01...). Added IEntry.IsSolid and implemented Rar and 7Zi[ support. 2022-04-25 01:16:53 +01:00
Adam Hathcock
f717133947 Merge pull request #660 from adamhathcock/dependabot/github_actions/actions/upload-artifact-3
Bump actions/upload-artifact from 2 to 3
2022-04-21 11:16:52 +01:00
dependabot[bot]
fcbfcfed03 Bump actions/upload-artifact from 2 to 3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-21 08:52:47 +00:00
Adam Hathcock
e6601c91ca Merge pull request #659 from adamhathcock/updates
Dependency updates and start of enforcing some C# standards
2022-04-21 09:52:26 +01:00
Adam Hathcock
0379903689 Fix tests 2022-04-21 08:59:35 +01:00
Adam Hathcock
6950eebf9f Dependency updates and start of enforcing some C# standards 2022-04-21 08:54:59 +01:00
Adam Hathcock
c15f1327c9 Merge pull request #658 from Nanook/master
Added Split archive support with unit tests. …
2022-04-21 08:26:06 +01:00
Craig
ec1999f73d Added Split archive support with unit tests. Added ArchiveFactory.IsArchive() and minor refactor. 2022-04-21 00:12:26 +01:00
Adam Hathcock
3d0a18b05d Merge pull request #655 from Ryhon0/master
Tar file mode, user and group
2022-04-11 16:43:40 +01:00
Ryhon
156a02c5a8 Tar file mode, user and group 2022-04-11 14:33:55 +02:00
Adam Hathcock
eba1a443e3 Merge pull request #652 from ds5678/net6_with_trimming
Add a net 6 target and make trimmable
2022-04-11 10:14:18 +01:00
ds5678
eb44cdc903 Update dotnetcore.yml 2022-04-08 02:21:07 -04:00
Jeremy Pritts
196df63de2 fix build project 2022-03-31 14:52:36 -04:00
Jeremy Pritts
ed3c11f44c update workflow and csproj files 2022-03-31 04:04:56 -04:00
Jeremy Pritts
7f6c877fdc add a net 6 target and make trimmable 2022-03-30 21:24:51 -04:00
Adam Hathcock
eee8309db8 Mark for 0.31 2022-03-30 12:03:03 +01:00
Adam Hathcock
155cfab792 Merge pull request #651 from loop-evgeny/evgeny-upgrade-adler32
Update Adler32 from ImageSharp v2.1.0
2022-03-30 12:01:32 +01:00
Evgeny Morozov
e1c36afdec Update Adler32 from ImageSharp v2.1.0
Adler32.cs is taken from 09b2cdb83a with minimal change to make it build as part of SharpCompress. Fixes https://github.com/adamhathcock/sharpcompress/issues/650 and https://github.com/adamhathcock/sharpcompress/issues/645.
2022-03-30 12:17:14 +02:00
Adam Hathcock
6b0d6a41ca Merge pull request #638 from Nanook/rar2MultiWithTest
Rar2 fix with new unit tests that fail on previous build.
2022-02-16 08:33:12 +00:00
Craig
dab157bb71 Rar2 fix with new unit tests that fail on previous build. 2022-02-15 16:24:22 +00:00
Adam Hathcock
8d17d09455 Merge pull request #624 from adamhathcock/issue-617
Add test and probable fix for Issue 617
2021-11-22 09:20:15 +00:00
Adam Hathcock
05208ccd9b Add test and probable fix for Issue 617 2021-11-22 08:40:40 +00:00
Adam Hathcock
a1e7c0068d Merge pull request #622 from adamhathcock/net461-tests
Net461 tests
2021-10-02 15:32:20 +01:00
Adam Hathcock
e6bec19946 Mark for 0.30 2021-10-02 15:29:22 +01:00
Adam Hathcock
ec2be2869f Fix whitespace from dotnet format 2021-10-02 15:29:03 +01:00
Adam Hathcock
ce5432ed73 Fix tests for multi-targetting 2021-10-02 15:25:43 +01:00
Adam Hathcock
b6e0ad89ce Remove duplicated artifact step 2021-10-02 15:21:05 +01:00
Adam Hathcock
2745bfa19b Minor SDK update 2021-10-02 15:19:51 +01:00
Adam Hathcock
3cdc4b38a6 Test 461 on github actions 2021-10-02 15:19:13 +01:00
Adam Hathcock
fc1ca808d7 Merge pull request #621 from inthemedium/master
Add net461 target to clean up issues with system.* nuget dependencies
2021-10-02 15:08:18 +01:00
Jeff Tyson
6983e66037 Fix preprocessor condition 2021-10-01 16:34:00 +00:00
Jeff Tyson
01f7336d09 Based on docs, the target should bet net461 2021-09-29 22:04:47 +00:00
Jeff Tyson
1561bba538 Add net462 target to clean up issues with system.* nuget dependencies 2021-09-29 21:55:11 +00:00
Adam Hathcock
3ecf8a5e0c Merge pull request #616 from amosonn/patch-1
Fix for chunked read for ZLibBaseStream
2021-09-27 09:14:58 +01:00
Adam Hathcock
e2095fc416 Merge branch 'master' into patch-1 2021-09-27 09:08:58 +01:00
Amos Onn
8398d40106 Fix #615 2021-09-14 22:02:18 +02:00
Amos Onn
134fa8892f Test for bug #615 2021-09-14 21:55:05 +02:00
Adam Hathcock
ea5c8dc063 Merge pull request #614 from adamhathcock/ensure-dest-dir-exists
Ensure destination directory exists.
2021-09-12 08:56:42 +01:00
Adam Hathcock
0209d00164 Minor updates and prep for 0.29 2021-09-12 08:52:00 +01:00
Adam Hathcock
a8d065dc9e Ensure destination directory exists 2021-09-12 08:47:30 +01:00
Adam Hathcock
7bd9711ade Merge pull request #610 from cyr/master
Bugfix for TarWriter - too much padding in large files
2021-09-12 08:43:20 +01:00
cyr
61802eadb4 Merge branch 'adamhathcock:master' into master 2021-09-12 09:37:07 +02:00
Adam Hathcock
b425659058 Merge pull request #611 from Thunderstr1k3/fix-zipheader-seeking
Allowing to seek empty zip files
2021-09-12 08:28:05 +01:00
Christian
3e32e3d7b1 Allowing to seek empty zip files 2021-09-02 13:54:32 +02:00
cyr
1b661c9df1 Fixed bug where large (int32+ file size) adds an additional 512 bytes of padding in tar files. 2021-08-27 22:38:04 +02:00
Adam Hathcock
54fc26b93d Update build and mark for 0.28.3 2021-06-04 13:43:35 +01:00
Adam Hathcock
161f99bbad Merge pull request #601 from salvois/master
Write ZIP64 End of Central Directory only if needed.
2021-06-04 13:22:01 +01:00
Adam Hathcock
c012db0776 Merge branch 'master' into master 2021-06-04 13:17:13 +01:00
Adam Hathcock
8ee257d299 Merge pull request #592 from adamhathcock/memory-downgrade
Downgrade System.Memory to fix buffer version issue
2021-06-04 13:16:40 +01:00
Adam Hathcock
f9522107c3 Merge branch 'master' into memory-downgrade 2021-06-04 13:16:34 +01:00
Adam Hathcock
e07046a37a Merge pull request #596 from DannyBoyk/issue_595_conditionally_read_zip64_extra
Conditionally parse Zip64 extra field based on specification
2021-06-04 13:07:08 +01:00
Salvatore Isaja
ad6d0d9ae8 Write ZIP64 End of Central Directory only if needed. 2021-05-23 21:10:35 +02:00
Daniel Nash
fdc33e91bd Conditionally parse Zip64 extra field based on specification
The Zip64 extra field should look for values based on the corresponding
values in the local entry header.

Fixes adamhathcock/sharpcompress#595
2021-04-26 14:58:10 -04:00
Adam Hathcock
a34f5a855c Mark for 0.28.2 2021-04-25 09:29:56 +01:00
Adam Hathcock
6474741af1 Merge pull request #593 from adamhathcock/fix-pkware-encryption
ReadFully used by pkware encryption didn’t like spans
2021-04-25 09:29:02 +01:00
Adam Hathcock
c10bd840c5 ReadFully used by pkware encryption didn’t like spans 2021-04-25 09:25:51 +01:00
Adam Hathcock
e6dded826b Downgrade System.Memory to fix buffer version issue 2021-04-24 09:16:46 +01:00
Adam Hathcock
8a022c4b18 Update FORMATS.md
remove LZipArchive/Reader/Writer mention
2021-03-28 08:58:11 +01:00
Adam Hathcock
cfef228afc Merge pull request #579 from Looooong/fix/do-not-place-extention-classes-in-common-namespace
Do not place extension classes in common namespace
2021-03-18 13:52:40 +00:00
Nguyễn Đức Long
237ff9f055 Do not place extension classes in common namespace 2021-03-18 20:44:04 +07:00
Adam Hathcock
020f862814 Bug fix for recursive call introduced in 0.28 2021-02-18 08:31:50 +00:00
Adam Hathcock
fa6107200d Merge pull request #572 from Erior/feature/521
Not so elegant perhaps for checking 7z encryption
2021-02-16 08:05:08 +00:00
Adam Hathcock
eb81f972c4 Merge branch 'master' into feature/521 2021-02-16 08:01:32 +00:00
Lars Vahlenberg
93c1ff396e Not so elegant perhaps 2021-02-14 16:29:01 +01:00
Adam Hathcock
403baf05a6 Mark for 0.28 2021-02-14 13:07:35 +00:00
Adam Hathcock
a51b56339a Fix complete entry check for RAR files. 2021-02-14 13:00:43 +00:00
Adam Hathcock
f48a6d47dc Merge pull request #571 from Erior/feature/540
Proposal fixing Extra bytes written when setting zip64
2021-02-14 12:54:17 +00:00
Adam Hathcock
5b52463e4c Merge pull request #570 from Erior/feature/555
Propsal for handling Zip with long comment
2021-02-14 12:52:42 +00:00
Adam Hathcock
6f08bb72d8 Merge pull request #569 from BrendanGrant/improve_how_missing_parts_are_handled
Improve how missing parts are handled
2021-02-14 12:49:49 +00:00
Lars Vahlenberg
045093f453 Linux is case sensitive with files names 2021-02-14 10:26:26 +01:00
Lars Vahlenberg
566c49ce53 Proposal
Zip64 requires version 4.5
Number of disks is 4 bytes and not 8
2021-02-14 02:42:32 +01:00
Lars Vahlenberg
d1d2758ee0 Propsal for handling Zip with long comment 2021-02-13 23:57:03 +01:00
Brendan Grant
5b86c40d5b Properly detect if RAR is complete at the end or not 2021-02-13 13:34:57 -06:00
Brendan Grant
53393e744e Supporting reading contents of incomplete files 2021-02-13 13:33:43 -06:00
Adam Hathcock
2dd17e3882 Be explicit about zip64 extra field sizes. Formatting 2021-02-13 07:05:53 +00:00
Adam Hathcock
c4f7433584 Merge pull request #567 from Nanook/master
Zip64 Header and Size fix
2021-02-13 06:58:41 +00:00
Adam Hathcock
9405a7cf4b Merge pull request #568 from Bond-009/stackalloc
Use stackallocs where possible/sensible
2021-02-13 06:39:32 +00:00
Bond_009
cd677440ce Use stackallocs where possible/sensible 2021-02-12 20:20:15 +01:00
Craig Greenhill
c06f4bc5a8 Zip64 Header and Size fix 2021-02-11 09:37:59 +00:00
Adam Hathcock
4a7337b223 Merge pull request #563 from adamhathcock/add-reader-test-gzip
Fix Rewindable stream Length and add GZip Reader tests
2021-01-13 15:13:34 +00:00
Adam Hathcock
1d8afb817e Bump version 2021-01-13 14:41:25 +00:00
Adam Hathcock
0f06c3d934 Fix rewindable stream to expose length 2021-01-13 14:40:36 +00:00
Adam Hathcock
9d5cb8d119 Add GZip Reader tests 2021-01-13 10:42:59 +00:00
Adam Hathcock
a28d686eb9 Fix relavant package references 2021-01-11 12:01:17 +00:00
Adam Hathcock
ac525a8ec2 Merge branch 'master' of github.com:adamhathcock/sharpcompress 2021-01-11 10:01:49 +00:00
Adam Hathcock
52c44befa2 Merge pull request #560 from adamhathcock/gzip-fixes
Expose Last Modified time on GZipStream.  Add CRC and Size to GZipEntries on Archive
2021-01-11 08:57:19 +00:00
Adam Hathcock
c64251c341 Mark for 0.27 2021-01-09 14:04:44 +00:00
Adam Hathcock
bdc57d3c33 Merge pull request #559 from adamhathcock/net5
Use Net5, NetCoreApp3.1, NetStandard2.1, NetStandard2.0 only
2021-01-09 13:43:37 +00:00
Adam Hathcock
7edc437df2 formatting 2021-01-09 13:40:57 +00:00
Adam Hathcock
57e4395e7d Merge branch 'master' into net5
# Conflicts:
#	build/Program.cs
#	src/SharpCompress/Common/Zip/ZipFilePart.cs
2021-01-09 13:40:09 +00:00
Adam Hathcock
ee17dca9e5 Fix formatting 2021-01-09 13:36:30 +00:00
Adam Hathcock
e9f3add5b9 Merge branch 'master' into gzip-fixes 2021-01-09 13:35:52 +00:00
Adam Hathcock
faf1a9f7e4 Merge pull request #561 from adamhathcock/format
Use dotnet format to ensure some kind of code style
2021-01-09 13:35:26 +00:00
Adam Hathcock
5357bd07c7 Let dotnet format do it’s thing 2021-01-09 13:33:34 +00:00
Adam Hathcock
8c0e2cbd25 Use dotnet format 2021-01-09 13:32:14 +00:00
Adam Hathcock
674f3b4f28 Merge branch 'master' into gzip-fixes 2021-01-09 13:25:55 +00:00
Adam Hathcock
6e42e00974 Merge pull request #485 from adamhathcock/issue-256
Create and using PauseEntryRebuilding for adding large numbers of ent…
2021-01-09 13:23:52 +00:00
Adam Hathcock
8598885258 Read trailer for GZip for CRC and uncompressed size 2021-01-09 13:22:06 +00:00
Adam Hathcock
669e40d53c Merge branch 'master' into issue-256 2021-01-09 13:01:16 +00:00
Adam Hathcock
1adcce6c62 Expose Last Modified time on GZipStream 2021-01-09 12:53:13 +00:00
Adam Hathcock
147be6e6e1 Use Net5, NetCoreApp3.1, NetStandard2.1, NetStandard2.0 only 2021-01-09 10:34:49 +00:00
Adam Hathcock
5879999094 Merge pull request #551 from carbon/alder32
Use hardware accelerated Alder32 impl
2020-11-19 08:21:31 +00:00
Jason Nelson
477a30cf5b Use hardware accelerated Alder32 impl 2020-11-18 11:21:29 -08:00
Adam Hathcock
2fec03e1ac Merge pull request #550 from carbon/cq
Improve Code Quality 3
2020-11-18 18:32:53 +00:00
Jason Nelson
9a17449a02 Format NewSubHeaderType 2020-11-18 09:44:13 -08:00
Jason Nelson
087a6aad8c Cross target .NETCOREAPP3.1 and react to new nullablity annotations 2020-11-18 09:43:08 -08:00
Jason Nelson
e243a8e88f Format AbstractArchive 2020-11-18 09:31:39 -08:00
Jason Nelson
b57df8026a Use pattern matching 2020-11-18 09:29:38 -08:00
Jason Nelson
a1d45b44cd Format ArchiveFactory 2020-11-18 09:28:24 -08:00
Jason Nelson
e47e1d220a Format AesDecoderStream 2020-11-18 09:25:38 -08:00
Jason Nelson
0129a933df Remove NETSTANDARD1_3 symbol 2020-11-18 09:23:50 -08:00
Jason Nelson
fa241bb0d7 Inline variable declarations 2020-11-18 09:21:45 -08:00
Jason Nelson
d8804ae108 Improve conditional logic to prepare to add .NETCOREAPP target 2020-11-18 09:19:21 -08:00
Jason Nelson
8090d269e7 Add polyfills for string.EndWith(char) && string.Contains(char) 2020-11-18 09:16:53 -08:00
Jason Nelson
b0101f20c5 Eliminate culture specific StartsWith comparisions 2020-11-18 09:12:01 -08:00
Jason Nelson
dd48e4299a Simplify .NET framework code exclusions, bump min .NET framework version to 4.6.1 2020-11-18 09:07:30 -08:00
Jason Nelson
c61ee0c24f Update deps 2020-11-18 09:02:11 -08:00
Jason Nelson
9576867c34 Enable C# 9 2020-11-18 09:01:35 -08:00
Adam Hathcock
4426a24298 Merge pull request #549 from adamhathcock/update-deps
Update dependencies
2020-11-03 08:47:58 +00:00
Adam Hathcock
3b43c1e413 Update dependencies 2020-11-03 08:45:10 +00:00
Adam Hathcock
aa6575c8f9 Merge pull request #541 from avao/master
UT and Fix for: Index out of range exception from gzip #532
2020-10-19 12:33:31 +01:00
avao
0268713960 UT and Fix for: Index out of range exception from gzip #532 2020-10-13 19:58:11 +01:00
Adam Hathcock
f36167d425 Merge pull request #531 from carbon/master
Improve CQ3
2020-08-01 06:25:09 +01:00
Jason Nelson
33ffcb9308 Use Array.Empty<byte> 2020-07-31 17:00:46 -07:00
Jason Nelson
a649c25a91 Eliminate two allocations in HuffmanTree 2020-07-31 16:58:21 -07:00
Jason Nelson
fa1e773960 Eliminate two allocations in Crc32 2020-07-31 16:55:07 -07:00
Jason Nelson
62f7238796 Make CMethodId readonly 2020-07-31 16:49:34 -07:00
Jason Nelson
d4ccf73340 Embed FAST_ENCODER_TREE_STRUCTURE_DATA 2020-07-31 16:47:05 -07:00
Jason Nelson
5ddb0f96bc Use switch expressions 2020-07-31 16:37:56 -07:00
Jason Nelson
75a6db8f4c Eliminate three allocations in HbMakeCodeLengths 2020-07-31 16:33:00 -07:00
Jason Nelson
ae5635319b Eliminate header bytes allocation 2020-07-31 16:30:26 -07:00
Jason Nelson
98ed3080d0 Eliminate three allocations 2020-07-31 16:30:09 -07:00
Jason Nelson
c618eacad4 Optimize RijndaelEngine 2020-07-31 16:22:44 -07:00
Jason Nelson
3b11e6ef97 Eliminate two allocations 2020-07-31 16:10:59 -07:00
Jason Nelson
40af9359db Pollyfill and use Stream.Read(Span<byte> buffer) 2020-07-31 16:08:38 -07:00
Jason Nelson
d6bf9dae42 Eliminate allocation 2020-07-31 16:01:09 -07:00
Adam Hathcock
13917941ff Merge pull request #530 from carbon/master
Enable test coverage for net461 and fix regression
2020-07-31 18:39:40 +01:00
Jason Nelson
28f04329ae Merge branch 'master' of https://github.com/carbon/sharpcompress 2020-07-31 10:12:37 -07:00
Jason Nelson
404a6b231d Fix .NET 461 failures 2020-07-31 10:12:34 -07:00
Jason Nelson
184596da3c Merge branch 'master' into master 2020-07-31 11:37:45 -05:00
Jason Nelson
f00f393687 Disable failing net461 tests 2020-07-31 09:30:20 -07:00
Jason Nelson
cbbfb89619 Add failure notes 2020-07-31 09:29:06 -07:00
Jason Nelson
6a5cf11dd0 Fix net461 bug 2020-07-31 09:27:41 -07:00
Jason Nelson
fc1d0a0464 Run tests against net461 2020-07-31 09:27:32 -07:00
Adam Hathcock
74af1759eb Merge pull request #529 from carbon/master
Improve code quality v2
2020-07-31 06:55:35 +01:00
Jason Nelson
ee3162ad71 Fix return 2020-07-30 17:49:29 -07:00
Jason Nelson
4357165163 Add Read/Write overrides to NonDisposingStream 2020-07-30 17:36:03 -07:00
Jason Nelson
6973436b94 Add and use Stream.Write(ReadOnlySpan<byte> buffer) polyfill 2020-07-30 17:29:33 -07:00
Jason Nelson
7750ed7106 Finish spanification of RijndaelEngine 2020-07-30 17:01:13 -07:00
Jason Nelson
773158e9d8 Seal LZipStream 2020-07-30 16:57:30 -07:00
Jason Nelson
4db615597d Refactor ExtraData and enable nullable 2020-07-30 16:48:22 -07:00
Jason Nelson
6bdf2365fc Inline variable declarations 2020-07-30 16:45:38 -07:00
Adam Hathcock
a7944f28c5 Fix CI again 2020-07-26 14:45:32 +01:00
Adam Hathcock
426d459284 Fix CI build 2020-07-26 14:39:13 +01:00
Adam Hathcock
b00b461ada Update documented targets 2020-07-26 14:38:19 +01:00
Adam Hathcock
84834b6348 ignore snukpkg 2020-07-26 14:36:42 +01:00
Adam Hathcock
f521fd35ff Fix tests, update to 0.26 2020-07-26 14:36:07 +01:00
Adam Hathcock
2979fceecf Merge pull request #522 from JTOne123/master
[PR] The proj files have been updated to enable SourceLink
2020-07-26 12:07:13 +01:00
Adam Hathcock
b12e8e793f Merge branch 'master' into master 2020-07-26 12:07:05 +01:00
Adam Hathcock
c77ec59a28 Merge pull request #527 from adamhathcock/default-encoding
Don’t use 437 Encoding by default anymore.
2020-07-26 12:06:30 +01:00
Adam Hathcock
42ba8cf828 Merge branch 'master' into default-encoding 2020-07-26 12:06:22 +01:00
Adam Hathcock
c7618fc895 Merge pull request #528 from DannyBoyk/issue_524_tararchive_fails_read_all_entries
Ensure TarArchive enumerates all entries
2020-07-26 12:05:58 +01:00
Daniel Nash
d055b34efe Ensure TarArchive enumerates all entries
While enumerating the entries of a tar file and writing their contents
to disk using TarArchive, it was discovered TarArchive was not properly
discarding padding bytes in the last block of each entry. TarArchive was
sometimes able to recover depending on the number of padding bytes due
to the logic it uses to find the next entry header, but not always.

TarArchive was changed to use TarReadOnlySubStream when opening entries
and TarReadOnlySubstream was changed to ensure all an entry's blocks are
read when it is being disposed.

Fixes adamhathcock/sharpcompress#524
2020-07-20 12:57:39 -04:00
Adam Hathcock
b7f635f540 Update readme 2020-07-16 15:35:27 +01:00
Adam Hathcock
5e95a54260 Merge branch 'master' into default-encoding 2020-07-16 14:32:51 +01:00
Adam Hathcock
4354e82bb5 Don’t use 437 Encoding by default anymore. 2020-07-16 14:28:37 +01:00
Adam Hathcock
ab7bdc24dc Merge pull request #523 from kdaadk/master
Decompress multipart solid RAR4.x archive
2020-07-01 12:56:58 +01:00
Dmitriy
81997fe1ba rename test 2020-07-01 15:10:21 +05:00
Dmitriy
de6759a83f - remove check of solid archive
- change tests
- add test on multi solid archive
2020-07-01 15:06:54 +05:00
Adam Hathcock
233dc33130 Fix running tests on build 2020-06-25 09:22:15 +01:00
Adam Hathcock
39b07f45f1 Update github action and minor SDK bump 2020-06-25 09:16:15 +01:00
Pavlo Datsiuk
802662a165 [COMMIT] The proj files have been updated to enable SourceLink [SharpCompress.csproj] 2020-06-25 10:58:21 +03:00
Adam Hathcock
2859848fc4 Give the artifacts names 2020-05-24 10:41:06 +01:00
Adam Hathcock
b734d00062 Remove README for appveyor and fix artifacts again 2020-05-24 10:35:39 +01:00
Adam Hathcock
02a17d22f6 Adjust artifacts and remove appveyor 2020-05-24 10:32:50 +01:00
Adam Hathcock
7bfff472c6 Fix yaml 2020-05-24 10:26:51 +01:00
Adam Hathcock
5aa146be17 Remove matrix var 2020-05-24 10:25:40 +01:00
Adam Hathcock
a0bfc22a29 Try upload artifact 2020-05-24 10:23:01 +01:00
Adam Hathcock
6ed46b5fcc Fix CI paths 2020-05-24 09:04:10 +01:00
Adam Hathcock
904e40ef57 Switch to bullseye for building 2020-05-24 09:00:27 +01:00
Adam Hathcock
00ff119ec4 Minor Rider issues resolved. Still two outstanding. 2020-05-24 08:42:36 +01:00
Adam Hathcock
60d2511e80 Remove .NET Standard 1.3 which is no longer in support 2020-05-24 08:42:06 +01:00
Adam Hathcock
ed56a4aa4a Merge pull request #515 from carbon/master
Enable nullable
2020-05-24 08:20:37 +01:00
Jason Nelson
5b6a1c97e3 Enable nullable 2020-05-23 16:27:55 -07:00
Adam Hathcock
8bfc9ef4de Update for 0.25.1 2020-05-22 13:46:36 +01:00
Adam Hathcock
fa949e089e Merge pull request #512 from adamhathcock/fix-codepages
Attempt Windows reference fix
2020-05-22 13:44:10 +01:00
Adam Hathcock
c296ca7660 Merge pull request #513 from RealOrko/symbolic-link-default-write
Added default implementation with warning for symbolic links
2020-05-22 13:43:56 +01:00
RealOrko
538b38869f Added a warning for the writing of symbolic links with a link to the original GitHub issue for the DOTNET runtime 2020-05-21 13:00:25 +01:00
Adam Hathcock
ce328ed90b Merge branch 'master' into fix-codepages 2020-05-15 08:28:25 +01:00
Adam Hathcock
632bae725d Add braces for clarity 2020-05-14 13:47:21 +01:00
Adam Hathcock
4f824b1d9a Add build flags for Core targets 2020-05-14 13:16:00 +01:00
Adam Hathcock
120aee8039 See if windows reference is fixed 2020-05-14 13:09:17 +01:00
Adam Hathcock
3b2b341c4d Merge pull request #508 from turbedi/minor_optimizations
Minor optimizations
2020-04-11 09:08:07 +01:00
Berkan Diler
4cad40f637 Minor string optimizations 2020-04-10 12:33:40 +02:00
Berkan Diler
2c64380019 Use 3 argument Array.Copy when possible 2020-04-10 12:06:38 +02:00
Berkan Diler
ccb9593de2 Replace Span<T>.Fill(0) with Span<T>.Clear() 2020-04-10 12:03:32 +02:00
Berkan Diler
921a99fc32 Replace static readonly byte[] fields with static ReadOnlySpan<byte> properties 2020-04-10 11:54:58 +02:00
Adam Hathcock
400d2c1774 Fix usings and add braces for better merging 2020-04-03 08:47:30 +01:00
Adam Hathcock
762497b1c1 Tag for 0.25.0 and update packages 2020-04-03 08:25:43 +01:00
Adam Hathcock
be9edc7512 Merge pull request #500 from Erior/Issue_86
ZipReader/StreamingZipReaderFactory fails for archive entries which are uncompressed files in ZIP format #86
2020-01-17 09:38:19 +00:00
Lars Vahlenberg
9bf9d34d94 Issue86 Proposal 2020-01-16 22:08:48 +01:00
Adam Hathcock
df8405006c Fix workflow name 2020-01-03 09:24:08 +00:00
Adam Hathcock
d135fdce58 Give github actions build a name and use badge 2020-01-03 09:22:51 +00:00
Adam Hathcock
ba570b93bb Merge pull request #496 from Bond-009/allocations
Reduce the amount of allocations
2020-01-03 09:18:17 +00:00
Adam Hathcock
6dfe0c7a96 Merge branch 'master' into allocations 2020-01-03 09:16:46 +00:00
Adam Hathcock
73d4430a65 Merge pull request #498 from adamhathcock/build-netcore3
Build netcore3
2020-01-03 09:15:14 +00:00
Adam Hathcock
ce6fd9b976 JUst one target 2020-01-03 09:12:10 +00:00
Adam Hathcock
ae7e8c03f2 Put wrong SDK 2020-01-03 09:07:34 +00:00
Adam Hathcock
22e2526f4c Update cake and dependencies 2020-01-03 09:06:13 +00:00
Adam Hathcock
50283d9411 Add new build targets for netcore3 2020-01-03 09:02:04 +00:00
Bond-009
d2c2b58f3b Fix language version and add netstandard2.1 2020-01-02 17:43:58 +01:00
Bond_009
50d4b39ca0 Fix test 2019-12-30 22:17:45 +01:00
Bond_009
1ed675e960 Minor improvement 2019-12-30 19:19:05 +01:00
Bond_009
80b0671844 Reduce the amount of allocations
* Directly fill an array instead of filling a List and copying that to
an array
* Use own buffer when writing bytes to a stream
* Remove DataConverter class, replaced by BinaryPrimitives
2019-12-30 18:58:25 +01:00
Bond-009
6f387336c0 Use functions from System.Memory instead of selfmade ones (#495)
* Use functions from System.Memory instead of selfmade ones

* Update SharpCompress.Test.csproj
2019-12-30 15:19:46 +00:00
Adam Hathcock
3b2e273832 Merge branch 'master' into issue-256 2019-10-10 09:27:46 +01:00
Adam Hathcock
9540b01bcc NET Standard 1.3 and 2.0 only (#482)
* Remove NET35, NET45 and NET Standard 1.0

* Update README and memset

* Remove NETCORE build flag

* NET 46 too?

* Update packages and usage
2019-10-10 09:24:41 +01:00
Adam Hathcock
43c839eb89 Create and using PauseEntryRebuilding for adding large numbers of entries 2019-10-09 09:55:16 +01:00
Adam Hathcock
446d6914c1 Merge pull request #483 from Bond-009/nameof
Use nameof for param names
2019-09-17 14:21:04 +01:00
Bond_009
637223aa53 Use nameof for param names 2019-09-17 13:28:44 +02:00
Adam Hathcock
17d5565120 Merge pull request #478 from Bond-009/buffers
Use System.Buffers Nuget package
2019-09-17 10:05:29 +01:00
Bond_009
4b54187b4c Fix build 2019-09-11 21:33:57 +02:00
Bond_009
cfb1421367 Use System.Buffers Nuget package 2019-09-11 20:06:50 +02:00
Adam Hathcock
5072a0f6f5 Merge pull request #471 from adamhathcock/release-024
Bump version and dependencies
2019-08-20 20:36:38 +01:00
Adam Hathcock
357dff1403 Bump version and dependencies 2019-08-20 14:29:47 -05:00
Adam Hathcock
a2bd66ded8 Merge pull request #460 from itn3000/tar-fix-garbled2
fix filename garbling in tar(#414)
2019-06-27 12:16:53 +01:00
itn3000
6bfa3c25a4 add more comments 2019-06-27 20:01:40 +09:00
itn3000
1ea9ab72c1 add comment for subtracting 2019-06-27 19:59:16 +09:00
itn3000
07c42b8725 replace magic number 2019-06-27 10:59:21 +09:00
itn3000
70392c32e2 use Buffer.BlockCopy for performance 2019-06-27 09:47:26 +09:00
itn3000
9b4b2a9f7c considering encoding in processing filename(#414)
modify test tar archive because it was not expected one.
(expected "тест.txt" in encoding 866, but actual is omitted upper byte)
2019-06-26 17:34:12 +09:00
Adam Hathcock
d3dd708b58 Merge pull request #457 from DannyBoyk/issue_456_zip_bounded_substreams_data_descriptors
Return a bounded substream when data descriptors are used in seekable zips
2019-06-04 13:42:24 +01:00
Daniel Nash
af264cdc58 Return a bounded substream when data descriptors are used in seekable zips 2019-06-04 08:31:42 -04:00
Adam Hathcock
cfd6df976f Merge pull request #455 from DannyBoyk/issue_454_zip_bad_extra_field
Handle a bad extra field in a local file header in zip files
2019-06-04 09:24:55 +01:00
Daniel Nash
b2bd20b47e Handle a bad extra field in a local file header in zip files 2019-06-03 13:02:28 -04:00
Adam Hathcock
ffea093e95 Merge pull request #453 from Lssikkes/master
Fix for clients failing on just having a 64 bit offset in ZIP64
2019-05-24 19:33:59 +01:00
Leroy Sikkes
78eb8fcf92 Fix for clients that don't support ZIP64 standard correctly in case headers are only pointed to in ZIP64 directory structure 2019-05-24 18:27:49 +02:00
Adam Hathcock
a052956881 Merge pull request #452 from Lssikkes/master
Various fixes for ZIP64 writer (zero byte entries, 32 bit where supported)
2019-05-24 16:17:48 +01:00
Lssikkes
9319ea6992 Updated ZIP64 writer to write 32 bit values to directory entries for better compatibility.
Support for zero byte files without corruption errors from WinRAR/7-zip
2019-05-24 16:14:30 +02:00
Adam Hathcock
4e5b70dbfa Merge pull request #444 from eugeny-trunin/mem-opt
Memory and speed optimization
2019-03-20 15:13:00 +00:00
evgeny
c68eaa8397 Memory and speed optimization 2019-03-20 17:46:57 +03:00
Adam Hathcock
bbb7c85ba7 Merge pull request #442 from turbolocust/master
Fix: ArchiveEncoding was ignored in TarWriterOptions
2019-03-19 08:31:31 +00:00
Matthias Fussenegger
8174359228 Fix: ArchiveEncoding was ignored in TarWriterOptions 2019-03-18 18:25:00 +01:00
Adam Hathcock
acf66c5195 Merge pull request #440 from adamhathcock/release-023
Bump release for 0.23 and update dependencies
2019-02-27 12:57:30 +00:00
Adam Hathcock
880c9fa97a Bump release and update dependencies 2019-02-27 12:55:16 +00:00
Adam Hathcock
e5c111f2be Merge pull request #436 from Numpsy/populate_zip_volume_comment
Changes to populate ZipArchive.ZipVolumne.Comment
2019-01-14 08:14:03 +00:00
Richard Webb
4e9cd064dd Unit test to show reading of a Zip volume/archive comment 2019-01-13 21:05:55 +00:00
Richard Webb
12a6d3977e Return the DirectoryEndHeader from SeekableZipHeaderFactory.ReadSeekable so that it can be used by ZipArchive 2018-12-14 22:44:44 +00:00
Adam Hathcock
a95bbaf820 Merge pull request #423 from markfinal/tarsymlink
Tar symlink support
2018-11-05 08:31:48 +00:00
Mark Final
70bafa653b Tar symlink extraction
Extended SharpCompress.Common.ExtractionOptions with a delegate to write symbolic links. If not is null, and a symbolic link is encountered, an exception is thrown.
Removed Mono.Posix.NETStandard from the library, but added to the .NET Core 2.1 test application.
Extended the test to implement the delegate.
2018-11-03 09:45:12 +00:00
Mark Final
3f4338489c Removed unnecessary code 2018-11-01 21:57:49 +00:00
Mark Final
d91e58f2cc Refs #248. Refs #132. Added a test case of a tar containing symlinks
This is a source archive of the MoltenVK project from github, which is my use-case for SharpCompress.
I added a test case in the project, which should extract the tar, and validate any symlink targets with what the tar thinks it ought to be.
2018-11-01 21:51:14 +00:00
Mark Final
192b9c1e8b Ref #248. Ref #132. Tar reader support for symlinks for .NET standard 2 and Posix platforms
Extracts linkname from the tar header, and exposes this on IEntry as the LinkTarget (string) property. If an entry is not a symlink, then that property is null.

Uses Mono.Posix.NETStandard nuget to create a symlink. However, this is only applicable to .NET standard 2.0+. So far, unable to find a nuget that works for older versions.

Also, not sure what to do on Windows.
2018-11-01 21:48:51 +00:00
Adam Hathcock
0941239454 Merge pull request #417 from KyotoFox/fix-entrystream-flush
Allow Flush on EntryStream
2018-10-04 12:48:08 +01:00
Knut Ørland
53ad00cdc4 Use soft tabs 2018-10-04 13:13:14 +02:00
Knut Ørland
6dd5da48f7 Added test that calls EntryStream.Flush() 2018-10-04 13:08:53 +02:00
Knut Ørland
efae8328a9 Don't throw an exception when flushing an EntryStream
From Microsoft docs: “In a class derived from Stream that doesn't
support writing, Flush is typically implemented as an empty method to
ensure full compatibility with other Stream types since it's valid to
flush a read-only stream.”
2018-10-04 13:05:36 +02:00
Adam Hathcock
f1facc51de Merge pull request #409 from G-Research/RecogniseEmptyTarArchives
Recognise empty tar archives.
2018-09-25 13:20:59 +01:00
Adam Hathcock
a471ca6a76 Use Cake tool on circle. Update test packages 2018-08-31 09:27:04 +01:00
Elliot Prior
83f6690576 Recognise empty tar archives.
Currently, when ArchiveFactory.Open is called on an empty tar archive, it throws due to being unable to determine the stream type. This fix allows it to recognise empty tar files by checking for whether the filename is empty, the size is empty and the entry type is defined. Add a test to try opening an empty archive.
2018-08-16 10:25:47 +01:00
Adam Hathcock
1850ea67f6 Merge pull request #408 from majoreffort/master
Test and fix for #407
2018-07-24 09:42:03 +01:00
majoreffort
2fd6178aa9 Fixed length in TarHeader#WriteStringBytes 2018-07-23 19:58:37 +02:00
majoreffort
ec044e6f42 Added Tar test for 100 char filename issue. 2018-07-23 19:48:01 +02:00
Adam Hathcock
bd96279649 Merge pull request #404 from MattKotsenas/bugfix/idisposable
Enable parallel test execution
2018-07-12 19:53:50 +01:00
Matt Kotsenas
f7ad595945 Enable test parallelization and remove garbage collection workaround
Now that the sources of file locking are fixed, enable test parallelization
and the forced garbage collection workaround.

Lastly, remove the `IsLocked` check because it doesn't work in a
parallel test running world - the file may be locked due to another test
running.
2018-07-12 10:33:19 -07:00
Matt Kotsenas
93c0b91de9 Refactor TestSharpCompressWithEmptyStream
Refactor `TestSharpCompressWithEmptyStream` so it asserts that the files
and bytes are the same.
2018-07-12 10:32:08 -07:00
Matt Kotsenas
138038b08f Move RarReaderTests over to user ReaderFactory
- Refactor `RarReaderTests` to use `ReaderFactory`
- Update `ReaderTests.Read` to support Rar tests
2018-07-12 10:32:08 -07:00
Matt Kotsenas
e9a6fed607 FIXUP decouple UseReader from VerifyFiles 2018-07-11 16:53:34 -07:00
Matt Kotsenas
87a1440382 Decouple UseReader from VerifyFiles 2018-07-11 16:49:49 -07:00
Matt Kotsenas
3c2f4ebe9b Combine ForwardOnlyStream and NonSeekableStream
Delete `NonSeekableStream` used in Zip64 tests in favor
of `ForwardOnlyStream` used in Mocks.

Additionally, delete the `ForwardOnlyStream.ReadByte` implementation
as the implementation on the base Stream is sufficient.
2018-07-11 16:42:03 -07:00
Matt Kotsenas
933ffe7828 Remove unused code from ArchiveTests 2018-07-11 16:33:46 -07:00
Matt Kotsenas
7d20ba5243 Simplify RarHeaderTests 2018-07-11 16:21:19 -07:00
Matt Kotsenas
44dc36af48 Update ReaderTests base class to validate Dispose
Update the `ReaderTests` base class to validate that `Dispose` is
called appropriately in both the close and the leave open cases.
2018-07-11 16:21:19 -07:00
Matt Kotsenas
98558c5ba9 Refactor TestStream constructor
Refactor the `TestStream` constructor so by default it defers to
the underlying Stream
2018-07-11 16:21:19 -07:00
Matt Kotsenas
6c25322465 Follow best-practices for Dispose in Volume and ForwardOnlyStream
Update `Volume` and `ForwardOnlyStream` to follow the project's
general pattern and best-practices for `Dispose`
2018-07-11 16:21:19 -07:00
Matt Kotsenas
6d1d62fd32 Delete AppendingStream
`AppendingStream` is unused, so rather than refactor it, just delete it.
2018-07-11 16:21:19 -07:00
Matt Kotsenas
ee4ae661d7 Refactor ListeningStream
Refactor `ListeningStream`:

- Override of `WriteByte` was redundant and removed
- Make `Dispose` delegate to base class
2018-07-11 16:21:19 -07:00
Matt Kotsenas
0473ec1626 Open test archives as read
Update `RarHeaderFactoryTests` and `GZipArchiveTests` to open the test
readers as `FileAccess.Read` and `FileShare.Read` to prevent issues with
multiple test from trying to open exclusive access to files.
2018-07-11 16:21:19 -07:00
Matt Kotsenas
c6cf0d40ee Simplify ReaderTests
The `IEnumerable<string>` version of `ReaderTests` is unused, so delete
it to simplify the code.
2018-07-11 16:21:19 -07:00
Matt Kotsenas
4cd80e96f3 Simplify GZip bad compression test 2018-07-11 16:21:19 -07:00
Matt Kotsenas
16524717ba Fix Stream leak in ArchiveFactory
`ArchiveFactory.Open` has two overloads that take `string` or
`FileInfo` (string delegates to FileInfo). Both of these implementations
open a `Stream` with the default `ReaderOptions`, which leaves the
stream open, resulting in a leak.

The fix is to set `LeaveOpen` to `false` if no options were provided.
Note that if a user was provding options and `LeaveOpen` was set to
`true`, the code did and will still leak.
2018-07-11 16:21:19 -07:00
Matt Kotsenas
cab1ce3d0c Update sub-streams to uniformly inherit from NonDisposingStream
Update the sub-stream classes to all inherit from `NonDisposingStream`.
This allows them to correctly implement the `Dispose` pattern, and delegate
the actual disposal to `NonDisposingStream`.

In doing so, we need to remove some redundant overrides from
`NonDisposingStream`, otherwise `BufferedSubStream` would use the
overrides inherited from `NonDisposingStream` instead of the ones
inherited from `Stream` (i.e. delegate `ReadByte` to `Read`).
2018-07-11 16:17:49 -07:00
Matt Kotsenas
6c2e5e1164 Cleanup NonDisposingStream for reuse
- Remove the duplicate `GC.SuppressFinalization` call
(called in `System.IO.Stream)
- Improve the `ThrowOnDispose` error message
2018-07-11 12:19:34 -07:00
Matt Kotsenas
c2bf540057 Close verification streams in TestBase.CompareArchivesByPath 2018-07-11 12:12:30 -07:00
Matt Kotsenas
a35c66e166 Move RewindableStreamTest.cs to the Streams/ folder 2018-07-10 12:07:33 -07:00
Matt Kotsenas
084c5e2686 Rename StreamTests.cs --> LzmaStreamTests.cs 2018-07-10 12:07:32 -07:00
Matt Kotsenas
6ae715b153 Move the TestStream and ForwardOnlyStream to Mocks folder
Move the `TestStream` and `ForwardOnlyStream` to Mocks/ to separate them
from the test classes.
2018-07-10 12:07:32 -07:00
Adam Hathcock
9c8692806a Merge pull request #403 from MattKotsenas/bugfix/parallel-tests
Fix and re-enable tests
2018-07-10 20:01:20 +01:00
Matt Kotsenas
2d87351d2a Add tests back to AppVeyor 2018-07-10 11:52:00 -07:00
Matt Kotsenas
3114afde0e Add workaround for in-use files
The `TestBase` is not always able to delete the scratch folder in
`Dispose()` because sometimes the files are still in use.

This problem appears to be leaked file handles (likely due to incorrect
handling of `IDisposable`). To avoid the problem for now, force a
garbage collection prior to deleting the scratch folder.
2018-07-10 11:49:38 -07:00
Matt Kotsenas
7b338511cc Create unique scratch path per test
Tests fail in Visual Studio because they try to reuse the same scratch
working space, and each test is responsible for resetting the space. To
simplify the test code:

1. Make `TestBase` `IDisposable` and have it create the scratch space
2. Remove `ResetScratch()` as it is now handled by the base class
3. Add a unique ID to each scrach space folder to prevent collisions
2018-07-10 11:46:44 -07:00
Adam Hathcock
09c27681e1 Merge pull request #402 from a764578566/master
file search support linq Pattern
2018-07-10 13:21:09 +01:00
zhoujr
4ebc1f82b7 file search support linq Pattern 2018-07-10 19:58:59 +08:00
Adam Hathcock
4640ca497a Merge pull request #400 from MattKotsenas/feature/avoid-exception-in-readerfactory
Avoid throwing NotSupportedException in ReaderFactory hot path
2018-07-10 08:47:13 +01:00
Matt Kotsenas
bebccaae28 Avoid throwing NotSupportedException in ReaderFactory hot path
`ReaderFactory.Open()` calls `ZipArchive.IsZipFile()` to determine if
the `Stream` is a zip archive, which calls into
`ZipHeaderFactory.ReadHeader()`, which throws a `NotSupportedException`
when the `Stream` is not a zip archive.

To be clear, this exception is caught and `IsZipFile()` returns `false`,
but when called in a hot-path, these exceptions can become expensive.

To address this issue, `ReadHeader` now returns `null` in the default
cause instead of throwing. All callsites were already checking for and
handling `null`, so no behavior changes.
2018-07-09 18:44:46 -07:00
Adam Hathcock
7ee53373c6 Remove tests as AppVeyor can’t handle them at the moment 2018-07-09 09:05:10 +01:00
Adam Hathcock
d577fe1ac6 Merge pull request #385 from twirpx/master
Fixed EFS flag handling
2018-07-09 08:48:34 +01:00
Adam Hathcock
9f976aaf78 Merge branch 'master' into master 2018-07-09 08:48:26 +01:00
Adam Hathcock
8a7d7e366f Merge pull request #396 from andreas-eriksson/Rar5IsEncrypted
Correctly set IsEncrypted for entries in Rar5.
2018-07-09 08:48:12 +01:00
Adam Hathcock
540ab1c6fa Merge branch 'master' into master 2018-07-09 08:47:32 +01:00
Adam Hathcock
6792afbdb1 Merge branch 'master' into Rar5IsEncrypted 2018-07-09 08:44:32 +01:00
Adam Hathcock
e5a7185671 Mark for 0.22 2018-07-09 08:42:45 +01:00
Adam Hathcock
cdaf453b2d Update dependencies and tests to .NET Core 2.1 2018-07-09 08:39:37 +01:00
Andreas Eriksson
f9cc80e1de Correctly set IsEncrypted for entries in Rar5. 2018-06-29 15:51:40 +02:00
Adam Hathcock
7beff9e83c Merge pull request #395 from adamhathcock/zip-slip-readers
Zip slip for Readers
2018-06-28 11:56:44 +01:00
Adam Hathcock
8f49f1b6f8 Merge remote-tracking branch 'origin/master' into zip-slip-readers 2018-06-28 11:52:43 +01:00
Adam Hathcock
7e336a0247 Slip in new SDK 2018-06-28 11:51:17 +01:00
Adam Hathcock
e37e8bdadc Move path handling for extraction to be common
Reader and Archive now share more extraction logic
2018-06-28 11:46:51 +01:00
Adam Hathcock
40bd61b16b Merge pull request #389 from frankyjuang/patch-1
Fix comment
2018-06-08 08:59:52 +01:00
Juang, Yi-Lin
87fbb45099 Fix comment 2018-06-08 11:27:43 +08:00
twirpx
e822f9a95c Tests fixed to use explicit use of 866 encoding because of usage file named in Russian in several tests 2018-05-30 22:17:27 +05:00
twirpx
8a5a9159e1 Fixed DirectoryEntryHeader Name/Comment decoding in case of EFS flags set 2018-05-30 21:47:31 +05:00
twirpx
73b3c6b419 Merge branch 'master' of https://github.com/adamhathcock/sharpcompress 2018-05-30 20:28:15 +05:00
Adam Hathcock
f9bd7ebdb0 Merge pull request #384 from MrJul/perf-readbyte
Implemented ReadByte/WriteByte on streams to improve performance
2018-05-28 09:21:28 +01:00
Julien Lebosquain
540618c062 Implemented ReadByte/WriteByte on streams to improve performance 2018-05-27 16:31:44 +02:00
Adam Hathcock
9e96dec8c9 Merge pull request #383 from itn3000/add-filename-encoding-example
add example for custom file encoding
2018-05-23 09:14:46 +01:00
itn3000
7b7af612ba add example for custom file encoding 2018-05-23 09:46:36 +09:00
Adam Hathcock
3a747ba87e Update USAGE with new stream handling 2018-05-16 08:51:33 +01:00
Adam Hathcock
87e57e3a9a Mark for 0.21.1 2018-05-15 09:14:56 +01:00
Adam Hathcock
785d0dcebf Merge pull request #381 from adamhathcock/issue-380
Allow forced encoding to override default encoding
2018-05-15 09:13:16 +01:00
Adam Hathcock
2314776f55 Also check for CustomDecoder 2018-05-15 08:28:11 +01:00
Adam Hathcock
473f5d8189 Make GetDecoder use GetEncoding for forced 2018-05-14 16:20:57 +01:00
Adam Hathcock
be971cb6f7 Allow forced encoding to override default encoding 2018-05-14 16:08:31 +01:00
Adam Hathcock
3f94c1a50d Remove lingering uses of non disposing stream 2018-05-08 14:10:49 +01:00
Adam Hathcock
2919ec293a mark for 0.21 2018-05-06 09:39:36 +01:00
Adam Hathcock
19d25152e5 Merge pull request #378 from adamhathcock/fix_crypto_namespace
Fix namespaces to not interfere with bouncy castle users
2018-05-06 09:20:17 +01:00
Adam Hathcock
747180203c Rider isn’t quite good enough in refactoring 2018-05-06 09:12:18 +01:00
Adam Hathcock
9f89a0844d Fix namespaces to not interfere with bouncy castle users 2018-05-06 09:09:45 +01:00
Adam Hathcock
c64282e915 more naming 2018-05-06 09:07:06 +01:00
Adam Hathcock
c44a80bab2 Merge remote-tracking branch 'origin/master' 2018-05-06 08:59:23 +01:00
Adam Hathcock
8dfc4a2ffb more variable naming 2018-05-06 08:59:00 +01:00
Adam Hathcock
c341c626a5 variable naming clean up 2018-05-06 08:49:32 +01:00
Adam Hathcock
173a0fe659 Some naming clean up 2018-05-05 19:35:58 +01:00
Adam Hathcock
5fdae1cf82 Make readonly and fix visibility 2018-05-05 19:23:34 +01:00
Adam Hathcock
9e892ab397 Merge pull request #376 from leezer3/master
Fix broken link in usage.md
2018-05-05 16:18:17 +01:00
Christopher Lees
e95559b4fc Fix broken link in usage.md 2018-05-05 15:08:56 +01:00
Adam Hathcock
18475cc86d Use proper xunit single threading 2018-05-05 09:38:56 +01:00
Adam Hathcock
88b59600cd Merge pull request #369 from adamhathcock/leaveOpen
Rework LeaveOpen to be consistent
2018-05-05 09:27:32 +01:00
Adam Hathcock
9a9d64bcbe Merge branch 'master' into leaveOpen
# Conflicts:
#	src/SharpCompress/Compressors/LZMA/LZipStream.cs
2018-05-05 09:25:26 +01:00
Adam Hathcock
4f3408ec25 Merge pull request #375 from adamhathcock/issue_360
Fixes lzip stream disposal
2018-05-05 09:20:35 +01:00
Adam Hathcock
e9d0fb85ac Merge branch 'master' into leaveOpen 2018-05-05 09:19:38 +01:00
Adam Hathcock
1ce37ef7a8 Fixes lzip stream disposal 2018-05-05 09:18:01 +01:00
Adam Hathcock
ecad356e30 Merge pull request #363 from sridhar6668/sridhar6668/support_extended_ascii
ZipArchive Reader: Uses IBM PC character encoding to decode filename …
2018-05-05 09:12:22 +01:00
Adam Hathcock
fafd8da91d Merge branch 'master' into leaveOpen 2018-05-05 09:10:19 +01:00
Adam Hathcock
2fb31d4b84 Merge branch 'master' into sridhar6668/support_extended_ascii 2018-05-05 09:09:09 +01:00
Adam Hathcock
8b478451ac Evil zip is a windows only test because of paths 2018-05-05 09:05:32 +01:00
Adam Hathcock
42b1205fb4 Merge pull request #374 from odinn1984/feat/fail_on_outside_target_files
fix: prevent extracting archived files outside of target path
2018-05-02 22:51:02 +01:00
odinn1986
80ceb1c375 fix: prevent extracting archived files outside of target path
This PR is meant to fix an arbitrary file write vulnerability, that can be
achieved using a specially crafted zip archive, that holds path traversal
filenames. When the filename gets concatenated to the target extraction
directory, the final path ends up outside of the target folder.

A sample malicious zip file named Zip.Evil.zip was used,
and when running the code below, resulted in the creation of C:/Temp/evil.txt
outside of the intended target directory.

There are various possible ways to avoid this issue, some include checking
for .. (dot dot) characters in the filename, but the best solution in our
opinion is to check if the final target filename, starts with the target
folder (after both are resolved to their absolute path).

Stay secure,
Snyk Team
2018-05-02 23:12:33 +03:00
Adam Hathcock
501407c3fe Change flag name to be closer to spec 2018-04-29 16:33:15 +01:00
Adam Hathcock
abddabf18e Proper fixes for all platforms 2018-04-29 16:27:26 +01:00
Adam Hathcock
91d753cbdb Merge branch 'master' into sridhar6668/support_extended_ascii 2018-04-29 15:12:02 +01:00
Adam Hathcock
259acd0694 misc additions 2018-04-29 15:09:26 +01:00
Adam Hathcock
33f7258ea2 Merge branch 'master' into leaveOpen
# Conflicts:
#	src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs
#	src/SharpCompress/Readers/Rar/RarReader.cs
2018-04-29 14:47:08 +01:00
Adam Hathcock
1ea7bb57e5 Merge branch 'master' into sridhar6668/support_extended_ascii 2018-04-29 11:39:09 +01:00
Adam Hathcock
3e60e796fb Merge pull request #340 from adamhathcock/rar5
Rar5 Feature
2018-04-29 11:36:49 +01:00
Adam Hathcock
d9c178cbee Fix all platform support 2018-04-29 11:33:49 +01:00
Adam Hathcock
031b3c55f6 FIx solid support. I did it wrong 2018-04-29 11:12:28 +01:00
Adam Hathcock
b43d2c3d95 Disabled decryption tests 2018-04-29 10:55:51 +01:00
Adam Hathcock
d865120480 ArchiveCryptHeader renamed 2018-04-29 10:13:46 +01:00
Adam Hathcock
15534f466a Add basic rar5 crypt header 2018-04-28 18:20:40 +01:00
Adam Hathcock
9d63dcb8d6 Uncommit some tests 2018-04-28 18:14:47 +01:00
Adam Hathcock
6efe30bd6e Merge branch 'master' into rar5
# Conflicts:
#	.gitignore
2018-04-28 18:09:10 +01:00
Adam Hathcock
52dd9f0609 Merge pull request #371 from adamhathcock/Issue-370
Expose stream length.  Clean up entry stream
2018-04-26 11:33:23 +01:00
Adam Hathcock
bee7f43880 Expose stream length. Clean up entry stream 2018-04-26 09:46:01 +01:00
Adam Hathcock
d38276e8cf Fix solid and some other tests 2018-04-23 10:29:46 +01:00
Adam Hathcock
f3daaeb200 Try to use both for Rarv5 support 2018-04-23 09:39:50 +01:00
Adam Hathcock
9b152a40a9 Merge branch 'master' into rar5 2018-04-22 11:35:33 +01:00
Adam Hathcock
89ae8ca526 Rejigger read only substream 2018-04-22 11:32:47 +01:00
Adam Hathcock
68a5e474a6 More testing of file handling 2018-04-22 11:19:11 +01:00
Adam Hathcock
bf58742ddf rework of leave stream open for readers 2018-04-22 11:09:03 +01:00
Adam Hathcock
f18e5b75bb Archives set up correctly 2018-04-22 10:06:30 +01:00
Adam Hathcock
e919c99b14 First pass of removing explicit leaveOpen on streams. 2018-04-22 10:02:18 +01:00
Adam Hathcock
b960f2e5ba Minor build updates 2018-04-22 09:17:03 +01:00
srperias@microsoft.com
5d8728d592 Decode without setting the default Encoding type 2018-03-28 13:12:54 -07:00
srperias@microsoft.com
04ba6c2d73 ZipArchive Reader: Uses IBM PC character encoding to decode filename and comment if the general purpose bit 11 is not set in the header 2018-03-27 13:54:16 -07:00
Adam Hathcock
0cab9bd4b4 Mark for 0.20.0 2018-03-24 07:42:20 +00:00
Adam Hathcock
279d305013 Merge pull request #359 from prettierci-commits/prettierci-master-1521104105
PrettierCI master Sync
2018-03-15 08:56:49 +00:00
PrettierCI
750c1fb069 Sync with Prettier 2018-03-15 08:55:06 +00:00
Adam Hathcock
359a6042cd Merge pull request #352 from adamhathcock/cake-026
Cake 0.26
2018-03-01 15:40:30 +00:00
Adam Hathcock
e27d2ec660 Remove netcoreapp1.x testing 2018-03-01 15:35:55 +00:00
Adam Hathcock
da56bfc01f Merge pull request #354 from frabar666/deflate64-decompress
Support Deflate64 decompression
2018-03-01 09:14:06 +00:00
frabar666
6e2c7d2857 support Deflate64 decompression 2018-02-27 23:31:11 +01:00
Adam Hathcock
5481609554 Build with new cake 2018-02-27 08:52:55 +00:00
Frederik Carlier
a62f4df0b1 Implement entry.ToString(), let it return entry.Key (#351) 2018-02-16 13:43:23 +00:00
Adam Hathcock
f893c1272c Merge pull request #337 from 4ybaka/issue-323-tar-archive-finalization
Added ability to leave tar archive open after stream is closed
2018-01-14 19:52:08 +00:00
Dmitry
e701f5277e Merge branch 'master' into issue-323-tar-archive-finalization 2018-01-13 00:47:04 +01:00
Dmitry Nesterov
f85fd1f6a4 Added ability to leave tar archive open after stream is closed 2018-01-13 00:44:42 +01:00
Dmitry Nesterov
8f7ea420b3 Revert "Added ability to leave tar archive open after stream is closed"
This reverts commit 9092ecf331.
2018-01-13 00:41:35 +01:00
Adam Hathcock
b39f389a67 Merge branch 'master' into rar5 2018-01-10 14:58:40 +00:00
Adam Hathcock
d8c8dabb52 Merge pull request #336 from diontools/ImproveStreamSkipping
Utility.Skip uses seek
2018-01-10 11:23:24 +00:00
Dmitry Nesterov
9092ecf331 Added ability to leave tar archive open after stream is closed 2018-01-04 22:57:32 +01:00
diontools
2fd9fe96ad Utility.Skip uses seek 2018-01-03 00:23:34 +09:00
coderb
554153e6a0 rar5: port old algos 2017-12-20 19:10:06 -05:00
coderb
3c29122dfe rar5: porting old algos 2017-12-20 19:04:41 -05:00
coderb
c42dc646ae rar5: reporting older algos 2017-12-20 18:51:48 -05:00
coderb
edd6206a03 rar5: fix checkin 2017-12-20 18:32:36 -05:00
coderb
a1e7f55b95 rar5: unpack working!!! 2017-12-20 18:32:12 -05:00
coderb
218823e9b2 rar5: unpack bugfix 2017-12-20 18:13:04 -05:00
coderb
3e8f52689e unrar5: unpack wip 2017-12-20 16:01:55 -05:00
coderb
0219fc3ea9 unrar5: unpack wip 2017-12-20 14:58:49 -05:00
coderb
66cb2ab662 unrar5: unpack wip 2017-12-20 14:28:22 -05:00
coderb
91c85f0aa6 unrar5: unpack wip 2017-12-20 14:22:47 -05:00
coderb
fd9790cc36 unrar5: unpack wip 2017-12-20 14:15:20 -05:00
coderb
0d40883176 unrar5: unpack wip 2017-12-20 11:19:30 -05:00
coderb
2d0319f779 rar5: unpack wip 2017-12-20 02:11:45 -05:00
coderb
aaeaa44c0b rar5: unpack wip 2017-12-20 01:55:54 -05:00
coderb
9fc77db073 rar5: unpack wip 2017-12-20 01:39:13 -05:00
coderb
bdaa060003 rar5: unpack wip 2017-12-20 01:21:53 -05:00
coderb
b5cb9901b1 rar5: wip 2017-12-20 00:29:07 -05:00
coderb
fb4d503c9a rar5: wip 2017-12-20 00:17:47 -05:00
coderb
c3c2fcf4d0 rar5: unpack wip 2017-12-19 21:41:36 -05:00
coderb
f2d2d94d1b rar5: unpack wip 2017-12-19 14:03:53 -05:00
coderb
11c1b45335 rar5: unpack wip 2017-12-19 13:52:57 -05:00
coderb
b8a308012f rar5: unpack work 2017-12-18 11:01:37 -05:00
coderb
122a732206 unrar5: pull in fast memset code 2017-12-18 10:18:17 -05:00
coderb
59e4383209 rar5: unpack wip 2017-12-18 10:02:34 -05:00
coderb
22b008f723 rar5: unpack wip 2017-12-18 09:51:24 -05:00
coderb
c770094425 rar5: fileheader fixes 2017-12-18 09:46:18 -05:00
coderb
093a5fdf31 rar5: oops 2017-12-18 09:25:55 -05:00
coderb
f811835f02 rar5: rename Entry.IsSplit -> IsSplitAfter, misc wip 2017-12-18 09:20:20 -05:00
coderb
5dda13b800 rar5: reorg code for side by side implementations 2017-12-18 08:23:18 -05:00
coderb
a20306afe0 rar5: port wip 2017-12-17 21:23:32 -05:00
coderb
476b1df323 rar5: clean port unrarsrc 5.5.8 wip 2017-12-17 20:59:34 -05:00
coderb
aec5a913da rar5: checkin missing file 2017-12-17 20:54:54 -05:00
coderb
e13795651d rar: import unrarsrc-5.5.8 for reference
this will allow us to diff against newer version of unrarsrc if we wish to update our port
2017-12-17 17:52:00 -05:00
coderb
cc175da0d8 rar5: unpack wip 2017-12-17 17:08:53 -05:00
coderb
a2369fb531 rar5: uppercase method names 2017-12-17 12:08:09 -05:00
coderb
c5b8a444f2 rar5: unpack tighten up access modifiers 2017-12-17 12:03:41 -05:00
coderb
f450608073 rar5: unpack use partial class instead of inheritance 2017-12-17 11:46:17 -05:00
coderb
0e57537167 rar5: unpack wip 2017-12-17 11:36:33 -05:00
coderb
1445b0a48b rar5: refactor unpack classes 2017-12-17 11:33:31 -05:00
coderb
d268cc7685 rar5: wip unpack50() 2017-12-17 11:16:42 -05:00
coderb
7969bbaac4 rar5: working on decompression 2017-12-17 11:04:13 -05:00
coderb
b9e89ca64b rar5: wip 2017-12-17 10:40:41 -05:00
coderb
f802b41665 rar5: wip 2017-12-17 10:08:21 -05:00
coderb
f0eac57bb9 rar5: more cleanup 2017-12-17 09:14:08 -05:00
coderb
c9d3563f31 rar5: some cleanup 2017-12-17 09:00:11 -05:00
coderb
8563179592 rar5: wip 2017-12-17 08:35:41 -05:00
coderb
1c49ff63e2 rar5: replicate rar test cases 2017-12-17 08:09:41 -05:00
coderb
5f121c5da4 rar5 wip 2017-12-17 07:39:02 -05:00
coderb
72f52359e6 rar5: wip 2017-12-17 01:58:40 -05:00
coderb
9f549b98da rar5: support ArchiveHeader, additional rar5 header implementation 2017-12-16 20:39:53 -05:00
coderb
c346a4ca94 rar5: change rar MarkHeader detection logic to support rar5 2017-12-16 17:35:07 -05:00
coderb
d334b54846 rar5: add test archives 2017-12-16 12:54:32 -05:00
Adam Hathcock
02f68b793c Mark for 0.19.2 2017-12-16 09:08:17 +00:00
Adam Hathcock
57b9133a0f Change namespace and visibility to avoid collisions (#333) 2017-12-16 09:05:21 +00:00
Adam Hathcock
815f5e09e8 Mark for 0.19.1 2017-12-15 14:46:14 +00:00
Adam Hathcock
5bdf01ee59 Absorb arraypool from CoreFX (#331) 2017-12-15 14:45:02 +00:00
Adam Hathcock
bd9417e74c Mark for 0.19 2017-12-12 11:17:57 +00:00
Adam Hathcock
694e869162 Use arraypool for transfer/skip (#326)
* Use arraypool for transfer/skip

* Merge fixes

* Remove redundant constant
2017-12-08 13:58:38 +00:00
Adam Hathcock
45845f8963 Add Circle CI build 2017-12-08 12:03:28 +00:00
Adam Hathcock
a8b6def76a Netcore2 (#302)
* Add netstandard 2.0 target and netcoreapp2.0 tests

* Update xunit

* set tests explicitly to netcore2

* update travis

* Don't say build as netcoreapp1.0

* try adding dotnet 1 too

* Remove .NET Core 1 support

* switch to circle

* update cake

* fix circle build

* try fix file ending test again

* Fix casing on files

* Another casing fix

* Add back netstandard1.0

* Finish adding netstandard 1.0 back

* Add netstandard1.3 back
2017-12-08 12:00:29 +00:00
Sors
a4ebd5fb3d Rar 5 format (#310)
Fix rar 5 format comment
2017-12-04 18:59:49 +00:00
Adam Hathcock
3da3b212fa create new memorystream to allow proper resizing as memorystream could be a user provided buffer. Update xunit (#307) 2017-12-04 18:48:38 +00:00
Martijn Kant
c2528cf93e Mk/add support for extracting password protected LZMA(2) 7z archives (#324)
* Added possibility to decompress a password protected 7z LZMA archive

* Fix tests
2017-12-04 10:55:30 +00:00
coderb
550fecd4d3 bugfix: eliminate spurious rar crc exception when Read() is called with count = 0 (#313) 2017-10-23 11:58:02 +01:00
Adam Hathcock
50b01428b4 Mark for 0.18.2 2017-09-22 09:16:42 +01:00
Thritton
bb59f28b22 Update ArchiveReader.cs (#303)
#227
Added check if argument is in range in method TranslateTime(long? time)
2017-09-19 15:25:10 +01:00
François
7064cda6de Zlib: fix Adler32 implementation (#301) 2017-09-17 22:21:09 +01:00
Adam Hathcock
525c1873e8 Fix merge 2017-09-17 22:16:57 +01:00
François
3d91b4eb5e XZ: fix padding issues (#300)
* XZ: fix variable-length integers decoding

* XZ: fix block and index padding issues

* cleanup in XZStreamTests
2017-09-17 22:14:23 +01:00
François
f20c03180e XZ: fix variable-length integers decoding (#299) 2017-09-17 22:05:20 +01:00
Vladimir Kozlov
08fee76b4e Fixes Double Dispose() of ZipWritingStream #294 https://github.com/adamhathcock/sharpcompress/issues/294 (#295) 2017-09-08 13:25:53 +01:00
twirpx
149f5e4fb5 Minor fixes 2017-08-22 11:46:32 +05:00
Adam Hathcock
0f511c4b2a Mark for 0.18.1 2017-08-17 11:43:34 +01:00
twirpx
42d9dfd117 Fixed bug: Passing default ReaderOptions when creating ZipReader for solid extraction (#287) 2017-08-16 08:19:23 +01:00
twirpx
1793fc949d Fixed bug: Passing default ReaderOptions when creating ZipReader for solid extraction 2017-08-16 08:57:36 +05:00
Adam Hathcock
3983db08ff Use nameof 2017-07-27 11:05:33 -05:00
Adam Hathcock
72114bceea Add release link 2017-07-17 10:22:58 -05:00
Adam Hathcock
c303f96682 mark for 0.18 2017-07-17 10:11:27 -05:00
Adam Hathcock
0e785968c4 Rework usage of WriterOptions for writers since it was inconsistently used. (#271) 2017-07-17 11:05:42 -04:00
Adam Hathcock
15110e18e2 Don't skip ZipReader data twice. (#272)
* Don't skip ZipReader data twice.

* Add archive for a new test
2017-07-17 11:05:21 -04:00
Adam Hathcock
5465af041b Use Skip and ReadFully extension methods where possible. (#276) 2017-07-17 10:55:22 -04:00
Adam Hathcock
310d56fc16 Made ArchiveEncoding a non-static class that is used with options. (#274)
* Made ArchiveEncoding a non-static class that is used with options.

* Revert some formatting.

* Optional string decoder delegate (#278)
2017-07-17 10:53:20 -04:00
eklann
231258ef69 Force encoding (#266)
* Fixing build

* Fixing build

* Fixing build

* Fixed build (seems working now)

* Added support to force specific encoding when reading or writing an archive

* Minor fixed related to force encoding

* Removed obsolete project file not present in master
2017-07-05 10:15:49 -05:00
Sam Bott
16b7e3ffc8 Add XZ tests (#258)
* tests added and converted to xunit

* reordered two assertions
2017-06-11 13:44:00 +01:00
Adam Hathcock
513e59f830 Mark for 0.17.1 2017-06-09 08:28:35 +01:00
Adam Hathcock
b10a1cf2bd Bug on Windows on .NET Core fix (#257)
* Bug on Windows on .NET Core fix: https://github.com/dotnet/corefx/issues/20676

* Add comment
2017-06-09 08:22:47 +01:00
Adam Hathcock
1656edaa29 Add some more details to nuget package 2017-06-01 12:36:01 +01:00
Adam Hathcock
cff49aacba Added explicit tar skip check. Caught skip issue. 2017-06-01 11:25:32 +01:00
Adam Hathcock
19c32aff6c README fixes 2017-06-01 10:56:11 +01:00
Adam Hathcock
db3ec8337f Mark for 0.17 2017-06-01 10:54:50 +01:00
Adam Hathcock
e7bfc40461 Fix Skipping when compressed size is unknown (fallback to decompressing) 2017-06-01 09:26:08 +01:00
Adam Hathcock
3d3ca254ba Zip64 introduced seekable behavior into ZipWriter. The position may … (#252)
* Zip64 introduced seekable behavior into ZipWriter.  The position may not be zero.

* Remove some dead code

* Update formats for zip64

* Make version created by and version needed to extract the same

* Running tests is faster than skipping
2017-05-31 16:55:49 +01:00
Adam Hathcock
b45bc859a4 XZ Format (#247)
* Started integrated XZ format from https://github.com/sambott/XZ.NET

* Add readme line as it was copy/pasted

* Tar used with XZ

* update formats
2017-05-31 16:55:26 +01:00
Adam Hathcock
912d7a8775 Lzip (#245)
* First pass.  Writing isn't implemented on stream.  Tests are busted.

* LZipReader works...no file name :(

* LZipWriter works

* Writing tests are actually correct now.  LZipStream correctly writes trailer now.  lzip command line tool likes it.

* Add recommendation blurb

* Update notes for formats

* LZip isn't an archive format

* Attempting to fix and implement crc32

* LZip writing test passes

* Had to invert crc to check uncompressed data.
2017-05-31 16:51:24 +01:00
Adam Hathcock
16885da1b5 Mark for 0.16.2 2017-05-31 14:47:51 +01:00
Adam Hathcock
26714052eb Merge pull request #249 from adamhathcock/zip_entry_compression_fix
Per entry compression was being written out incorrectly on the centra…
2017-05-31 12:55:37 +01:00
Adam Hathcock
3df763a783 Merge branch 'master' into zip_entry_compression_fix 2017-05-31 11:15:30 +01:00
Adam Hathcock
925842bc4b Merge pull request #251 from dbaumber/Issue-250
Fix for Issue #250: remove extra build flags for .NET 3.5
2017-05-31 10:54:52 +01:00
Dan Baumberger
cead62704e Fix for Issue #250: remove extra build flags for .NET 3.5 as to
enable WinZipAes for .NET 3.5.
2017-05-30 13:43:48 -07:00
Adam Hathcock
3f24a744c0 Merge branch 'master' into zip_entry_compression_fix 2017-05-30 16:10:41 +01:00
Adam Hathcock
cce97548a2 Merge pull request #212 from kenkendk/remove_unused_code
Removed the unused code to write entries in Zip Headers
2017-05-30 16:09:04 +01:00
Adam Hathcock
9270d7cabf Add cache for dotnet packages 2017-05-30 16:04:55 +01:00
Adam Hathcock
264aa6d366 Merge branch 'master' into remove_unused_code 2017-05-30 15:58:44 +01:00
Adam Hathcock
69fc74e376 Per entry compression was being written out incorrectly on the central directory. Fix for that. 2017-05-30 15:37:41 +01:00
Adam Hathcock
a361d41e68 Fix test namespaces 2017-05-30 15:14:02 +01:00
Adam Hathcock
38766dac99 Wrong logic for skipping tests 2017-05-30 12:50:03 +01:00
Adam Hathcock
c30bc65281 Don't run tests on travis either 2017-05-30 12:46:34 +01:00
Adam Hathcock
296ebd942a Shrink script a bit 2017-05-30 12:37:16 +01:00
Adam Hathcock
afa19f7ad8 Add xplat cake and travis build 2017-05-30 12:35:12 +01:00
Adam Hathcock
a193b2d3b1 Add xplat build 2017-05-29 10:35:55 +01:00
Adam Hathcock
be4a65e572 update readme 2017-05-24 08:52:12 +01:00
Adam Hathcock
6832918e71 Mark for 0.16.1 2017-05-23 16:21:07 +01:00
Adam Hathcock
fd9a3ffbcc Merge commit '18641d4f9b849daea7b6fbb7edad51369534ffa3'
* commit '18641d4f9b849daea7b6fbb7edad51369534ffa3':
  Normalize Rar keys
2017-05-23 16:15:58 +01:00
Adam Hathcock
41added690 Private setter clean up 2017-05-23 16:15:47 +01:00
Adam Hathcock
18641d4f9b Merge pull request #238 from adamhathcock/issue_201
Normalize Rar keys
2017-05-23 16:14:55 +01:00
Adam Hathcock
4d0c5099d4 Merge branch 'master' into issue_201 2017-05-23 16:13:09 +01:00
Adam Hathcock
9d9d491245 Slightly better fix for https://github.com/adamhathcock/sharpcompress/pull/235 2017-05-23 16:10:15 +01:00
Adam Hathcock
7b81d18071 Merge pull request #235 from dbaumber/Issue-230
Issue #230: preserve the compression method when getting a compressed…
2017-05-23 15:50:32 +01:00
Dan Baumberger
7d0acbc988 Merge branch 'Issue-230' of https://github.com/dbaumber/sharpcompress into Issue-230 2017-05-23 07:46:48 -07:00
Dan Baumberger
313c044c41 Added a unit test for the WinZipAes multiple OpenEntryStream() bug. 2017-05-23 07:44:45 -07:00
Dan Baumberger
f6f8adf97e Merge branch 'master' into Issue-230 2017-05-23 07:43:02 -07:00
Adam Hathcock
bc97d325ca Normalize Rar keys 2017-05-22 10:55:15 +01:00
Adam Hathcock
0f2d325f20 oh yeah, appveyor doesn't like the tests 2017-05-22 09:08:16 +01:00
Adam Hathcock
63d5503e12 forgot to actually add tests to script 2017-05-22 09:06:33 +01:00
Adam Hathcock
e53f2cac4a Mark for 0.16.0 2017-05-22 08:58:52 +01:00
Adam Hathcock
3b73464233 Merge pull request #236 from damieng/zip-min-version-of-20
Default zip ver to 20 (deflate/encyption), fixes #164
2017-05-22 08:38:18 +01:00
Damien Guard
575f10f766 Default zip ver to 20 (deflate/encyption), fixes #164 2017-05-19 16:37:20 -07:00
Dan Baumberger
8d3fc3533b Issue #230: preserve the compression method when getting a compressed stream for encrypted ZIP archives. 2017-05-19 08:36:11 -07:00
Adam Hathcock
60370b8539 don't run appveyor tests 2017-05-19 15:51:06 +01:00
Adam Hathcock
f6db114865 Remove console writelines 2017-05-19 15:47:53 +01:00
Adam Hathcock
1c6c344b6b Tests don't run on appveyor 2017-05-19 15:45:29 +01:00
Adam Hathcock
d0302898e0 Add back net45,net35 and cake 2017-05-19 13:33:12 +01:00
Adam Hathcock
057ac9b001 Enable test 2017-05-19 11:03:31 +01:00
Adam Hathcock
8be931bbcb Doing some resharper clean up 2017-05-19 10:52:49 +01:00
Adam Hathcock
3197ef289c Forgot to hit save 2017-05-19 10:15:19 +01:00
Adam Hathcock
631578c175 Update to next version. Stop Zip64 tests from running all the time and some clean up 2017-05-19 10:10:23 +01:00
Adam Hathcock
f1809163c7 correct gitignore 2017-05-19 09:44:45 +01:00
Adam Hathcock
60e1fe86f2 Fix test running 2017-05-19 09:40:37 +01:00
Adam Hathcock
59d7de5bfc Try again appveyor 2017-05-19 09:36:05 +01:00
Adam Hathcock
6e95c1d84a Drop net35 support as dot net tooling doesn’t support it currently 2017-05-19 09:34:02 +01:00
Adam Hathcock
ee64670755 Move test folder to be tests 2017-05-19 09:19:37 +01:00
Adam Hathcock
3f7d0f5b68 Update test project 2017-05-19 09:14:43 +01:00
Adam Hathcock
e3514c5c4b Don’t attempt to autodeploy 2017-05-19 09:06:18 +01:00
Adam Hathcock
cc3a9cff88 Merge pull request #231 from adamhathcock/VS2017
Vs2017
2017-05-19 09:02:12 +01:00
Adam Hathcock
15e821aa39 Remove unused events 2017-05-19 08:49:44 +01:00
Adam Hathcock
8dd1dbab5f Remove Cake as it’s unnecessary for basic build/test/publish 2017-05-19 08:47:17 +01:00
Adam Hathcock
65ce91ddf6 Update. Only use net35, net standard 1.0 and net standard 1.3 2017-05-19 08:46:27 +01:00
Adam Hathcock
bf55595d6f Merge pull request #226 from gardebring/master
Add new event handler to allow tracking of progress of extraction progress for individual entry
2017-04-25 13:07:44 +01:00
Anders Gardebring
2aa123ccd7 Remove begin and end events since this can now be tracked via progress instead 2017-04-25 13:21:04 +02:00
Anders Gardebring
0990b06cc9 Create new TransferTo method and pass Entry and IReaderExtractionListener instead of passing an action lambda. 2017-04-25 12:48:56 +02:00
Anders Gardebring
e05f9843ba Use strongly typed ReaderProgress instead of object[] 2017-04-25 12:36:32 +02:00
Anders Gardebring
683d2714d0 Add new event to be able to track progress of extraction of individual entry when extracting an archive. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract. 2017-04-24 13:50:45 +02:00
Anders Gardebring
b8ef1ecafc Revert "Add new feature to allow injection of an action into the extraction process. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract."
This reverts commit 467fc2d03d.
2017-04-24 10:22:49 +02:00
Anders Gardebring
467fc2d03d Add new feature to allow injection of an action into the extraction process. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract. 2017-04-20 11:45:53 +02:00
Adam Hathcock
58b4fe4f28 Merge pull request #220 from coderb/master
verify RAR crc on header and file data
2017-04-07 11:56:06 +01:00
Brien Oberstein
97d5e0aac4 verify rar CRC on header and file data 2017-04-04 12:20:06 -04:00
Adam Hathcock
356c977cff Merge pull request #215 from mnadareski/master
Removed restriction on 7zip file entries
2017-03-17 09:20:59 +00:00
Matt Nadareski
99d6062376 Removed restriction on 7zip file entries 2017-03-16 15:55:20 -07:00
Adam Hathcock
f8538403e4 Merge pull request #211 from kenkendk/add_zip64
Add zip64
2017-03-13 10:23:26 +00:00
Kenneth Skovhede
ba12019bc7 Removed the unused code to write entries in Zip Headers 2017-03-11 08:05:49 +01:00
Kenneth Skovhede
726b9c80f6 Fixed compiling the unittest 2017-03-11 01:05:58 +01:00
Kenneth Skovhede
2894711c51 Added a test suite to verify zip64 write support is working, and can be read in both Archive and Stream mode 2017-03-11 00:54:06 +01:00
Kenneth Skovhede
85280f6f4f Changed the logic to throw exceptions when sizes exceed the zip archive limits, and zip64 is not enabled.
This changes the logic, such that archives larger than 4GiB are still automatically written correct (only the central header is special).
Archives with individual streams larger than 4 GiB must set the zip64 flag, either on the archive or the individual streams.
2017-03-11 00:53:42 +01:00
Kenneth Skovhede
d7f4c0ee32 Fixed an error in the zip64 central end of header: the signature + length (12 bytes) are not included in the reported length. 2017-03-10 23:10:06 +01:00
Kenneth Skovhede
1263c0d976 Added support for writing zip64 headers 2017-03-09 23:56:42 +01:00
Kenneth Skovhede
cd3cbd2b32 Support for writing zip64 headers in the unused code 2017-03-09 23:18:57 +01:00
Adam Hathcock
b3a4fed8be Mark for 0.15.2 2017-03-09 11:02:44 +00:00
Adam Hathcock
d0b4af6666 Merge pull request #210 from kenkendk/fix_invalid_headers
Fix invalid headers
2017-03-09 10:41:18 +00:00
Kenneth Skovhede
81ab5c189d Fixed writing correct headers in zip archives 2017-03-09 11:34:24 +01:00
Kenneth Skovhede
6ef3be4b5c Fixed writing correct headers in zip archives 2017-03-09 11:32:20 +01:00
Adam Hathcock
9f90a1d651 Mark for 0.15.1 2017-01-25 09:31:01 +00:00
Adam Hathcock
ce9a3fd1ef Add file ordering fix for OS X 2017-01-25 09:29:13 +00:00
Adam Hathcock
7c6f05058e Merge pull request #206 from markryd/zip64-extraction
Zip64 extending information and ZipReader
2017-01-25 09:03:43 +00:00
Mark Rydstrom
a8c3a7439e Add support for zip64 to ZipReader 2017-01-25 17:05:48 +10:00
Mark Rydstrom
839b3ab0cf Add support for zip64 extended information field 2017-01-25 16:51:15 +10:00
Adam Hathcock
44d54db80e Fix some path issues on OS X when running tests. 2017-01-24 17:36:51 +00:00
Adam Hathcock
a67d7bc429 Mark for 0.15 2017-01-24 17:25:19 +00:00
Adam Hathcock
079a818c6c Merge pull request #205 from markryd/zip64-extraction
Add zip64 support for ZipArchive extraction
2017-01-24 16:56:42 +00:00
Mark Rydstrom
6be6ef0b5c Add zip64 support for ZipArchive extraction 2017-01-24 13:04:03 +10:00
Adam Hathcock
8e51d9d646 0.14.1 2016-11-30 14:26:18 +00:00
Adam Hathcock
ea206f4f02 Merge pull request #199 from adamhathcock/Issue-198
Gzip entry can't be read multiple times
2016-11-25 09:33:56 +00:00
Adam Hathcock
f175a2a252 Merge branch 'master' into Issue-198 2016-11-25 09:21:44 +00:00
Adam Hathcock
3f7e559b86 Merge pull request #200 from ITnent/bug/Issue-197
Open branch, to fix multiple crashes on repeated zip archives reading…
2016-11-25 09:21:34 +00:00
Vladimir Demidov
2959b4d701 Modified check integrity condition for the encrypted file. 2016-11-24 20:41:08 +03:00
Vladimir Demidov
031286c5eb Fixed defects after review. 2016-11-24 18:01:49 +03:00
Vladimir Demidov
e181fa8c4a Restored original tabs. 2016-11-24 17:11:43 +03:00
Vladimir Demidov
7b035bec5d Fixed some issues after review. 2016-11-24 16:21:02 +03:00
Vladimir Demidov
f39d2bf53a Open branch, to fix multiple crashes on repeated zip archives reading. Added fix. 2016-11-24 15:14:29 +03:00
Adam Hathcock
7c8e407182 Merge branch 'master' into Issue-198 2016-11-21 12:21:29 +00:00
Adam Hathcock
a09136d46b Merge pull request #195 from jskeet/strong-naming
Strong-name both the main and test projects
2016-11-21 12:06:13 +00:00
Adam Hathcock
5fe1363ee1 Gzip entry can't be read multiple times https://github.com/adamhathcock/sharpcompress/issues/198 2016-11-21 12:04:35 +00:00
Jon Skeet
b41823fc10 Strong-name both the main and test projects
It's not clear whether SharpCompress.Test.Portable (as referenced
in AssemblyInfo.cs) still exists, but build.ps1 certainly works.
2016-11-15 18:42:56 +00:00
Adam Hathcock
0a64fe28b0 Oops, removed too much from project.json 2016-10-14 09:03:15 +01:00
Adam Hathcock
e320ccfa9a 0.14.0 2016-10-14 08:59:19 +01:00
Adam Hathcock
9628ff9456 Merge pull request #191 from jskeet/lzip
Initial read-only support for LZip
2016-10-14 08:50:32 +01:00
Jon Skeet
d540f78cfc Initial read-only support for LZip
LZip has no notion of flienames, so an LzipReader wouldn't make very much sense;
I've just implemented the stream, and hooked it into tar support.
2016-10-12 15:08:56 +01:00
Adam Hathcock
66420cd299 Merge pull request #189 from ziaa/master
Remove unbalanced parentheses in code samples
2016-10-08 18:25:30 +01:00
Seyed Zia Azimi
dd0594471f Remove unbalanced parentheses in samples 2016-10-07 19:33:41 +03:30
Adam Hathcock
844ba228ee Make 0.13.1 2016-10-03 13:44:19 +01:00
Adam Hathcock
7efc701b32 Merge pull request #188 from adamhathcock/fix_nulls
Fix null password on ReaderFactory.  Fix null options on SevenZipArchive
2016-10-03 13:41:55 +01:00
Adam Hathcock
d7e29f7c4d Fix occasionally failing test 2016-10-03 13:37:04 +01:00
Adam Hathcock
f26ba91386 Fix null password on ReaderFactory. Fix null options on SevenZipArchive 2016-10-03 13:32:53 +01:00
Adam Hathcock
c73ac2039c Merge pull request #185 from adamhathcock/ppmd_allocation_zipwriter
Make PpmdProperties lazy to avoid unnecessary allocations.
2016-10-03 13:04:14 +01:00
Adam Hathcock
671f9cd0cb Empty commit to kick build 2016-10-03 12:58:23 +01:00
Adam Hathcock
131b5b9714 Can't use Lazy on .NET 3.5 :( 2016-10-03 11:20:29 +01:00
Adam Hathcock
74af0889b9 Make PpmdProperties lazy to avoid unnecessary allocations. 2016-10-03 10:16:26 +01:00
Adam Hathcock
e5ee399045 Merge pull request #181 from claunia/patch-1
Update FORMATS.md
2016-09-30 07:08:52 +01:00
deeb7a0f64 Update FORMATS.md
Add ADC to formats list.
2016-09-29 22:53:51 +01:00
1286 changed files with 205968 additions and 42728 deletions

13
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.2.5",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}

7
.copilot-agent.yml Normal file
View File

@@ -0,0 +1,7 @@
enabled: true
agent:
name: copilot-coding-agent
allow:
- paths: ["src/**/*", "tests/**/*", "README.md", "AGENTS.md"]
actions: ["create", "modify"]
require_review_before_merge: true

570
.editorconfig Normal file
View File

@@ -0,0 +1,570 @@
# Version: 2.0.1 (Using https://semver.org/)
# Updated: 2020-12-11
# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
# See http://EditorConfig.org for more information about .editorconfig files.
##########################################
# Common Settings
##########################################
# This file is the top-most EditorConfig file
root = true
# All Files
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
##########################################
# File Extension Settings
##########################################
# Visual Studio Solution Files
[*.sln]
indent_style = tab
# Visual Studio XML Project Files
[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# XML Configuration Files
[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
indent_size = 2
# JSON Files
[*.{json,json5,webmanifest}]
indent_size = 2
# YAML Files
[*.{yml,yaml}]
indent_size = 2
# Markdown Files
[*.md]
trim_trailing_whitespace = false
# Web Files
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
indent_size = 2
# Batch Files
[*.{cmd,bat}]
end_of_line = crlf
# Bash Files
[*.sh]
end_of_line = lf
# Makefiles
[Makefile]
indent_style = tab
##########################################
# Default .NET Code Style Severities
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
##########################################
[*.{cs,csx,cake,vb,vbx}]
# Default Severity for all .NET Code Style rules below
dotnet_analyzer_diagnostic.severity = silent
##########################################
# File Header (Uncomment to support file headers)
# https://docs.microsoft.com/visualstudio/ide/reference/add-file-header
##########################################
# [*.{cs,csx,cake,vb,vbx}]
# file_header_template = <copyright file="{fileName}" company="PROJECT-AUTHOR">\n© PROJECT-AUTHOR\n</copyright>
# SA1636: File header copyright text should match
# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project.
# dotnet_diagnostic.SA1636.severity = none
##########################################
# .NET Language Conventions
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions
##########################################
# .NET Code Style Settings
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings
[*.{cs,csx,cake,vb,vbx}]
# "this." and "Me." qualifiers
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me
#dotnet_style_qualification_for_field = true:warning
#dotnet_style_qualification_for_property = true:warning
#dotnet_style_qualification_for_method = true:warning
#dotnet_style_qualification_for_event = true:warning
# Language keywords instead of framework type names for type references
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning
# Modifier preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers
dotnet_style_require_accessibility_modifiers = always:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning
dotnet_style_readonly_field = true:warning
# Parentheses preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
# Expression-level preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
dotnet_style_object_initializer = true:warning
dotnet_style_collection_initializer = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
dotnet_diagnostic.IDE0045.severity = suggestion
dotnet_style_prefer_conditional_expression_over_return = false:suggestion
dotnet_diagnostic.IDE0046.severity = suggestion
dotnet_style_prefer_compound_assignment = true:warning
# Null-checking preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences
dotnet_style_coalesce_expression = true:warning
dotnet_style_null_propagation = true:warning
# Parameter preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences
dotnet_code_quality_unused_parameters = all:warning
# More style options (Undocumented)
# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641
dotnet_style_operator_placement_when_wrapping = end_of_line
# https://github.com/dotnet/roslyn/pull/40070
dotnet_style_prefer_simplified_interpolation = true:warning
# C# Code Style Settings
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings
[*.{cs,csx,cake}]
# Implicit and explicit types
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_elsewhere = true:warning
# Expression-bodied members
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members
csharp_style_expression_bodied_methods = true:warning
csharp_style_expression_bodied_constructors = true:warning
csharp_style_expression_bodied_operators = true:warning
csharp_style_expression_bodied_properties = true:warning
csharp_style_expression_bodied_indexers = true:warning
csharp_style_expression_bodied_accessors = true:warning
csharp_style_expression_bodied_lambdas = true:warning
csharp_style_expression_bodied_local_functions = true:warning
# Pattern matching
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
# Inlined variable declarations
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations
csharp_style_inlined_variable_declaration = true:warning
# Expression-level preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
csharp_prefer_simple_default_expression = true:warning
# "Null" checking preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences
csharp_style_throw_expression = true:warning
csharp_style_conditional_delegate_call = true:warning
# Code block preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences
csharp_prefer_braces = true:warning
# Unused value preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
dotnet_diagnostic.IDE0058.severity = suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
dotnet_diagnostic.IDE0059.severity = suggestion
# Index and range preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_range_operator = true:warning
# Miscellaneous preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences
csharp_style_deconstructed_variable_declaration = true:warning
csharp_style_pattern_local_over_anonymous_function = true:warning
csharp_using_directive_placement = outside_namespace:warning
csharp_prefer_static_local_function = true:warning
csharp_prefer_simple_using_statement = true:suggestion
dotnet_diagnostic.IDE0063.severity = suggestion
##########################################
# .NET Formatting Conventions
# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
##########################################
# Organize usings
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives
dotnet_sort_system_directives_first = true
# Newline options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = no_change
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents_when_block = false
# Spacing options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_after_comma = true
csharp_space_before_comma = false
csharp_space_after_dot = false
csharp_space_before_dot = false
csharp_space_after_semicolon_in_for_statement = true
csharp_space_before_semicolon_in_for_statement = false
csharp_space_around_declaration_statements = false
csharp_space_before_open_square_brackets = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_square_brackets = false
# Wrapping options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
csharp_preserve_single_line_statements = false
csharp_preserve_single_line_blocks = true
csharp_style_namespace_declarations = file_scoped
##########################################
# .NET Naming Conventions
# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions
##########################################
[*.{cs,csx,cake,vb,vbx}]
dotnet_diagnostic.CA1000.severity = suggestion
dotnet_diagnostic.CA1001.severity = error
dotnet_diagnostic.CA1018.severity = error
dotnet_diagnostic.CA1036.severity = silent
dotnet_diagnostic.CA1051.severity = suggestion
dotnet_diagnostic.CA1068.severity = error
dotnet_diagnostic.CA1069.severity = error
dotnet_diagnostic.CA1304.severity = error
dotnet_diagnostic.CA1305.severity = suggestion
dotnet_diagnostic.CA1307.severity = suggestion
dotnet_diagnostic.CA1309.severity = suggestion
dotnet_diagnostic.CA1310.severity = error
dotnet_diagnostic.CA1507.severity = suggestion
dotnet_diagnostic.CA1513.severity = suggestion
dotnet_diagnostic.CA1707.severity = suggestion
dotnet_diagnostic.CA1708.severity = suggestion
dotnet_diagnostic.CA1711.severity = suggestion
dotnet_diagnostic.CA1716.severity = suggestion
dotnet_diagnostic.CA1720.severity = suggestion
dotnet_diagnostic.CA1725.severity = suggestion
dotnet_diagnostic.CA1805.severity = suggestion
dotnet_diagnostic.CA1816.severity = suggestion
dotnet_diagnostic.CA1822.severity = suggestion
dotnet_diagnostic.CA1825.severity = error
dotnet_diagnostic.CA1826.severity = silent
dotnet_diagnostic.CA1827.severity = error
dotnet_diagnostic.CA1829.severity = suggestion
dotnet_diagnostic.CA1834.severity = error
dotnet_diagnostic.CA1845.severity = suggestion
dotnet_diagnostic.CA1848.severity = suggestion
dotnet_diagnostic.CA1852.severity = suggestion
dotnet_diagnostic.CA1860.severity = silent
dotnet_diagnostic.CA2016.severity = suggestion
dotnet_diagnostic.CA2201.severity = error
dotnet_diagnostic.CA2206.severity = error
dotnet_diagnostic.CA2208.severity = error
dotnet_diagnostic.CA2211.severity = error
dotnet_diagnostic.CA2249.severity = error
dotnet_diagnostic.CA2251.severity = error
dotnet_diagnostic.CA2252.severity = none
dotnet_diagnostic.CA2254.severity = suggestion
dotnet_diagnostic.CS0169.severity = error
dotnet_diagnostic.CS0219.severity = error
dotnet_diagnostic.CS0649.severity = suggestion
dotnet_diagnostic.CS1998.severity = error
dotnet_diagnostic.CS8602.severity = error
dotnet_diagnostic.CS8604.severity = error
dotnet_diagnostic.CS8618.severity = error
dotnet_diagnostic.CS0618.severity = suggestion
dotnet_diagnostic.CS4014.severity = error
dotnet_diagnostic.CS8600.severity = error
dotnet_diagnostic.CS8603.severity = error
dotnet_diagnostic.CS8625.severity = error
dotnet_diagnostic.BL0005.severity = suggestion
dotnet_diagnostic.MVC1000.severity = suggestion
dotnet_diagnostic.RZ10012.severity = error
dotnet_diagnostic.IDE0004.severity = error # redundant cast
dotnet_diagnostic.IDE0005.severity = suggestion
dotnet_diagnostic.IDE0007.severity = error # Use var
dotnet_diagnostic.IDE0011.severity = error # Use braces on if statements
dotnet_diagnostic.IDE0010.severity = silent # populate switch
dotnet_diagnostic.IDE0017.severity = suggestion # initialization can be simplified
dotnet_diagnostic.IDE0021.severity = silent # expression body for constructors
dotnet_diagnostic.IDE0022.severity = silent # expression body for methods
dotnet_diagnostic.IDE0023.severity = suggestion # use expression body for operators
dotnet_diagnostic.IDE0024.severity = silent # expression body for operators
dotnet_diagnostic.IDE0025.severity = suggestion # use expression body for properties
dotnet_diagnostic.IDE0027.severity = suggestion # Use expression body for accessors
dotnet_diagnostic.IDE0028.severity = silent # expression body for accessors
dotnet_diagnostic.IDE0032.severity = suggestion # Use auto property
dotnet_diagnostic.IDE0033.severity = error # prefer tuple name
dotnet_diagnostic.IDE0037.severity = suggestion # simplify anonymous type
dotnet_diagnostic.IDE0040.severity = error # modifiers required
dotnet_diagnostic.IDE0041.severity = error # simplify null
dotnet_diagnostic.IDE0042.severity = error # deconstruct variable
dotnet_diagnostic.IDE0044.severity = suggestion # make field only when possible
dotnet_diagnostic.IDE0047.severity = suggestion # parameter name
dotnet_diagnostic.IDE0051.severity = error # unused field
dotnet_diagnostic.IDE0052.severity = error # unused member
dotnet_diagnostic.IDE0053.severity = suggestion # lambda not needed
dotnet_diagnostic.IDE0055.severity = suggestion # Fix formatting
dotnet_diagnostic.IDE0057.severity = suggestion # substring can be simplified
dotnet_diagnostic.IDE0060.severity = suggestion # unused parameters
dotnet_diagnostic.IDE0061.severity = suggestion # local expression body
dotnet_diagnostic.IDE0062.severity = suggestion # local to static
dotnet_diagnostic.IDE0063.severity = error # simplify using
dotnet_diagnostic.IDE0066.severity = suggestion # switch expression
dotnet_diagnostic.IDE0072.severity = suggestion # Populate switch - forces population of all cases even when default specified
dotnet_diagnostic.IDE0078.severity = suggestion # use pattern matching
dotnet_diagnostic.IDE0090.severity = suggestion # new can be simplified
dotnet_diagnostic.IDE0130.severity = suggestion # namespace folder structure
dotnet_diagnostic.IDE0160.severity = silent # Use block namespaces ARE NOT required
dotnet_diagnostic.IDE0161.severity = error # Please use file namespaces
dotnet_diagnostic.IDE0200.severity = suggestion # lambda not needed
dotnet_diagnostic.IDE1006.severity = suggestion # Naming rule violation: These words cannot contain lower case characters
dotnet_diagnostic.IDE0260.severity = suggestion # Use pattern matching
dotnet_diagnostic.IDE0270.severity = suggestion # Null check simplifcation
dotnet_diagnostic.IDE0290.severity = error # Primary Constructor
dotnet_diagnostic.IDE0300.severity = suggestion # Collection
dotnet_diagnostic.IDE0305.severity = suggestion # Collection ToList
dotnet_diagnostic.NX0001.severity = error
dotnet_diagnostic.NX0002.severity = silent
dotnet_diagnostic.NX0003.severity = silent
dotnet_diagnostic.VSTHRD110.severity = error
dotnet_diagnostic.VSTHRD107.severity = error
##########################################
# Styles
##########################################
# camel_case_style - Define the camelCase style
dotnet_naming_style.camel_case_style.capitalization = camel_case
# pascal_case_style - Define the PascalCase style
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# constant_case - Define the CONSTANT_CASE style
dotnet_naming_style.constant_case.capitalization = all_upper
dotnet_naming_style.constant_case.word_separator = _
# first_upper_style - The first character must start with an upper-case character
dotnet_naming_style.first_upper_style.capitalization = first_word_upper
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
# disallowed_style - Anything that has this style applied is marked as disallowed
dotnet_naming_style.disallowed_style.capitalization = pascal_case
dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
dotnet_naming_style.internal_error_style.capitalization = pascal_case
dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
dotnet_naming_style.underscore_camel_case_style.capitalization = camel_case
dotnet_naming_style.underscore_camel_case_style.required_prefix = _
##########################################
# .NET Design Guideline Field Naming Rules
# Naming rules for fields follow the .NET Framework design guidelines
# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
##########################################
# All public/protected/protected_internal constant fields must be constant_case
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = constant_case
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
# All public/protected/protected_internal static readonly fields must be constant_case
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
# No other public/protected/protected_internal fields are allowed
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
##########################################
# StyleCop Field Naming Rules
# Naming rules for fields follow the StyleCop analyzers
# This does not override any rules using disallowed_style above
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
##########################################
# All constant fields must be constant_case
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = constant_case
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
# All static readonly fields must be constant_case
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
# No non-private instance fields are allowed
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
# Private fields must be camelCase
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = underscore_camel_case_style
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
# Local variables must be camelCase
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = warning
# This rule should never fire. However, it's included for at least two purposes:
# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
##########################################
# Other Naming Rules
##########################################
# All of the following must be PascalCase:
# - Namespaces
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
# - Classes and Enumerations
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
# - Delegates
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
# - Constructors, Properties, Events, Methods
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
dotnet_naming_rule.element_rule.symbols = element_group
dotnet_naming_rule.element_rule.style = pascal_case_style
dotnet_naming_rule.element_rule.severity = warning
# Interfaces use PascalCase and are prefixed with uppercase 'I'
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
dotnet_naming_symbols.interface_group.applicable_kinds = interface
dotnet_naming_rule.interface_rule.symbols = interface_group
dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
dotnet_naming_rule.interface_rule.severity = warning
# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
dotnet_naming_rule.type_parameter_rule.severity = warning
# Function parameters use camelCase
# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
dotnet_naming_rule.parameters_rule.symbols = parameters_group
dotnet_naming_rule.parameters_rule.style = camel_case_style
dotnet_naming_rule.parameters_rule.severity = warning
##########################################
# License
##########################################
# The following applies as to the .editorconfig file ONLY, and is
# included below for reference, per the requirements of the license
# corresponding to this .editorconfig file.
# See: https://github.com/RehanSaeed/EditorConfig
#
# MIT License
#
# Copyright (c) 2017-2019 Muhammad Rehan Saeed
# Copyright (c) 2019 Henry Gabryjelski
#
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject
# to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
##########################################

2
.gitattributes vendored
View File

@@ -2,4 +2,4 @@
* text=auto
# need original files to be windows
test/TestArchives/Original/*.txt eol=crlf
*.txt text eol=crlf

17
.github/agents/copilot-agent.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
enabled: true
agent:
name: copilot-coding-agent
allow:
- paths: ["src/**/*", "tests/**/*", "README.md", "AGENTS.md"]
actions: ["create", "modify", "delete"]
require_review_before_merge: true
required_approvals: 1
allowed_merge_strategies:
- squash
- merge
auto_merge_on_green: false
run_workflows: true
notes: |
- This manifest expresses the policy for the Copilot coding agent in this repository.
- It does NOT install or authorize the agent; a repository admin must install the Copilot coding agent app and grant the repository the necessary permissions (contents: write, pull_requests: write, checks: write, actions: write/read, issues: write) to allow the agent to act.
- Keep allow paths narrow and prefer require_review_before_merge during initial rollout.

13
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "nuget"
directory: "/" # change to "/src/YourProject" if .csproj files are in subfolders
schedule:
interval: "weekly"
open-pull-requests-limit: 5
# optional: target-branch: "master"

25
.github/prompts/plan-async.prompt.md vendored Normal file
View File

@@ -0,0 +1,25 @@
# Plan: Implement Missing Async Functionality in SharpCompress
SharpCompress has async support for low-level stream operations and Reader/Writer APIs, but critical entry points (Archive.Open, factory methods, initialization) remain synchronous. This plan adds async overloads for all user-facing I/O operations and fixes existing async bugs, enabling full end-to-end async workflows.
## Steps
1. **Add async factory methods** to [ArchiveFactory.cs](src/SharpCompress/Factories/ArchiveFactory.cs), [ReaderFactory.cs](src/SharpCompress/Factories/ReaderFactory.cs), and [WriterFactory.cs](src/SharpCompress/Factories/WriterFactory.cs) with `OpenAsync` and `CreateAsync` overloads accepting `CancellationToken`
2. **Implement async Open methods** on concrete archive types ([ZipArchive.cs](src/SharpCompress/Archives/Zip/ZipArchive.cs), [TarArchive.cs](src/SharpCompress/Archives/Tar/TarArchive.cs), [RarArchive.cs](src/SharpCompress/Archives/Rar/RarArchive.cs), [GZipArchive.cs](src/SharpCompress/Archives/GZip/GZipArchive.cs), [SevenZipArchive.cs](src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs)) and reader types ([ZipReader.cs](src/SharpCompress/Readers/Zip/ZipReader.cs), [TarReader.cs](src/SharpCompress/Readers/Tar/TarReader.cs), etc.)
3. **Convert archive initialization logic to async** including header reading, volume loading, and format signature detection across archive constructors and internal initialization methods
4. **Fix LZMA decoder async bugs** in [LzmaStream.cs](src/SharpCompress/Compressors/LZMA/LzmaStream.cs), [Decoder.cs](src/SharpCompress/Compressors/LZMA/Decoder.cs), and [OutWindow.cs](src/SharpCompress/Compressors/LZMA/OutWindow.cs) to enable true async 7Zip support and remove `NonDisposingStream` workaround
5. **Complete Rar async implementation** by converting `UnpackV2017` methods to async in [UnpackV2017.cs](src/SharpCompress/Compressors/Rar/UnpackV2017.cs) and updating Rar20 decompression
6. **Add comprehensive async tests** covering all new async entry points, cancellation scenarios, and concurrent operations across all archive formats in test files
## Further Considerations
1. **Breaking changes** - Should new async methods be added alongside existing sync methods (non-breaking), or should sync methods eventually be deprecated? Recommend additive approach for backward compatibility.
2. **Performance impact** - Header parsing for formats like Zip/Tar is often small; consider whether truly async parsing adds value vs sync parsing wrapped in Task, or make it conditional based on stream type (network vs file).
3. **7Zip complexity** - The LZMA async bug fix (Step 4) may be challenging due to state management in the decoder; consider whether to scope it separately or implement a simpler workaround that maintains correctness.

123
.github/prompts/plan-for-next.prompt.md vendored Normal file
View File

@@ -0,0 +1,123 @@
# Plan: Modernize SharpCompress Public API
Based on comprehensive analysis, the API has several inconsistencies around factory patterns, async support, format capabilities, and options classes. Most improvements can be done incrementally without breaking changes.
## Steps
1. **Standardize factory patterns** by deprecating format-specific static `Open` methods in [Archives/Zip/ZipArchive.cs](src/SharpCompress/Archives/Zip/ZipArchive.cs), [Archives/Tar/TarArchive.cs](src/SharpCompress/Archives/Tar/TarArchive.cs), etc. in favor of centralized [Factories/ArchiveFactory.cs](src/SharpCompress/Factories/ArchiveFactory.cs)
2. **Complete async implementation** in [Writers/Zip/ZipWriter.cs](src/SharpCompress/Writers/Zip/ZipWriter.cs) and other writers that currently use sync-over-async, implementing true async I/O throughout the writer hierarchy
3. **Unify options classes** by making [Common/ExtractionOptions.cs](src/SharpCompress/Common/ExtractionOptions.cs) inherit from `OptionsBase` and adding progress reporting to extraction methods consistently
4. **Clarify GZip semantics** in [Archives/GZip/GZipArchive.cs](src/SharpCompress/Archives/GZip/GZipArchive.cs) by adding XML documentation explaining single-entry limitation and relationship to GZip compression used in Tar.gz
## Further Considerations
1. **Breaking changes roadmap** - Should we plan a major version (2.0) to remove deprecated factory methods, clean up `ArchiveType` enum (remove Arc/Arj or add full support), and consolidate naming patterns?
2. **Progress reporting consistency** - Should `IProgress<ArchiveExtractionProgress<IEntry>>` be added to all extraction extension methods or consolidated into options classes?
## Detailed Analysis
### Factory Pattern Issues
Three different factory patterns exist with overlapping functionality:
1. **Static Factories**: ArchiveFactory, ReaderFactory, WriterFactory
2. **Instance Factories**: IArchiveFactory, IReaderFactory, IWriterFactory
3. **Format-specific static methods**: Each archive class has static `Open` methods
**Example confusion:**
```csharp
// Three ways to open a Zip archive - which is recommended?
var archive1 = ArchiveFactory.Open("file.zip");
var archive2 = ZipArchive.Open("file.zip");
var archive3 = ArchiveFactory.AutoFactory.Open(fileInfo, options);
```
### Async Support Gaps
Base `IWriter` interface has async methods, but writer implementations provide minimal async support. Most writers just call synchronous methods:
```csharp
public virtual async Task WriteAsync(...)
{
// Default implementation calls synchronous version
Write(filename, source, modificationTime);
await Task.CompletedTask.ConfigureAwait(false);
}
```
Real async implementations only in:
- `TarWriter` - Proper async implementation
- Most other writers use sync-over-async
### GZip Archive Special Case
GZip is treated as both a compression format and an archive format, but only supports single-entry archives:
```csharp
protected override GZipArchiveEntry CreateEntryInternal(...)
{
if (Entries.Any())
{
throw new InvalidFormatException("Only one entry is allowed in a GZip Archive");
}
// ...
}
```
### Options Class Hierarchy
```
OptionsBase (LeaveStreamOpen, ArchiveEncoding)
├─ ReaderOptions (LookForHeader, Password, DisableCheckIncomplete, BufferSize, ExtensionHint, Progress)
├─ WriterOptions (CompressionType, CompressionLevel, Progress)
│ ├─ ZipWriterOptions (ArchiveComment, UseZip64)
│ ├─ TarWriterOptions (FinalizeArchiveOnClose, HeaderFormat)
│ └─ GZipWriterOptions (no additional properties)
└─ ExtractionOptions (standalone - Overwrite, ExtractFullPath, PreserveFileTime, PreserveAttributes)
```
**Issues:**
- `ExtractionOptions` doesn't inherit from `OptionsBase` - no encoding support during extraction
- Progress reporting inconsistency between readers and extraction
- Obsolete properties (`ChecksumIsValid`, `Version`) with unclear migration path
### Implementation Priorities
**High Priority (Non-Breaking):**
1. Add API usage guide (Archive vs Reader, factory recommendations, async best practices)
2. Fix progress reporting consistency
3. Complete async implementation in writers
**Medium Priority (Next Major Version):**
1. Unify factory pattern - deprecate format-specific static `Open` methods
2. Clean up options classes - make `ExtractionOptions` inherit from `OptionsBase`
3. Clarify archive types - remove Arc/Arj from `ArchiveType` enum or add full support
4. Standardize naming across archive types
**Low Priority:**
1. Add BZip2 archive support similar to GZipArchive
2. Complete obsolete property cleanup with migration guide
### Backward Compatibility Strategy
**Safe (Non-Breaking) Changes:**
- Add new methods to interfaces (use default implementations)
- Add new options properties (with defaults)
- Add new factory methods
- Improve async implementations
- Add progress reporting support
**Breaking Changes to Avoid:**
- ❌ Removing format-specific `Open` methods (deprecate instead)
- ❌ Changing `LeaveStreamOpen` default (currently `true`)
- ❌ Removing obsolete properties before major version bump
- ❌ Changing return types or signatures of existing methods
**Deprecation Pattern:**
- Use `[Obsolete]` for one major version
- Use `[EditorBrowsable(EditorBrowsableState.Never)]` in next major version
- Remove in following major version

155
.github/workflows/NUGET_RELEASE.md vendored Normal file
View File

@@ -0,0 +1,155 @@
# NuGet Release Workflow
This document describes the automated NuGet release workflow for SharpCompress.
## Overview
The `nuget-release.yml` workflow automatically builds, tests, and publishes SharpCompress packages to NuGet.org when:
- Changes are pushed to the `master` or `release` branch
- A version tag (format: `MAJOR.MINOR.PATCH`) is pushed
The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.
## How It Works
### Version Determination
The workflow automatically determines the version based on whether the commit is tagged using C# code in the build project:
1. **Tagged Release (Stable)**:
- If the current commit has a version tag (e.g., `0.42.1`)
- Uses the tag as the version number
- Published as a stable release
2. **Untagged Release (Prerelease)**:
- If the current commit is NOT tagged
- Creates a prerelease version based on the next minor version
- Format: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`
- Example: `0.43.0-beta.123` (if last tag is 0.42.x)
- Published as a prerelease to NuGet.org (Windows build only)
### Workflow Steps
The workflow runs on a matrix of operating systems (Windows and Ubuntu):
1. **Checkout**: Fetches the repository with full history for version detection
2. **Setup .NET**: Installs .NET 10.0
3. **Determine Version**: Runs `determine-version` build target to check for tags and determine version
4. **Update Version**: Runs `update-version` build target to update the version in the project file
5. **Build and Test**: Runs the full build and test suite on both platforms
6. **Upload Artifacts**: Uploads the generated `.nupkg` files as workflow artifacts (separate for each OS)
7. **Push to NuGet**: (Windows only) Runs `push-to-nuget` build target to publish the package to NuGet.org using the API key
All version detection, file updates, and publishing logic is implemented in C# in the `build/Program.cs` file using build targets.
## Setup Requirements
### 1. NuGet API Key Secret
The workflow requires a `NUGET_API_KEY` secret to be configured in the repository settings:
1. Go to https://www.nuget.org/account/apikeys
2. Create a new API key with "Push" permission for the SharpCompress package
3. In GitHub, go to: **Settings****Secrets and variables****Actions**
4. Create a new secret named `NUGET_API_KEY` with the API key value
### 2. Branch Protection (Recommended)
Consider enabling branch protection rules for the `release` branch to ensure:
- Code reviews are required before merging
- Status checks pass before merging
- Only authorized users can push to the branch
## Usage
### Creating a Stable Release
There are two ways to trigger a stable release:
**Method 1: Push tag to trigger workflow**
1. Ensure all changes are committed on the `master` or `release` branch
2. Create and push a version tag:
```bash
git checkout master # or release
git tag 0.43.0
git push origin 0.43.0
```
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)
**Method 2: Tag after pushing to branch**
1. Ensure all changes are merged and pushed to the `master` or `release` branch
2. Create and push a version tag on the already-pushed commit:
```bash
git checkout master # or release
git tag 0.43.0
git push origin 0.43.0
```
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)
### Creating a Prerelease
1. Push changes to the `master` or `release` branch without tagging:
```bash
git checkout master # or release
git push origin master # or release
```
2. The workflow will automatically:
- Build and test the project on both Windows and Ubuntu
- Publish a prerelease version like `0.43.0-beta.456` to NuGet.org (Windows build)
## Troubleshooting
### Workflow Fails to Push to NuGet
- **Check the API Key**: Ensure `NUGET_API_KEY` is set correctly in repository secrets
- **Check API Key Permissions**: Verify the API key has "Push" permission for SharpCompress
- **Check API Key Expiration**: NuGet API keys may expire; create a new one if needed
### Version Conflict
If you see "Package already exists" errors:
- The workflow uses `--skip-duplicate` flag to handle this gracefully
- If you need to republish the same version, delete it from NuGet.org first (if allowed)
### Build or Test Failures
- The workflow will not push to NuGet if build or tests fail
- Check the workflow logs in GitHub Actions for details
- Fix the issues and push again
## Manual Package Creation
If you need to create a package manually without publishing:
```bash
dotnet run --project build/build.csproj -- publish
```
The package will be created in the `artifacts/` directory.
## Build Targets
The workflow uses the following C# build targets defined in `build/Program.cs`:
- **determine-version**: Detects version from git tags and outputs VERSION and PRERELEASE variables
- **update-version**: Updates VersionPrefix, AssemblyVersion, and FileVersion in the project file
- **push-to-nuget**: Pushes the generated NuGet packages to NuGet.org (requires NUGET_API_KEY)
These targets can be run manually for testing:
```bash
# Determine the version
dotnet run --project build/build.csproj -- determine-version
# Update version in project file
VERSION=0.43.0 dotnet run --project build/build.csproj -- update-version
# Push to NuGet (requires NUGET_API_KEY environment variable)
NUGET_API_KEY=your-key dotnet run --project build/build.csproj -- push-to-nuget
```
## Related Files
- `.github/workflows/nuget-release.yml` - The workflow definition
- `build/Program.cs` - Build script with version detection and publishing logic
- `src/SharpCompress/SharpCompress.csproj` - Project file with version information

120
.github/workflows/TESTING.md vendored Normal file
View File

@@ -0,0 +1,120 @@
# Testing Guide for NuGet Release Workflow
This document describes how to test the NuGet release workflow.
## Testing Strategy
Since this workflow publishes to NuGet.org and requires repository secrets, testing should be done carefully. The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.
## Pre-Testing Checklist
- [x] Workflow YAML syntax validated
- [x] Version determination logic tested locally
- [x] Version update logic tested locally
- [x] Build script works (`dotnet run --project build/build.csproj`)
## Manual Testing Steps
### 1. Test Prerelease Publishing (Recommended First Test)
This tests the workflow on untagged commits to the master or release branch.
**Steps:**
1. Ensure `NUGET_API_KEY` secret is configured in repository settings
2. Create a test commit on the `master` or `release` branch (e.g., update a comment or README)
3. Push to the `master` or `release` branch
4. Monitor the GitHub Actions workflow at: https://github.com/adamhathcock/sharpcompress/actions
5. Verify:
- Workflow triggers and runs successfully on both Windows and Ubuntu
- Version is determined correctly (e.g., `0.43.0-beta.XXX` if last tag is 0.42.x)
- Build and tests pass on both platforms
- Package artifacts are uploaded for both platforms
- Package is pushed to NuGet.org as prerelease (Windows build only)
**Expected Outcome:**
- A new prerelease package appears on NuGet.org: https://www.nuget.org/packages/SharpCompress/
- Package version follows pattern: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`
### 2. Test Tagged Release Publishing
This tests the workflow when a version tag is pushed.
**Steps:**
1. Prepare the `master` or `release` branch with all desired changes
2. Create a version tag (must be a pure semantic version like `MAJOR.MINOR.PATCH`):
```bash
git checkout master # or release
git tag 0.42.2
git push origin 0.42.2
```
3. Monitor the GitHub Actions workflow
4. Verify:
- Workflow triggers and runs successfully on both Windows and Ubuntu
- Version is determined as the tag (e.g., `0.42.2`)
- Build and tests pass on both platforms
- Package artifacts are uploaded for both platforms
- Package is pushed to NuGet.org as stable release (Windows build only)
**Expected Outcome:**
- A new stable release package appears on NuGet.org
- Package version matches the tag
### 3. Test Duplicate Package Handling
This tests the `--skip-duplicate` flag behavior.
**Steps:**
1. Push to the `release` branch without making changes
2. Monitor the workflow
3. Verify:
- Workflow runs but NuGet push is skipped with "duplicate" message
- No errors occur
### 4. Test Build Failure Handling
This tests that failed builds don't publish packages.
**Steps:**
1. Introduce a breaking change in a test or code
2. Push to the `release` branch
3. Verify:
- Workflow runs and detects the failure
- Build or test step fails
- NuGet push step is skipped
- No package is published
## Verification
After each test, verify:
1. **GitHub Actions Logs**: Check the workflow logs for any errors or warnings
2. **NuGet.org**: Verify the package appears with correct version and metadata
3. **Artifacts**: Download and inspect the uploaded artifacts
## Rollback/Cleanup
If testing produces unwanted packages:
1. **Prerelease packages**: Can be unlisted on NuGet.org (Settings → Unlist)
2. **Stable packages**: Cannot be deleted, only unlisted (use test versions)
3. **Tags**: Can be deleted with:
```bash
git tag -d 0.42.2
git push origin :refs/tags/0.42.2
```
## Known Limitations
- NuGet.org does not allow re-uploading the same version
- Deleted packages on NuGet.org reserve the version number
- The workflow requires the `NUGET_API_KEY` secret to be set
## Success Criteria
The workflow is considered successful if:
- ✅ Prerelease versions are published correctly with beta suffix
- ✅ Tagged versions are published as stable releases
- ✅ Build and test failures prevent publishing
- ✅ Duplicate packages are handled gracefully
- ✅ Workflow logs are clear and informative

61
.github/workflows/nuget-release.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: NuGet Release
on:
push:
branches:
- 'master'
- 'release'
tags:
- '[0-9]+.[0-9]+.[0-9]+'
pull_request:
branches:
- 'master'
- 'release'
permissions:
contents: read
jobs:
build-and-publish:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history for versioning
- uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
# Determine version using C# build target
- name: Determine Version
id: version
run: dotnet run --project build/build.csproj -- determine-version
# Update version in project file using C# build target
- name: Update Version in Project
run: dotnet run --project build/build.csproj -- update-version
env:
VERSION: ${{ steps.version.outputs.version }}
# Build and test
- name: Build and Test
run: dotnet run --project build/build.csproj
# Upload artifacts for verification
- name: Upload NuGet Package
uses: actions/upload-artifact@v6
with:
name: ${{ matrix.os }}-nuget-package
path: artifacts/*.nupkg
# Push to NuGet.org using C# build target (Windows only, not on PRs)
- name: Push to NuGet
if: success() && matrix.os == 'windows-latest' && github.event_name != 'pull_request'
run: dotnet run --project build/build.csproj -- push-to-nuget
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}

17
.gitignore vendored
View File

@@ -4,12 +4,23 @@ _ReSharper.SharpCompress/
bin/
*.suo
*.user
TestArchives/Scratch/
TestArchives/Scratch2/
tests/TestArchives/Scratch/
tests/TestArchives/Scratch2/
TestResults/
*.nupkg
packages/*/
project.lock.json
test/TestArchives/Scratch
tests/TestArchives/Scratch
tests/TestArchives/*/Scratch
tests/TestArchives/*/Scratch2
.vs
tools
.idea/
artifacts/
.DS_Store
*.snupkg
# BenchmarkDotNet artifacts
BenchmarkDotNet.Artifacts/
**/BenchmarkDotNet.Artifacts/

9
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"recommendations": [
"ms-dotnettools.csdevkit",
"ms-dotnettools.csharp",
"ms-dotnettools.vscode-dotnet-runtime",
"csharpier.csharpier-vscode",
"formulahendry.dotnet-test-explorer"
]
}

97
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,97 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Tests (net10.0)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "dotnet",
"args": [
"test",
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
"-f",
"net10.0",
"--no-build",
"--verbosity=normal"
],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Debug Specific Test (net10.0)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "dotnet",
"args": [
"test",
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
"-f",
"net10.0",
"--no-build",
"--filter",
"FullyQualifiedName~${input:testName}"
],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Debug Performance Tests",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "dotnet",
"args": [
"run",
"--project",
"${workspaceFolder}/tests/SharpCompress.Performance/SharpCompress.Performance.csproj",
"--no-build"
],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Debug Build Script",
"type": "coreclr",
"request": "launch",
"program": "dotnet",
"args": [
"run",
"--project",
"${workspaceFolder}/build/build.csproj",
"--",
"${input:buildTarget}"
],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
}
],
"inputs": [
{
"id": "testName",
"type": "promptString",
"description": "Enter test name or pattern (e.g., TestMethodName or ClassName)",
"default": ""
},
{
"id": "buildTarget",
"type": "pickString",
"description": "Select build target",
"options": [
"clean",
"restore",
"build",
"test",
"format",
"publish",
"default"
],
"default": "build"
}
]
}

29
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,29 @@
{
"dotnet.defaultSolution": "SharpCompress.sln",
"files.exclude": {
"**/bin": true,
"**/obj": true
},
"files.watcherExclude": {
"**/bin/**": true,
"**/obj/**": true,
"**/artifacts/**": true
},
"search.exclude": {
"**/bin": true,
"**/obj": true,
"**/artifacts": true
},
"editor.formatOnSave": false,
"[csharp]": {
"editor.defaultFormatter": "csharpier.csharpier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
}
},
"csharpier.enableDebugLogs": false,
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,
"dotnet-test-explorer.testProjectPath": "tests/**/*.csproj"
}

178
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,178 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/SharpCompress.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "build-release",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/SharpCompress.sln",
"-c",
"Release",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"problemMatcher": "$msCompile",
"group": "build"
},
{
"label": "build-library",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/src/SharpCompress/SharpCompress.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"problemMatcher": "$msCompile",
"group": "build"
},
{
"label": "restore",
"command": "dotnet",
"type": "process",
"args": [
"restore",
"${workspaceFolder}/SharpCompress.sln"
],
"problemMatcher": "$msCompile"
},
{
"label": "clean",
"command": "dotnet",
"type": "process",
"args": [
"clean",
"${workspaceFolder}/SharpCompress.sln"
],
"problemMatcher": "$msCompile"
},
{
"label": "test",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
"--no-build",
"--verbosity=normal"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "test",
"isDefault": true
},
"dependsOn": "build"
},
{
"label": "test-net10",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
"-f",
"net10.0",
"--no-build",
"--verbosity=normal"
],
"problemMatcher": "$msCompile",
"group": "test",
"dependsOn": "build"
},
{
"label": "test-net48",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/tests/SharpCompress.Test/SharpCompress.Test.csproj",
"-f",
"net48",
"--no-build",
"--verbosity=normal"
],
"problemMatcher": "$msCompile",
"group": "test",
"dependsOn": "build"
},
{
"label": "format",
"command": "dotnet",
"type": "process",
"args": [
"csharpier",
"."
],
"problemMatcher": []
},
{
"label": "format-check",
"command": "dotnet",
"type": "process",
"args": [
"csharpier",
"check",
"."
],
"problemMatcher": []
},
{
"label": "run-build-script",
"command": "dotnet",
"type": "process",
"args": [
"run",
"--project",
"${workspaceFolder}/build/build.csproj"
],
"problemMatcher": "$msCompile"
},
{
"label": "pack",
"command": "dotnet",
"type": "process",
"args": [
"pack",
"${workspaceFolder}/src/SharpCompress/SharpCompress.csproj",
"-c",
"Release",
"-o",
"${workspaceFolder}/artifacts/"
],
"problemMatcher": "$msCompile",
"dependsOn": "build-release"
},
{
"label": "performance-tests",
"command": "dotnet",
"type": "process",
"args": [
"run",
"--project",
"${workspaceFolder}/tests/SharpCompress.Performance/SharpCompress.Performance.csproj",
"-c",
"Release"
],
"problemMatcher": "$msCompile"
}
]
}

181
AGENTS.md Normal file
View File

@@ -0,0 +1,181 @@
---
description: 'Guidelines for building SharpCompress - A C# compression library'
applyTo: '**/*.cs'
---
# SharpCompress Development
## About SharpCompress
SharpCompress is a pure C# compression library supporting multiple archive formats (Zip, Tar, GZip, BZip2, 7Zip, Rar, LZip, XZ, ZStandard) for .NET Framework 4.62, .NET Standard 2.1, .NET 6.0, and .NET 8.0. The library provides both seekable Archive APIs and forward-only Reader/Writer APIs for streaming scenarios.
## C# Instructions
- Always use the latest version C#, currently C# 13 features.
- Write clear and concise comments for each function.
- Follow the existing code style and patterns in the codebase.
## General Instructions
- **Agents should NEVER commit to git** - Agents should stage files and leave committing to the user. Only create commits when the user explicitly requests them.
- Make only high confidence suggestions when reviewing code changes.
- Write code with good maintainability practices, including comments on why certain design decisions were made.
- Handle edge cases and write clear exception handling.
- For libraries or external dependencies, mention their usage and purpose in comments.
- Preserve backward compatibility when making changes to public APIs.
## Naming Conventions
- Follow PascalCase for component names, method names, and public members.
- Use camelCase for private fields and local variables.
- Prefix interface names with "I" (e.g., IUserService).
## Code Formatting
**Copilot agents: You MUST run the `format` task after making code changes to ensure consistency.**
- Use CSharpier for code formatting to ensure consistent style across the project
- CSharpier is configured as a local tool in `.config/dotnet-tools.json`
### Commands
1. **Restore tools** (first time only):
```bash
dotnet tool restore
```
2. **Check if files are formatted correctly** (doesn't modify files):
```bash
dotnet csharpier check .
```
- Exit code 0: All files are properly formatted
- Exit code 1: Some files need formatting (will show which files and differences)
3. **Format files** (modifies files):
```bash
dotnet csharpier format .
```
- Formats all files in the project to match CSharpier style
- Run from project root directory
4. **Configure your IDE** to format on save using CSharpier for the best experience
### Additional Notes
- The project also uses `.editorconfig` for editor settings (indentation, encoding, etc.)
- Let CSharpier handle code style while `.editorconfig` handles editor behavior
- Always run `dotnet csharpier check .` before committing to verify formatting
## Project Setup and Structure
- The project targets multiple frameworks: .NET Framework 4.62, .NET Standard 2.1, .NET 6.0, and .NET 8.0
- Main library is in `src/SharpCompress/`
- Tests are in `tests/SharpCompress.Test/`
- Performance tests are in `tests/SharpCompress.Performance/`
- Test archives are in `tests/TestArchives/`
- Build project is in `build/`
- Use `dotnet build` to build the solution
- Use `dotnet test` to run tests
- Solution file: `SharpCompress.sln`
### Directory Structure
```
src/SharpCompress/
├── Archives/ # IArchive implementations (Zip, Tar, Rar, 7Zip, GZip)
├── Readers/ # IReader implementations (forward-only)
├── Writers/ # IWriter implementations (forward-only)
├── Compressors/ # Low-level compression streams (BZip2, Deflate, LZMA, etc.)
├── Factories/ # Format detection and factory pattern
├── Common/ # Shared types (ArchiveType, Entry, Options)
├── Crypto/ # Encryption implementations
└── IO/ # Stream utilities and wrappers
tests/SharpCompress.Test/
├── Zip/, Tar/, Rar/, SevenZip/, GZip/, BZip2/ # Format-specific tests
├── TestBase.cs # Base test class with helper methods
└── TestArchives/ # Test data (not checked into main test project)
```
### Factory Pattern
All format types implement factory interfaces (`IArchiveFactory`, `IReaderFactory`, `IWriterFactory`) for auto-detection:
- `ReaderFactory.Open()` - Auto-detects format by probing stream
- `WriterFactory.Open()` - Creates writer for specified `ArchiveType`
- Factories located in: `src/SharpCompress/Factories/`
## Nullable Reference Types
- Declare variables non-nullable, and check for `null` at entry points.
- Always use `is null` or `is not null` instead of `== null` or `!= null`.
- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
## SharpCompress-Specific Guidelines
### Supported Formats
SharpCompress supports multiple archive and compression formats:
- **Archive Formats**: Zip, Tar, 7Zip, Rar (read-only)
- **Compression**: DEFLATE, BZip2, LZMA/LZMA2, PPMd, ZStandard (decompress only), Deflate64 (decompress only)
- **Combined Formats**: Tar.GZip, Tar.BZip2, Tar.LZip, Tar.XZ, Tar.ZStandard
- See [docs/FORMATS.md](docs/FORMATS.md) for complete format support matrix
### Stream Handling Rules
- **Disposal**: As of version 0.21, SharpCompress closes wrapped streams by default
- Use `ReaderOptions` or `WriterOptions` with `LeaveStreamOpen = true` to control stream disposal
- Use `NonDisposingStream` wrapper when working with compression streams directly to prevent disposal
- Always dispose of readers, writers, and archives in `using` blocks
- For forward-only operations, use Reader/Writer APIs; for random access, use Archive APIs
### Async/Await Patterns
- All I/O operations support async/await with `CancellationToken`
- Async methods follow the naming convention: `MethodNameAsync`
- Key async methods:
- `WriteEntryToAsync` - Extract entry asynchronously
- `WriteAllToDirectoryAsync` - Extract all entries asynchronously
- `WriteAsync` - Write entry asynchronously
- `WriteAllAsync` - Write directory asynchronously
- `OpenEntryStreamAsync` - Open entry stream asynchronously
- Always provide `CancellationToken` parameter in async methods
### Archive APIs vs Reader/Writer APIs
- **Archive API**: Use for random access with seekable streams (e.g., `ZipArchive`, `TarArchive`)
- **Reader API**: Use for forward-only reading on non-seekable streams (e.g., `ZipReader`, `TarReader`)
- **Writer API**: Use for forward-only writing on streams (e.g., `ZipWriter`, `TarWriter`)
- 7Zip only supports Archive API due to format limitations
### Tar-Specific Considerations
- Tar format requires file size in the header
- If no size is specified to TarWriter and the stream is not seekable, an exception will be thrown
- Tar combined with compression (GZip, BZip2, LZip, XZ) is supported
### Zip-Specific Considerations
- Supports Zip64 for large files (seekable streams only)
- Supports PKWare and WinZip AES encryption
- Multiple compression methods: None, Shrink, Reduce, Implode, DEFLATE, Deflate64, BZip2, LZMA, PPMd
- Encrypted LZMA is not supported
### Performance Considerations
- For large files, use Reader/Writer APIs with non-seekable streams to avoid loading entire file in memory
- Leverage async I/O for better scalability
- Consider compression level trade-offs (speed vs. size)
- Use appropriate buffer sizes for stream operations
## Testing
- Always include test cases for critical paths of the application.
- Test with multiple archive formats when making changes to core functionality.
- Include tests for both Archive and Reader/Writer APIs when applicable.
- Test async operations with cancellation tokens.
- Do not emit "Act", "Arrange" or "Assert" comments.
- Copy existing style in nearby files for test method names and capitalization.
- Use test archives from `tests/TestArchives` directory for consistency.
- Test stream disposal and `LeaveStreamOpen` behavior.
- Test edge cases: empty archives, large files, corrupted archives, encrypted archives.
### Test Organization
- Base class: `TestBase` - Provides `TEST_ARCHIVES_PATH`, `SCRATCH_FILES_PATH`, temp directory management
- Framework: xUnit with AwesomeAssertions
- Test archives: `tests/TestArchives/` - Use existing archives, don't create new ones unnecessarily
- Match naming style of nearby test files
## Common Pitfalls
1. **Don't mix Archive and Reader APIs** - Archive needs seekable stream, Reader doesn't
2. **Solid archives (Rar, 7Zip)** - Use `ExtractAllEntries()` for best performance, not individual entry extraction
3. **Stream disposal** - Always set `LeaveStreamOpen` explicitly when needed (default is to close)
4. **Tar + non-seekable stream** - Must provide file size or it will throw
6. **Format detection** - Use `ReaderFactory.Open()` for auto-detection, test with actual archive files

17
Directory.Build.props Normal file
View File

@@ -0,0 +1,17 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<AnalysisMode>Recommended</AnalysisMode>
<WarningsAsErrors>true</WarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RunAnalyzersDuringLiveAnalysis>False</RunAnalyzersDuringLiveAnalysis>
<RunAnalyzersDuringBuild>False</RunAnalyzersDuringBuild>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
</Project>

25
Directory.Packages.props Normal file
View File

@@ -0,0 +1,25 @@
<Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Bullseye" Version="6.1.0" />
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
<PackageVersion Include="Glob" Version="1.1.9" />
<PackageVersion Include="JetBrains.Profiler.SelfApi" Version="2.5.15" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
<PackageVersion Include="Microsoft.NET.ILLink.Task" Version="10.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageVersion Include="SimpleExec" Version="13.0.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.0" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Memory" Version="4.6.3" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<GlobalPackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
<GlobalPackageReference
Include="Microsoft.VisualStudio.Threading.Analyzers"
Version="17.14.15"
/>
</ItemGroup>
</Project>

View File

@@ -1,31 +0,0 @@
# Archive Formats
## Accessing Archives
Archive classes allow random access to a seekable stream.
Reader classes allow forward-only reading
Writer classes allow forward-only Writing
## Supported Format Table
| Archive Format | Compression Format(s) | Compress/Decompress | Archive API | Reader API | Writer API |
| --- | --- | --- | --- | --- | --- |
| Rar | Rar | Decompress (1) | RarArchive | RarReader | N/A |
| Zip (2) | None, DEFLATE, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
| Tar | None, BZip2, GZip | Both | TarArchive | TarReader | TarWriter (3) |
| GZip (single file) | GZip | Both | GZipArchive | GZipReader | GZipWriter |
| 7Zip (4) | LZMA, LZMA2, BZip2, PPMd, BCJ, BCJ2, Deflate | Decompress | SevenZipArchive | N/A | N/A |
1. SOLID Rars are only supported in the RarReader API.
2. Zip format supports pkware and WinzipAES encryption. However, encrypted LZMA is not supported.
3. The Tar format requires a file size in the header. If no size is specified to the TarWriter and the stream is not seekable, then an exception will be thrown.
4. The 7Zip format doesn't allow for reading as a forward-only stream so 7Zip is only supported through the Archive API
## Compressors
For those who want to directly compress/decompress bits
| Compressor | Compress/Decompress |
| --- | --- |
| BZip2Stream | Both |
| GZipStream | Both |
| DeflateStream | Both |
| LZMAStream | Both |
| PPMdStream | Both |

9
NuGet.config Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>

110
README.md
View File

@@ -1,108 +1,48 @@
# SharpCompress
SharpCompress is a compression library for .NET/Mono/Silverlight/WP7 that can unrar, un7zip, unzip, untar unbzip2 and ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip are implemented.
SharpCompress is a compression library in pure C# for .NET Framework 4.8, .NET 8.0 and .NET 10.0 that can unrar, un7zip, unzip, untar unbzip2, ungzip, unlzip, unzstd, unarc and unarj with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip/lzip are implemented.
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
[![Build status](https://ci.appveyor.com/api/projects/status/voxg971oemmvxh1e/branch/master?svg=true)](https://ci.appveyor.com/project/adamhathcock/sharpcompress/branch/master)
**NEW:** All I/O operations now support async/await for improved performance and scalability. See the [USAGE.md](docs/USAGE.md#async-examples) for examples.
GitHub Actions Build -
[![SharpCompress](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml/badge.svg)](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml)
[![Static Badge](https://img.shields.io/badge/API%20Docs-DNDocs-190088?logo=readme&logoColor=white)](https://dndocs.com/d/sharpcompress/api/index.html)
## Need Help?
Post Issues on Github!
Check the [Supported Formats](FORMATS.md) and [basic usage.](USAGE.md)
Check the [Supported Formats](docs/FORMATS.md) and [Basic Usage.](docs/USAGE.md)
## Recommended Formats
In general, I recommend GZip (Deflate)/BZip2 (BZip)/LZip (LZMA) as the simplicity of the formats lend to better long term archival as well as the streamability. Tar is often used in conjunction for multiple files in a single archive (e.g. `.tar.gz`)
Zip is okay, but it's a very hap-hazard format and the variation in headers and implementations makes it hard to get correct. Uses Deflate by default but supports a lot of compression methods.
RAR is not recommended as it's a proprietary format and the compression is closed source. Use Tar/LZip for LZMA
7Zip and XZ both are overly complicated. 7Zip does not support streamable formats. XZ has known holes explained here: (http://www.nongnu.org/lzip/xz_inadequate.html) Use Tar/LZip for LZMA compression instead.
ZStandard is an efficient format that works well for streaming with a flexible compression level to tweak the speed/performance trade off you are looking for. We currently only implement decompression for ZStandard but as we leverage the [ZstdSharp](https://github.com/oleg-st/ZstdSharp) library one could likely add compression support without much trouble (PRs are welcome!).
## A Simple Request
Hi everyone. I hope you're using SharpCompress and finding it useful. Please give me feedback on what you'd like to see changed especially as far as usability goes. New feature suggestions are always welcome as well. I would also like to know what projects SharpCompress is being used in. I like seeing how it is used to give me ideas for future versions. Thanks!
Please do not email me directly to ask for help. If you think there is a real issue, please report it here.
Please do not email me directly to ask for help. If you think there is a real issue, please report it here.
## Want to contribute?
I'm always looking for help or ideas. Please submit code or email with ideas. Unfortunately, just letting me know you'd like to help is not enough because I really have no overall plan of what needs to be done. I'll definitely accept code submissions and add you as a member of the project!
## TODOs (always lots)
## Notes
* RAR 5 support
* 7Zip writing
* Zip64
* Multi-volume Zip support.
* RAR5 support
XZ implementation based on: https://github.com/sambott/XZ.NET by @sambott
## Version Log
### Version 0.13.0
* Breaking change: Big refactor of Options on API.
* 7Zip supports Deflate
### Version 0.12.4
* Forward only zip issue fix https://github.com/adamhathcock/sharpcompress/issues/160
* Try to fix frameworks again by copying targets from JSON.NET
### Version 0.12.3
* 7Zip fixes https://github.com/adamhathcock/sharpcompress/issues/73
* Maybe all profiles will work with project.json now
### Version 0.12.2
* Support Profile 259 again
### Version 0.12.1
* Support Silverlight 5
### Version 0.12.0
* .NET Core RTM!
* Bug fix for Tar long paths
### Version 0.11.6
* Bug fix for global header in Tar
* Writers now have a leaveOpen `bool` overload. They won't close streams if not-requested to.
### Version 0.11.5
* Bug fix in Skip method
### Version 0.11.4
* SharpCompress is now endian neutral (matters for Mono platforms)
* Fix for Inflate (need to change implementation)
* Fixes for RAR detection
### Version 0.11.1
* Added Cancel on IReader
* Removed .NET 2.0 support and LinqBridge dependency
### Version 0.11
* Been over a year, contains mainly fixes from contributors!
* Possible breaking change: ArchiveEncoding is UTF8 by default now.
* TAR supports writing long names using longlink
* RAR Protect Header added
### Version 0.10.3
* Finally fixed Disposal issue when creating a new archive with the Archive API
### Version 0.10.2
* Fixed Rar Header reading for invalid extended time headers.
* Windows Store assembly is now strong named
* Known issues with Long Tar names being worked on
* Updated to VS2013
* Portable targets SL5 and Windows Phone 8 (up from SL4 and WP7)
### Version 0.10.1
* Fixed 7Zip extraction performance problem
### Version 0.10:
* Added support for RAR Decryption (thanks to https://github.com/hrasyid)
* Embedded some BouncyCastle crypto classes to allow RAR Decryption and Winzip AES Decryption in Portable and Windows Store DLLs
* Built in Release (I think)
Some Help/Discussion: https://sharpcompress.codeplex.com/discussions
XZ BCJ filters support contributed by Louis-Michel Bergeron, on behalf of aDolus Technology Inc. - 2022
7Zip implementation based on: https://code.google.com/p/managed-lzma/

View File

@@ -1,44 +1,62 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F18F1765-4A02-42FD-9BEF-F0E2FCBD9D17}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SharpCompress", "src\SharpCompress\SharpCompress.xproj", "{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C5BE746-03E5-4895-9988-0B57F162F86C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0F0901FF-E8D9-426A-B5A2-17C7F47C1529}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SharpCompress.Test", "test\SharpCompress.Test\SharpCompress.Test.xproj", "{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5}"
ProjectSection(ProjectDependencies) = postProject
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998} = {FD19DDD8-72B2-4024-8665-0D1F7A2AA998}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.Build.0 = Release|Any CPU
{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998} = {3C5BE746-03E5-4895-9988-0B57F162F86C}
{3B80E585-A2F3-4666-8F69-C7FFDA0DD7E5} = {0F0901FF-E8D9-426A-B5A2-17C7F47C1529}
EndGlobalSection
EndGlobal
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C5BE746-03E5-4895-9988-0B57F162F86C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0F0901FF-E8D9-426A-B5A2-17C7F47C1529}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpCompress", "src\SharpCompress\SharpCompress.csproj", "{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpCompress.Test", "tests\SharpCompress.Test\SharpCompress.Test.csproj", "{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "build", "build\build.csproj", "{D4D613CB-5E94-47FB-85BE-B8423D20C545}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB42573-7D22-4490-BA12-1B7FB99CE7FB}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
global.json = global.json
.editorconfig = .editorconfig
.gitignore = .gitignore
Directory.Packages.props = Directory.Packages.props
NuGet.config = NuGet.config
.github\workflows\nuget-release.yml = .github\workflows\nuget-release.yml
README.md = README.md
AGENTS.md = AGENTS.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Performance", "tests\SharpCompress.Performance\SharpCompress.Performance.csproj", "{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998}.Release|Any CPU.Build.0 = Release|Any CPU
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F}.Release|Any CPU.Build.0 = Release|Any CPU
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4D613CB-5E94-47FB-85BE-B8423D20C545}.Release|Any CPU.Build.0 = Release|Any CPU
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FD19DDD8-72B2-4024-8665-0D1F7A2AA998} = {3C5BE746-03E5-4895-9988-0B57F162F86C}
{F2B1A1EB-0FA6-40D0-8908-E13247C7226F} = {0F0901FF-E8D9-426A-B5A2-17C7F47C1529}
{5BDE6DBC-9E5F-4E21-AB71-F138A3E72B17} = {0F0901FF-E8D9-426A-B5A2-17C7F47C1529}
EndGlobalSection
EndGlobal

View File

@@ -15,17 +15,17 @@
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">Basic Clean</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/APPLY_ON_COMPLETION/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ARGUMENTS_NAMED/@EntryValue">Named</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ARGUMENTS_NAMED/@EntryValue">Positional</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_FIRST_ARG_BY_PAREN/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_FIRST_ARG_BY_PAREN/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_LINQ_QUERY/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARGUMENT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXPRESSION/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXPRESSION/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_FOR_STMT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">True</s:Boolean>
@@ -42,16 +42,20 @@
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_ANONYMOUS_METHOD_BLOCK/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_ANONYMOUS_METHOD_BLOCK/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSORHOLDER_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSORHOLDER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
@@ -63,18 +67,22 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVar</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVar</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVar</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
@@ -114,6 +122,17 @@
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=6af8f80e_002D9fdd_002D4223_002D8e02_002D473db916f9b2/@EntryIndexedValue">&lt;SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from Solution" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
&lt;Solution /&gt;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>

BIN
SharpCompress.snk Normal file

Binary file not shown.

131
USAGE.md
View File

@@ -1,131 +0,0 @@
# SharpCompress Usage
## Stream Rules
When dealing with Streams, the rule should be that you don't close a stream you didn't create. This, in effect, should mean you should always put a Stream in a using block to dispose it.
However, the .NET Framework often has classes that will dispose streams by default to make things "easy" like the following:
```C#
using (var reader = new StreamReader(File.Open("foo")))
{
...
}
```
In this example, reader should get disposed. However, stream rules should say the the `FileStream` created by `File.Open` should remain open. However, the .NET Framework closes it for you by default unless you override the constructor. In general, you should be writing Stream code like this:
```C#
using (var fileStream = File.Open("foo"))
using (var reader = new StreamReader(fileStream))
{
...
}
```
To deal with the "correct" rules as well as the expectations of users, I've decided on this:
* When writing, leave streams open.
* When reading, close streams
To be explicit though, consider always using the overloads that use `ReaderOptions` or `WriterOptions` and explicitly set `LeaveStreamOpen` the way you want.
## Samples
Also, look over the tests for more thorough [examples](https://github.com/adamhathcock/sharpcompress/tree/master/test/SharpCompress.Test)
### Create Zip Archive from all files in a directory to a file
```C#
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo("C:\\temp.zip", CompressionType.Deflate);
}
```
### Create Zip Archive from all files in a directory and save in memory
```C#
var memoryStream = new MemoryStream();
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo(memoryStream, new WriterOptions(CompressionType.Deflate)
{
LeaveStreamOpen = true
});
}
//reset memoryStream to be usable now
memoryStream.Position = 0;
```
### Extract all files from a Rar file to a directory using RarArchive
```C#
using (var archive = RarArchive.Open("Test.rar"))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory("D:\\temp", new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
```
### Use ReaderFactory to autodetect archive type and Open the entry stream
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2")))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Console.WriteLine(reader.Entry.Key);
reader.WriteEntryToDirectory(@"C:\temp", new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
}
```
### Use ReaderFactory to autodetect archive type and Open the entry stream
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2")))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
using (var entryStream = reader.OpenEntryStream())
{
entryStream.CopyTo(...);
}
}
}
}
```
### Use WriterFactory to write all files from a directory in a streaming manner.
```C#
using (Stream stream = File.OpenWrite("C:\\temp.tgz"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)
{
LeaveOpenStream = true
}))
{
writer.WriteAll("D:\\temp", "*", SearchOption.AllDirectories);
}
```

View File

@@ -1,17 +0,0 @@
version: '0.13.{build}'
init:
- git config --global core.autocrlf true
build_script:
- ps: .\build.ps1
test: off
cache:
- tools -> build.cake
- tools -> build.ps1
artifacts:
- path: nupkgs\*.nupkg
name: NuPkgs

View File

@@ -1,229 +0,0 @@
#addin "Cake.Json"
#addin "nuget:?package=NuGet.Core"
using NuGet;
//////////////////////////////////////////////////////////////////////
// ARGUMENTS
//////////////////////////////////////////////////////////////////////
var target = Argument("target", "Default");
var apiKey = Argument("apiKey", "");
var repo = Argument("repo", "");
//////////////////////////////////////////////////////////////////////
// PREPARATION
//////////////////////////////////////////////////////////////////////
var sources = new [] { "https://api.nuget.org/v3/index.json" };
var publishTarget = "";
Warning("=============");
var globalPath = MakeFullPath("global.json");
var nupkgs = MakeFullPath("nupkgs");
Warning("Operating on global.json: " + globalPath);
Warning("=============");
//////////////////////////////////////////////////////////////////////
// FUNCTIONS
//////////////////////////////////////////////////////////////////////
string MakeFullPath(string relativePath)
{
if (string.IsNullOrEmpty(repo))
{
return MakeAbsolute(new DirectoryPath(relativePath)).ToString();
}
if (!System.IO.Path.IsPathRooted(repo))
{
return MakeAbsolute(new DirectoryPath(System.IO.Path.Combine(repo,relativePath))).ToString();
}
return System.IO.Path.Combine(repo, relativePath);
}
IEnumerable<string> GetAllProjects()
{
var global = DeserializeJsonFromFile<JObject>(globalPath);
var projs = global["projects"].Select(x => x.ToString());
foreach(var y in projs)
{
yield return MakeFullPath(y);
}
}
IEnumerable<string> GetSourceProjects()
{
return GetAllProjects().Where(x => x.EndsWith("src"));
}
IEnumerable<string> GetTestProjects()
{
return GetAllProjects().Where(x => x.EndsWith("test"));
}
IEnumerable<string> GetFrameworks(string path)
{
var projectJObject = DeserializeJsonFromFile<JObject>(path);
foreach(var prop in ((JObject)projectJObject["frameworks"]).Properties())
{
yield return prop.Name;
}
}
string GetVersion(string path)
{
var projectJObject = DeserializeJsonFromFile<JObject>(path);
return ((JToken)projectJObject["version"]).ToString();
}
IEnumerable<string> GetProjectJsons(IEnumerable<string> projects)
{
foreach(var proj in projects)
{
foreach(var projectJson in GetFiles(proj + "/**/project.json"))
{
yield return MakeFullPath(projectJson.ToString());
}
}
}
bool IsNuGetPublished (FilePath file, string nugetSource)
{
var pkg = new ZipPackage(file.ToString());
var repo = PackageRepositoryFactory.Default.CreateRepository(nugetSource);
var packages = repo.FindPackagesById(pkg.Id);
var version = SemanticVersion.Parse(pkg.Version.ToString());
//Filter the list of packages that are not Release (Stable) versions
var exists = packages.Any (p => p.Version == version);
return exists;
}
//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////
Task("Restore")
.Does(() =>
{
var settings = new DotNetCoreRestoreSettings
{
Sources = sources,
NoCache = true
};
foreach(var project in GetProjectJsons(GetSourceProjects().Concat(GetTestProjects())))
{
DotNetCoreRestore(project, settings);
}
});
Task("Build")
.Does(() =>
{
var settings = new DotNetCoreBuildSettings
{
Configuration = "Release"
};
foreach(var project in GetProjectJsons(GetSourceProjects().Concat(GetTestProjects())))
{
foreach(var framework in GetFrameworks(project))
{
Information("Building: {0} on Framework: {1}", project, framework);
Information("========");
settings.Framework = framework;
DotNetCoreBuild(project, settings);
}
}
});
Task("Test")
.Does(() =>
{
var settings = new DotNetCoreTestSettings
{
Configuration = "Release",
Verbose = true
};
foreach(var project in GetProjectJsons(GetTestProjects()))
{
settings.Framework = GetFrameworks(project).First();
DotNetCoreTest(project.ToString(), settings);
}
}).ReportError(exception =>
{
Error(exception.ToString());
});
Task("Pack")
.Does(() =>
{
if (DirectoryExists(nupkgs))
{
DeleteDirectory(nupkgs, true);
}
CreateDirectory(nupkgs);
var settings = new DotNetCorePackSettings
{
Configuration = "Release",
OutputDirectory = nupkgs
};
foreach(var project in GetProjectJsons(GetSourceProjects()))
{
DotNetCorePack(project, settings);
}
});
Task("Publish")
.IsDependentOn("Restore")
.IsDependentOn("Build")
.IsDependentOn("Test")
.IsDependentOn("Pack")
.Does(() =>
{
var packages = GetFiles(nupkgs + "/*.nupkg");
foreach(var package in packages)
{
if (package.ToString().Contains("symbols"))
{
Warning("Skipping Symbols package " + package);
continue;
}
if (IsNuGetPublished(package, sources[1]))
{
throw new InvalidOperationException(package + " is already published.");
}
NuGetPush(package, new NuGetPushSettings{
ApiKey = apiKey,
Verbosity = NuGetVerbosity.Detailed,
Source = publishTarget
});
}
});
//////////////////////////////////////////////////////////////////////
// TASK TARGETS
//////////////////////////////////////////////////////////////////////
Task("Default")
.IsDependentOn("Restore")
.IsDependentOn("Build")
.IsDependentOn("Test")
.IsDependentOn("Pack");
//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////
RunTarget(target);

130
build.ps1
View File

@@ -1,130 +0,0 @@
<#
.SYNOPSIS
This is a Powershell script to bootstrap a Cake build.
.DESCRIPTION
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
and execute your Cake build script with the parameters you provide.
.PARAMETER Target
The build script target to run.
.PARAMETER Configuration
The build configuration to use.
.PARAMETER Verbosity
Specifies the amount of information to be displayed.
.PARAMETER WhatIf
Performs a dry run of the build script.
No tasks will be executed.
.PARAMETER ScriptArgs
Remaining arguments are added here.
.LINK
http://cakebuild.net
#>
[CmdletBinding()]
Param(
[string]$Script = "build.cake",
[string]$Target = "Default",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity = "Verbose",
[switch]$WhatIf,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
$CakeVersion = "0.16.1"
$DotNetChannel = "preview";
$DotNetVersion = "1.0.0-preview2-003131";
$DotNetInstallerUri = "https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0-preview2/scripts/obtain/dotnet-install.ps1";
$NugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
# Make sure tools folder exists
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
$ToolPath = Join-Path $PSScriptRoot "tools"
if (!(Test-Path $ToolPath)) {
Write-Verbose "Creating tools directory..."
New-Item -Path $ToolPath -Type directory | out-null
}
###########################################################################
# INSTALL .NET CORE CLI
###########################################################################
Function Remove-PathVariable([string]$VariableToRemove)
{
$path = [Environment]::GetEnvironmentVariable("PATH", "User")
if ($path -ne $null)
{
$newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
[Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "User")
}
$path = [Environment]::GetEnvironmentVariable("PATH", "Process")
if ($path -ne $null)
{
$newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
[Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "Process")
}
}
# Get .NET Core CLI path if installed.
$FoundDotNetCliVersion = $null;
if (Get-Command dotnet -ErrorAction SilentlyContinue) {
$FoundDotNetCliVersion = dotnet --version;
}
if($FoundDotNetCliVersion -ne $DotNetVersion) {
$InstallPath = Join-Path $PSScriptRoot ".dotnet"
if (!(Test-Path $InstallPath)) {
mkdir -Force $InstallPath | Out-Null;
}
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, "$InstallPath\dotnet-install.ps1");
& $InstallPath\dotnet-install.ps1 -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath;
Remove-PathVariable "$InstallPath"
$env:PATH = "$InstallPath;$env:PATH"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
$env:DOTNET_CLI_TELEMETRY_OPTOUT=1
}
###########################################################################
# INSTALL NUGET
###########################################################################
# Make sure nuget.exe exists.
$NugetPath = Join-Path $ToolPath "nuget.exe"
if (!(Test-Path $NugetPath)) {
Write-Host "Downloading NuGet.exe..."
(New-Object System.Net.WebClient).DownloadFile($NugetUrl, $NugetPath);
}
###########################################################################
# INSTALL CAKE
###########################################################################
# Make sure Cake has been installed.
$CakePath = Join-Path $ToolPath "Cake.$CakeVersion/Cake.exe"
if (!(Test-Path $CakePath)) {
Write-Host "Installing Cake..."
Invoke-Expression "&`"$NugetPath`" install Cake -Version $CakeVersion -OutputDirectory `"$ToolPath`"" | Out-Null;
if ($LASTEXITCODE -ne 0) {
Throw "An error occured while restoring Cake from NuGet."
}
}
###########################################################################
# RUN BUILD SCRIPT
###########################################################################
# Build the argument list.
$Arguments = @{
target=$Target;
configuration=$Configuration;
verbosity=$Verbosity;
dryrun=$WhatIf;
}.GetEnumerator() | %{"--{0}=`"{1}`"" -f $_.key, $_.value };
# Start Cake
Write-Host "Running build script..."
Invoke-Expression "& `"$CakePath`" `"$Script`" $Arguments $ScriptArgs"
exit $LASTEXITCODE

268
build/Program.cs Normal file
View File

@@ -0,0 +1,268 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using GlobExpressions;
using static Bullseye.Targets;
using static SimpleExec.Command;
const string Clean = "clean";
const string Restore = "restore";
const string Build = "build";
const string Test = "test";
const string Format = "format";
const string CheckFormat = "check-format";
const string Publish = "publish";
const string DetermineVersion = "determine-version";
const string UpdateVersion = "update-version";
const string PushToNuGet = "push-to-nuget";
Target(
Clean,
["**/bin", "**/obj"],
dir =>
{
IEnumerable<string> GetDirectories(string d)
{
return Glob.Directories(".", d);
}
void RemoveDirectory(string d)
{
if (Directory.Exists(d))
{
Console.WriteLine(d);
Directory.Delete(d, true);
}
}
foreach (var d in GetDirectories(dir))
{
RemoveDirectory(d);
}
}
);
Target(
Format,
() =>
{
Run("dotnet", "tool restore");
Run("dotnet", "csharpier format .");
}
);
Target(
CheckFormat,
() =>
{
Run("dotnet", "tool restore");
Run("dotnet", "csharpier check .");
}
);
Target(Restore, [CheckFormat], () => Run("dotnet", "restore"));
Target(
Build,
[Restore],
() =>
{
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release --no-restore");
}
);
Target(
Test,
[Build],
["net10.0", "net48"],
framework =>
{
IEnumerable<string> GetFiles(string d)
{
return Glob.Files(".", d);
}
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && framework == "net48")
{
return;
}
foreach (var file in GetFiles("**/*.Test.csproj"))
{
Run("dotnet", $"test {file} -c Release -f {framework} --no-restore --verbosity=normal");
}
}
);
Target(
Publish,
[Test],
() =>
{
Run("dotnet", "pack src/SharpCompress/SharpCompress.csproj -c Release -o artifacts/");
}
);
Target(
DetermineVersion,
async () =>
{
var (version, isPrerelease) = await GetVersion();
Console.WriteLine($"VERSION={version}");
Console.WriteLine($"PRERELEASE={isPrerelease.ToString().ToLower()}");
// Write to environment file for GitHub Actions
var githubOutput = Environment.GetEnvironmentVariable("GITHUB_OUTPUT");
if (!string.IsNullOrEmpty(githubOutput))
{
File.AppendAllText(githubOutput, $"version={version}\n");
File.AppendAllText(githubOutput, $"prerelease={isPrerelease.ToString().ToLower()}\n");
}
}
);
Target(
UpdateVersion,
async () =>
{
var version = Environment.GetEnvironmentVariable("VERSION");
if (string.IsNullOrEmpty(version))
{
var (detectedVersion, _) = await GetVersion();
version = detectedVersion;
}
Console.WriteLine($"Updating project file with version: {version}");
var projectPath = "src/SharpCompress/SharpCompress.csproj";
var content = File.ReadAllText(projectPath);
// Get base version (without prerelease suffix)
var baseVersion = version.Split('-')[0];
// Update VersionPrefix
content = Regex.Replace(
content,
@"<VersionPrefix>[^<]*</VersionPrefix>",
$"<VersionPrefix>{version}</VersionPrefix>"
);
// Update AssemblyVersion
content = Regex.Replace(
content,
@"<AssemblyVersion>[^<]*</AssemblyVersion>",
$"<AssemblyVersion>{baseVersion}</AssemblyVersion>"
);
// Update FileVersion
content = Regex.Replace(
content,
@"<FileVersion>[^<]*</FileVersion>",
$"<FileVersion>{baseVersion}</FileVersion>"
);
File.WriteAllText(projectPath, content);
Console.WriteLine($"Updated VersionPrefix to: {version}");
Console.WriteLine($"Updated AssemblyVersion and FileVersion to: {baseVersion}");
}
);
Target(
PushToNuGet,
() =>
{
var apiKey = Environment.GetEnvironmentVariable("NUGET_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
Console.WriteLine(
"NUGET_API_KEY environment variable is not set. Skipping NuGet push."
);
return;
}
var packages = Directory.GetFiles("artifacts", "*.nupkg");
if (packages.Length == 0)
{
Console.WriteLine("No packages found in artifacts directory.");
return;
}
foreach (var package in packages)
{
Console.WriteLine($"Pushing {package} to NuGet.org");
try
{
// Note: API key is passed via command line argument which is standard practice for dotnet nuget push
// The key is already in an environment variable and not displayed in normal output
Run(
"dotnet",
$"nuget push \"{package}\" --api-key {apiKey} --source https://api.nuget.org/v3/index.json --skip-duplicate"
);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to push {package}: {ex.Message}");
throw;
}
}
}
);
Target("default", [Publish], () => Console.WriteLine("Done!"));
await RunTargetsAndExitAsync(args);
static async Task<(string version, bool isPrerelease)> GetVersion()
{
// Check if current commit has a version tag
var currentTag = (await GetGitOutput("tag", "--points-at HEAD"))
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault(tag => Regex.IsMatch(tag.Trim(), @"^\d+\.\d+\.\d+$"));
if (!string.IsNullOrEmpty(currentTag))
{
// Tagged release - use the tag as version
var version = currentTag.Trim();
Console.WriteLine($"Building tagged release version: {version}");
return (version, false);
}
else
{
// Not tagged - create prerelease version based on next minor version
var allTags = (await GetGitOutput("tag", "--list"))
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
.Where(tag => Regex.IsMatch(tag.Trim(), @"^\d+\.\d+\.\d+$"))
.Select(tag => tag.Trim())
.ToList();
var lastTag = allTags.OrderBy(tag => Version.Parse(tag)).LastOrDefault() ?? "0.0.0";
var lastVersion = Version.Parse(lastTag);
// Increment minor version for next release
var nextVersion = new Version(lastVersion.Major, lastVersion.Minor + 1, 0);
// Use commit count since the last version tag if available; otherwise, fall back to total count
var revListArgs = allTags.Any() ? $"--count {lastTag}..HEAD" : "--count HEAD";
var commitCount = (await GetGitOutput("rev-list", revListArgs)).Trim();
var version = $"{nextVersion}-beta.{commitCount}";
Console.WriteLine($"Building prerelease version: {version}");
return (version, true);
}
}
static async Task<string> GetGitOutput(string command, string args)
{
try
{
// Use SimpleExec's Read to execute git commands in a cross-platform way
var (output, _) = await ReadAsync("git", $"{command} {args}");
return output;
}
catch (Exception ex)
{
throw new Exception($"Git command failed: git {command} {args}\n{ex.Message}", ex);
}
}

11
build/build.csproj Normal file
View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bullseye" />
<PackageReference Include="Glob" />
<PackageReference Include="SimpleExec" />
</ItemGroup>
</Project>

65
build/packages.lock.json Normal file
View File

@@ -0,0 +1,65 @@
{
"version": 2,
"dependencies": {
"net10.0": {
"Bullseye": {
"type": "Direct",
"requested": "[6.1.0, )",
"resolved": "6.1.0",
"contentHash": "fltnAJDe0BEX5eymXGUq+il2rSUA0pHqUonNDRH2TrvRu8SkU17mYG0IVpdmG2ibtfhdjNrv4CuTCxHOwcozCA=="
},
"Glob": {
"type": "Direct",
"requested": "[1.1.9, )",
"resolved": "1.1.9",
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Microsoft.VisualStudio.Threading.Analyzers": {
"type": "Direct",
"requested": "[17.14.15, )",
"resolved": "17.14.15",
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
},
"SimpleExec": {
"type": "Direct",
"requested": "[13.0.0, )",
"resolved": "13.0.0",
"contentHash": "zcCR1pupa1wI1VqBULRiQKeHKKZOuJhi/K+4V5oO+rHJZlaOD53ViFo1c3PavDoMAfSn/FAXGAWpPoF57rwhYg=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
}
}
}

512
docs/API.md Normal file
View File

@@ -0,0 +1,512 @@
# API Quick Reference
Quick reference for commonly used SharpCompress APIs.
## Factory Methods
### Opening Archives
```csharp
// Auto-detect format
using (var reader = ReaderFactory.Open(stream))
{
// Works with Zip, Tar, GZip, Rar, 7Zip, etc.
}
// Specific format - Archive API
using (var archive = ZipArchive.Open("file.zip"))
using (var archive = TarArchive.Open("file.tar"))
using (var archive = RarArchive.Open("file.rar"))
using (var archive = SevenZipArchive.Open("file.7z"))
using (var archive = GZipArchive.Open("file.gz"))
// With options
var options = new ReaderOptions
{
Password = "password",
LeaveStreamOpen = true,
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("encrypted.zip", options))
```
### Creating Archives
```csharp
// Writer Factory
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write entries
}
// Specific writer
using (var archive = ZipArchive.Create())
using (var archive = TarArchive.Create())
using (var archive = GZipArchive.Create())
// With options
var options = new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = false
};
using (var archive = ZipArchive.Create())
{
archive.SaveTo("output.zip", options);
}
```
---
## Archive API Methods
### Reading/Extracting
```csharp
using (var archive = ZipArchive.Open("file.zip"))
{
// Get all entries
IEnumerable<IArchiveEntry> entries = archive.Entries;
// Find specific entry
var entry = archive.Entries.FirstOrDefault(e => e.Key == "file.txt");
// Extract all
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
// Extract single entry
var entry = archive.Entries.First();
entry.WriteToFile(@"C:\output\file.txt");
entry.WriteToFile(@"C:\output\file.txt", new ExtractionOptions { Overwrite = true });
// Get entry stream
using (var stream = entry.OpenEntryStream())
{
stream.CopyTo(outputStream);
}
}
// Async extraction (requires IAsyncArchive)
using (var asyncArchive = await ZipArchive.OpenAsync("file.zip"))
{
await asyncArchive.WriteToDirectoryAsync(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true },
cancellationToken: cancellationToken
);
}
using (var stream = await entry.OpenEntryStreamAsync(cancellationToken))
{
// ...
}
```
### Entry Properties
```csharp
foreach (var entry in archive.Entries)
{
string name = entry.Key; // Entry name/path
long size = entry.Size; // Uncompressed size
long compressedSize = entry.CompressedSize;
bool isDir = entry.IsDirectory;
DateTime? modTime = entry.LastModifiedTime;
CompressionType compression = entry.CompressionType;
}
```
### Creating Archives
```csharp
using (var archive = ZipArchive.Create())
{
// Add file
archive.AddEntry("file.txt", @"C:\source\file.txt");
// Add multiple files
archive.AddAllFromDirectory(@"C:\source");
archive.AddAllFromDirectory(@"C:\source", "*.txt"); // Pattern
// Save to file
archive.SaveTo("output.zip", CompressionType.Deflate);
// Save to stream
archive.SaveTo(outputStream, new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = true
});
}
```
---
## Reader API Methods
### Forward-Only Reading
```csharp
using (var stream = File.OpenRead("file.zip"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
IArchiveEntry entry = reader.Entry;
if (!entry.IsDirectory)
{
// Extract entry
reader.WriteEntryToDirectory(@"C:\output");
reader.WriteEntryToFile(@"C:\output\file.txt");
// Or get stream
using (var entryStream = reader.OpenEntryStream())
{
entryStream.CopyTo(outputStream);
}
}
}
}
// Async variants (use OpenAsync to get IAsyncReader)
using (var stream = File.OpenRead("file.zip"))
using (var reader = await ReaderFactory.OpenAsync(stream))
{
while (await reader.MoveToNextEntryAsync())
{
await reader.WriteEntryToFileAsync(
@"C:\output\" + reader.Entry.Key,
cancellationToken: cancellationToken
);
}
// Async extraction of all entries
await reader.WriteAllToDirectoryAsync(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true },
cancellationToken
);
}
```
---
## Writer API Methods
### Creating Archives (Streaming)
```csharp
using (var stream = File.Create("output.zip"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write single file
using (var fileStream = File.OpenRead("source.txt"))
{
writer.Write("entry.txt", fileStream, DateTime.Now);
}
// Write directory
writer.WriteAll("C:\\source", "*", SearchOption.AllDirectories);
writer.WriteAll("C:\\source", "*.txt", SearchOption.TopDirectoryOnly);
// Async variants
using (var fileStream = File.OpenRead("source.txt"))
{
await writer.WriteAsync("entry.txt", fileStream, DateTime.Now, cancellationToken);
}
await writer.WriteAllAsync("C:\\source", "*", SearchOption.AllDirectories, cancellationToken);
}
```
---
## Common Options
### ReaderOptions
```csharp
var options = new ReaderOptions
{
Password = "password", // For encrypted archives
LeaveStreamOpen = true, // Don't close wrapped stream
ArchiveEncoding = new ArchiveEncoding // Custom character encoding
{
Default = Encoding.GetEncoding(932)
}
};
using (var archive = ZipArchive.Open("file.zip", options))
{
// ...
}
```
### WriterOptions
```csharp
var options = new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9, // 0-9 for Deflate
LeaveStreamOpen = true, // Don't close stream
};
archive.SaveTo("output.zip", options);
```
### ExtractionOptions
```csharp
var options = new ExtractionOptions
{
ExtractFullPath = true, // Recreate directory structure
Overwrite = true, // Overwrite existing files
PreserveFileTime = true // Keep original timestamps
};
archive.WriteToDirectory(@"C:\output", options);
```
---
## Compression Types
### Available Compressions
```csharp
// For creating archives
CompressionType.None // No compression (store)
CompressionType.Deflate // DEFLATE (default for ZIP/GZip)
CompressionType.Deflate64 // Deflate64
CompressionType.BZip2 // BZip2
CompressionType.LZMA // LZMA (for 7Zip, LZip, XZ)
CompressionType.PPMd // PPMd (for ZIP)
CompressionType.Rar // RAR compression (read-only)
CompressionType.ZStandard // ZStandard
ArchiveType.Arc
ArchiveType.Arj
ArchiveType.Ace
// For Tar archives with compression
// Use WriterFactory to create compressed tar archives
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.GZip)) // Tar.GZip
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.BZip2)) // Tar.BZip2
```
### Archive Types
```csharp
ArchiveType.Zip
ArchiveType.Tar
ArchiveType.GZip
ArchiveType.BZip2
ArchiveType.Rar
ArchiveType.SevenZip
ArchiveType.XZ
ArchiveType.ZStandard
```
---
## Patterns & Examples
### Extract with Error Handling
```csharp
try
{
using (var archive = ZipArchive.Open("archive.zip",
new ReaderOptions { Password = "password" }))
{
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
}
catch (PasswordRequiredException)
{
Console.WriteLine("Password required");
}
catch (InvalidArchiveException)
{
Console.WriteLine("Archive is invalid");
}
catch (SharpCompressException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
```
### Extract with Progress
```csharp
var progress = new Progress<ProgressReport>(report =>
{
Console.WriteLine($"Extracting {report.EntryPath}: {report.PercentComplete}%");
});
var options = new ReaderOptions { Progress = progress };
using (var archive = ZipArchive.Open("archive.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
```
### Async Extract with Cancellation
```csharp
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(5));
try
{
using (var archive = await ZipArchive.OpenAsync("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true },
cancellationToken: cts.Token
);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Extraction cancelled");
}
```
### Create with Custom Compression
```csharp
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(@"D:\source");
// Fastest
archive.SaveTo("fast.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 1
});
// Balanced (default)
archive.SaveTo("normal.zip", CompressionType.Deflate);
// Best compression
archive.SaveTo("best.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9
});
}
```
### Stream Processing (No File I/O)
```csharp
using (var outputStream = new MemoryStream())
using (var archive = ZipArchive.Create())
{
// Add content from memory
using (var contentStream = new MemoryStream(Encoding.UTF8.GetBytes("Hello")))
{
archive.AddEntry("file.txt", contentStream);
}
// Save to memory
archive.SaveTo(outputStream, CompressionType.Deflate);
// Get bytes
byte[] archiveBytes = outputStream.ToArray();
}
```
### Extract Specific Files
```csharp
using (var archive = ZipArchive.Open("archive.zip"))
{
var filesToExtract = new[] { "file1.txt", "file2.txt" };
foreach (var entry in archive.Entries.Where(e => filesToExtract.Contains(e.Key)))
{
entry.WriteToFile(@"C:\output\" + entry.Key);
}
}
```
### List Archive Contents
```csharp
using (var archive = ZipArchive.Open("archive.zip"))
{
foreach (var entry in archive.Entries)
{
if (entry.IsDirectory)
Console.WriteLine($"[DIR] {entry.Key}");
else
Console.WriteLine($"[FILE] {entry.Key} ({entry.Size} bytes)");
}
}
```
---
## Common Mistakes
### ✗ Wrong - Stream not disposed
```csharp
var stream = File.OpenRead("archive.zip");
var archive = ZipArchive.Open(stream);
archive.WriteToDirectory(@"C:\output");
// stream not disposed - leaked resource
```
### ✓ Correct - Using blocks
```csharp
using (var stream = File.OpenRead("archive.zip"))
using (var archive = ZipArchive.Open(stream))
{
archive.WriteToDirectory(@"C:\output");
}
// Both properly disposed
```
### ✗ Wrong - Mixing API styles
```csharp
// Loading entire archive then iterating
using (var archive = ZipArchive.Open("large.zip"))
{
var entries = archive.Entries.ToList(); // Loads all in memory
foreach (var e in entries)
{
e.WriteToFile(...); // Then extracts each
}
}
```
### ✓ Correct - Use Reader for large files
```csharp
// Streaming iteration
using (var stream = File.OpenRead("large.zip"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
```
---
## Related Documentation
- [USAGE.md](USAGE.md) - Complete code examples
- [FORMATS.md](FORMATS.md) - Supported formats
- [PERFORMANCE.md](PERFORMANCE.md) - API selection guide

659
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,659 @@
# SharpCompress Architecture Guide
This guide explains the internal architecture and design patterns of SharpCompress for contributors.
## Overview
SharpCompress is organized into three main layers:
```
┌─────────────────────────────────────────┐
│ User-Facing APIs (Top Layer) │
│ Archive, Reader, Writer Factories │
├─────────────────────────────────────────┤
│ Format-Specific Implementations │
│ ZipArchive, TarReader, GZipWriter, │
│ RarArchive, SevenZipArchive, etc. │
├─────────────────────────────────────────┤
│ Compression & Crypto (Bottom Layer) │
│ Deflate, LZMA, BZip2, AES, CRC32 │
└─────────────────────────────────────────┘
```
---
## Directory Structure
### `src/SharpCompress/`
#### `Archives/` - Archive Implementations
Contains `IArchive` implementations for seekable, random-access APIs.
**Key Files:**
- `AbstractArchive.cs` - Base class for all archives
- `IArchive.cs` - Archive interface definition
- `ArchiveFactory.cs` - Factory for opening archives
- Format-specific: `ZipArchive.cs`, `TarArchive.cs`, `RarArchive.cs`, `SevenZipArchive.cs`, `GZipArchive.cs`
**Use Archive API when:**
- Stream is seekable (file, memory)
- Need random access to entries
- Archive fits in memory
- Simplicity is important
#### `Readers/` - Reader Implementations
Contains `IReader` implementations for forward-only, non-seekable APIs.
**Key Files:**
- `AbstractReader.cs` - Base reader class
- `IReader.cs` - Reader interface
- `ReaderFactory.cs` - Auto-detection factory
- `ReaderOptions.cs` - Configuration for readers
- Format-specific: `ZipReader.cs`, `TarReader.cs`, `GZipReader.cs`, `RarReader.cs`, etc.
**Use Reader API when:**
- Stream is non-seekable (network, pipe, compressed)
- Processing large files
- Memory is limited
- Forward-only processing is acceptable
#### `Writers/` - Writer Implementations
Contains `IWriter` implementations for forward-only writing.
**Key Files:**
- `AbstractWriter.cs` - Base writer class
- `IWriter.cs` - Writer interface
- `WriterFactory.cs` - Factory for creating writers
- `WriterOptions.cs` - Configuration for writers
- Format-specific: `ZipWriter.cs`, `TarWriter.cs`, `GZipWriter.cs`
#### `Factories/` - Format Detection
Factory classes for auto-detecting archive format and creating appropriate readers/writers.
**Key Files:**
- `Factory.cs` - Base factory class
- `IFactory.cs` - Factory interface
- Format-specific: `ZipFactory.cs`, `TarFactory.cs`, `RarFactory.cs`, etc.
**How It Works:**
1. `ReaderFactory.Open(stream)` probes stream signatures
2. Identifies format by magic bytes
3. Creates appropriate reader instance
4. Returns generic `IReader` interface
#### `Common/` - Shared Types
Common types, options, and enumerations used across formats.
**Key Files:**
- `IEntry.cs` - Entry interface (file within archive)
- `Entry.cs` - Entry implementation
- `ArchiveType.cs` - Enum for archive formats
- `CompressionType.cs` - Enum for compression methods
- `ArchiveEncoding.cs` - Character encoding configuration
- `ExtractionOptions.cs` - Extraction configuration
- Format-specific headers: `Zip/Headers/`, `Tar/Headers/`, `Rar/Headers/`, etc.
#### `Compressors/` - Compression Algorithms
Low-level compression streams implementing specific algorithms.
**Algorithms:**
- `Deflate/` - DEFLATE compression (Zip default)
- `BZip2/` - BZip2 compression
- `LZMA/` - LZMA compression (7Zip, XZ, LZip)
- `PPMd/` - Prediction by Partial Matching (Zip, 7Zip)
- `ZStandard/` - ZStandard compression (decompression only)
- `Xz/` - XZ format (decompression only)
- `Rar/` - RAR-specific unpacking
- `Arj/`, `Arc/`, `Ace/` - Legacy format decompression
- `Filters/` - BCJ/BCJ2 filters for executable compression
**Each Compressor:**
- Implements a `Stream` subclass
- Provides both compression and decompression
- Some are read-only (decompression only)
#### `Crypto/` - Encryption & Hashing
Cryptographic functions and stream wrappers.
**Key Files:**
- `Crc32Stream.cs` - CRC32 calculation wrapper
- `BlockTransformer.cs` - Block cipher transformations
- AES, PKWare, WinZip encryption implementations
#### `IO/` - Stream Utilities
Stream wrappers and utilities.
**Key Classes:**
- `SharpCompressStream` - Base stream class
- `ProgressReportingStream` - Progress tracking wrapper
- `MarkingBinaryReader` - Binary reader with position marks
- `BufferedSubStream` - Buffered read-only substream
- `ReadOnlySubStream` - Read-only view of parent stream
- `NonDisposingStream` - Prevents wrapped stream disposal
---
## Design Patterns
### 1. Factory Pattern
**Purpose:** Auto-detect format and create appropriate reader/writer.
**Example:**
```csharp
// User calls factory
using (var reader = ReaderFactory.Open(stream)) // Returns IReader
{
while (reader.MoveToNextEntry())
{
// Process entry
}
}
// Behind the scenes:
// 1. Factory.Open() probes stream signatures
// 2. Detects format (Zip, Tar, Rar, etc.)
// 3. Creates appropriate reader (ZipReader, TarReader, etc.)
// 4. Returns as generic IReader interface
```
**Files:**
- `src/SharpCompress/Factories/ReaderFactory.cs`
- `src/SharpCompress/Factories/WriterFactory.cs`
- `src/SharpCompress/Factories/ArchiveFactory.cs`
### 2. Strategy Pattern
**Purpose:** Encapsulate compression algorithms as swappable strategies.
**Example:**
```csharp
// Different compression strategies
CompressionType.Deflate // DEFLATE
CompressionType.BZip2 // BZip2
CompressionType.LZMA // LZMA
CompressionType.PPMd // PPMd
// Writer uses strategy pattern
var archive = ZipArchive.Create();
archive.SaveTo("output.zip", CompressionType.Deflate); // Use Deflate
archive.SaveTo("output.bz2", CompressionType.BZip2); // Use BZip2
```
**Files:**
- `src/SharpCompress/Compressors/` - Strategy implementations
### 3. Decorator Pattern
**Purpose:** Wrap streams with additional functionality.
**Example:**
```csharp
// Progress reporting decorator
var progressStream = new ProgressReportingStream(baseStream, progressReporter);
progressStream.Read(buffer, 0, buffer.Length); // Reports progress
// Non-disposing decorator
var nonDisposingStream = new NonDisposingStream(baseStream);
using (var compressor = new DeflateStream(nonDisposingStream))
{
// baseStream won't be disposed when compressor is disposed
}
```
**Files:**
- `src/SharpCompress/IO/ProgressReportingStream.cs`
- `src/SharpCompress/IO/NonDisposingStream.cs`
### 4. Template Method Pattern
**Purpose:** Define algorithm skeleton in base class, let subclasses fill details.
**Example:**
```csharp
// AbstractArchive defines common archive operations
public abstract class AbstractArchive : IArchive
{
// Template methods
public virtual void WriteToDirectory(string destinationDirectory, ExtractionOptions options)
{
// Common extraction logic
foreach (var entry in Entries)
{
// Call subclass method
entry.WriteToFile(destinationPath, options);
}
}
// Subclasses override format-specific details
protected abstract Entry CreateEntry(EntryData data);
}
```
**Files:**
- `src/SharpCompress/Archives/AbstractArchive.cs`
- `src/SharpCompress/Readers/AbstractReader.cs`
### 5. Iterator Pattern
**Purpose:** Provide sequential access to entries.
**Example:**
```csharp
// Archive API - provides collection
IEnumerable<IEntry> entries = archive.Entries;
foreach (var entry in entries)
{
// Random access - entries already in memory
}
// Reader API - provides iterator
IReader reader = ReaderFactory.Open(stream);
while (reader.MoveToNextEntry())
{
// Forward-only iteration - one entry at a time
var entry = reader.Entry;
}
```
---
## Key Interfaces
### IArchive - Random Access API
```csharp
public interface IArchive : IDisposable
{
IEnumerable<IEntry> Entries { get; }
void WriteToDirectory(string destinationDirectory,
ExtractionOptions options = null);
IEntry FirstOrDefault(Func<IEntry, bool> predicate);
// ... format-specific methods
}
```
**Implementations:** `ZipArchive`, `TarArchive`, `RarArchive`, `SevenZipArchive`, `GZipArchive`
### IReader - Forward-Only API
```csharp
public interface IReader : IDisposable
{
IEntry Entry { get; }
bool MoveToNextEntry();
void WriteEntryToDirectory(string destinationDirectory,
ExtractionOptions options = null);
Stream OpenEntryStream();
// ... async variants
}
```
**Implementations:** `ZipReader`, `TarReader`, `RarReader`, `GZipReader`, etc.
### IWriter - Writing API
```csharp
public interface IWriter : IDisposable
{
void Write(string entryPath, Stream source,
DateTime? modificationTime = null);
void WriteAll(string sourceDirectory, string searchPattern,
SearchOption searchOption);
// ... async variants
}
```
**Implementations:** `ZipWriter`, `TarWriter`, `GZipWriter`
### IEntry - Archive Entry
```csharp
public interface IEntry
{
string Key { get; }
uint Size { get; }
uint CompressedSize { get; }
bool IsDirectory { get; }
DateTime? LastModifiedTime { get; }
CompressionType CompressionType { get; }
void WriteToFile(string fullPath, ExtractionOptions options = null);
void WriteToStream(Stream destinationStream);
Stream OpenEntryStream();
// ... async variants
}
```
---
## Adding Support for a New Format
### Step 1: Understand the Format
- Research format specification
- Understand compression/encryption used
- Study existing similar formats in codebase
### Step 2: Create Format Structure Classes
**Create:** `src/SharpCompress/Common/NewFormat/`
```csharp
// Headers and data structures
public class NewFormatHeader
{
public uint Magic { get; set; }
public ushort Version { get; set; }
// ... other fields
public static NewFormatHeader Read(BinaryReader reader)
{
// Deserialize from binary
}
}
public class NewFormatEntry
{
public string FileName { get; set; }
public uint CompressedSize { get; set; }
public uint UncompressedSize { get; set; }
// ... other fields
}
```
### Step 3: Create Archive Implementation
**Create:** `src/SharpCompress/Archives/NewFormat/NewFormatArchive.cs`
```csharp
public class NewFormatArchive : AbstractArchive
{
private NewFormatHeader _header;
private List<NewFormatEntry> _entries;
public static NewFormatArchive Open(Stream stream)
{
var archive = new NewFormatArchive();
archive._header = NewFormatHeader.Read(stream);
archive.LoadEntries(stream);
return archive;
}
public override IEnumerable<IEntry> Entries => _entries.Select(e => new Entry(e));
protected override Stream OpenEntryStream(Entry entry)
{
// Return decompressed stream for entry
}
// ... other abstract method implementations
}
```
### Step 4: Create Reader Implementation
**Create:** `src/SharpCompress/Readers/NewFormat/NewFormatReader.cs`
```csharp
public class NewFormatReader : AbstractReader
{
private NewFormatHeader _header;
private BinaryReader _reader;
public NewFormatReader(Stream stream)
{
_reader = new BinaryReader(stream);
_header = NewFormatHeader.Read(_reader);
}
public override bool MoveToNextEntry()
{
// Read next entry header
if (!_reader.BaseStream.CanRead) return false;
var entryData = NewFormatEntry.Read(_reader);
// ... set this.Entry
return entryData != null;
}
// ... other abstract method implementations
}
```
### Step 5: Create Factory
**Create:** `src/SharpCompress/Factories/NewFormatFactory.cs`
```csharp
public class NewFormatFactory : Factory, IArchiveFactory, IReaderFactory
{
// Archive format magic bytes (signature)
private static readonly byte[] NewFormatSignature = new byte[] { 0x4E, 0x46 }; // "NF"
public static NewFormatFactory Instance { get; } = new();
public IArchive CreateArchive(Stream stream)
=> NewFormatArchive.Open(stream);
public IReader CreateReader(Stream stream, ReaderOptions options)
=> new NewFormatReader(stream) { Options = options };
public bool Matches(Stream stream, ReadOnlySpan<byte> signature)
=> signature.StartsWith(NewFormatSignature);
}
```
### Step 6: Register Factory
**Update:** `src/SharpCompress/Factories/ArchiveFactory.cs`
```csharp
private static readonly IFactory[] Factories =
{
ZipFactory.Instance,
TarFactory.Instance,
RarFactory.Instance,
SevenZipFactory.Instance,
GZipFactory.Instance,
NewFormatFactory.Instance, // Add here
// ... other factories
};
```
### Step 7: Add Tests
**Create:** `tests/SharpCompress.Test/NewFormat/NewFormatTests.cs`
```csharp
public class NewFormatTests : TestBase
{
[Fact]
public void NewFormat_Extracts_Successfully()
{
var archivePath = Path.Combine(TEST_ARCHIVES_PATH, "archive.newformat");
using (var archive = NewFormatArchive.Open(archivePath))
{
archive.WriteToDirectory(SCRATCH_FILES_PATH);
// Assert extraction
}
}
[Fact]
public void NewFormat_Reader_Works()
{
var archivePath = Path.Combine(TEST_ARCHIVES_PATH, "archive.newformat");
using (var stream = File.OpenRead(archivePath))
using (var reader = new NewFormatReader(stream))
{
Assert.True(reader.MoveToNextEntry());
Assert.NotNull(reader.Entry);
}
}
}
```
### Step 8: Add Test Archives
Place test files in `tests/TestArchives/Archives/NewFormat/` directory.
### Step 9: Document
Update `docs/FORMATS.md` with format support information.
---
## Compression Algorithm Implementation
### Creating a New Compression Stream
**Example:** Creating `CustomStream` for a custom compression algorithm
```csharp
public class CustomStream : Stream
{
private readonly Stream _baseStream;
private readonly bool _leaveOpen;
public CustomStream(Stream baseStream, bool leaveOpen = false)
{
_baseStream = baseStream;
_leaveOpen = leaveOpen;
}
public override int Read(byte[] buffer, int offset, int count)
{
// Decompress data from _baseStream into buffer
// Return number of decompressed bytes
}
public override void Write(byte[] buffer, int offset, int count)
{
// Compress data from buffer into _baseStream
}
protected override void Dispose(bool disposing)
{
if (disposing && !_leaveOpen)
{
_baseStream?.Dispose();
}
base.Dispose(disposing);
}
}
```
---
## Stream Handling Best Practices
### Disposal Pattern
```csharp
// Correct: Nested using blocks
using (var fileStream = File.OpenRead("archive.zip"))
using (var archive = ZipArchive.Open(fileStream))
{
archive.WriteToDirectory(@"C:\output");
}
// Both archive and fileStream properly disposed
// Correct: Using with options
var options = new ReaderOptions { LeaveStreamOpen = true };
var stream = File.OpenRead("archive.zip");
using (var archive = ZipArchive.Open(stream, options))
{
archive.WriteToDirectory(@"C:\output");
}
stream.Dispose(); // Manually dispose if LeaveStreamOpen = true
```
### NonDisposingStream Wrapper
```csharp
// Prevent unwanted stream closure
var baseStream = File.OpenRead("data.bin");
var nonDisposing = new NonDisposingStream(baseStream);
using (var compressor = new DeflateStream(nonDisposing))
{
// Compressor won't close baseStream when disposed
}
// baseStream still usable
baseStream.Position = 0; // Works
baseStream.Dispose(); // Manual disposal
```
---
## Performance Considerations
### Memory Efficiency
1. **Avoid loading entire archive in memory** - Use Reader API for large files
2. **Process entries sequentially** - Especially for solid archives
3. **Use appropriate buffer sizes** - Larger buffers for network I/O
4. **Dispose streams promptly** - Free resources when done
### Algorithm Selection
1. **Archive API** - Fast for small archives with random access
2. **Reader API** - Efficient for large files or streaming
3. **Solid archives** - Sequential extraction much faster
4. **Compression levels** - Trade-off between speed and size
---
## Testing Guidelines
### Test Coverage
1. **Happy path** - Normal extraction works
2. **Edge cases** - Empty archives, single file, many files
3. **Corrupted data** - Handle gracefully
4. **Error cases** - Missing passwords, unsupported compression
5. **Async operations** - Both sync and async code paths
### Test Archives
- Use `tests/TestArchives/` for test data
- Create format-specific subdirectories
- Include encrypted, corrupted, and edge case archives
- Don't recreate existing archives
### Test Patterns
```csharp
[Fact]
public void Archive_Extraction_Works()
{
// Arrange
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "test.zip");
// Act
using (var archive = ZipArchive.Open(testArchive))
{
archive.WriteToDirectory(SCRATCH_FILES_PATH);
}
// Assert
Assert.True(File.Exists(Path.Combine(SCRATCH_FILES_PATH, "file.txt")));
}
```
---
## Related Documentation
- [AGENTS.md](../AGENTS.md) - Development guidelines
- [FORMATS.md](FORMATS.md) - Supported formats

610
docs/ENCODING.md Normal file
View File

@@ -0,0 +1,610 @@
# SharpCompress Character Encoding Guide
This guide explains how SharpCompress handles character encoding for archive entries (filenames, comments, etc.).
## Overview
Most archive formats store filenames and metadata as bytes. SharpCompress must convert these bytes to strings using the appropriate character encoding.
**Common Problem:** Archives created on systems with non-UTF8 encodings (especially Japanese, Chinese systems) appear with corrupted filenames when extracted on systems that assume UTF8.
---
## ArchiveEncoding Class
### Basic Usage
```csharp
using SharpCompress.Common;
using SharpCompress.Readers;
// Configure encoding before opening archive
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding(932) // cp932 for Japanese
}
};
using (var archive = ZipArchive.Open("japanese.zip", options))
{
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry.Key); // Now shows correct characters
}
}
```
### ArchiveEncoding Properties
| Property | Purpose |
|----------|---------|
| `Default` | Default encoding for filenames (fallback) |
| `CustomDecoder` | Custom decoding function for special cases |
### Setting for Different APIs
**Archive API:**
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("file.zip", options))
{
// Use archive with correct encoding
}
```
**Reader API:**
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var stream = File.OpenRead("file.zip"))
using (var reader = ReaderFactory.Open(stream, options))
{
while (reader.MoveToNextEntry())
{
// Filenames decoded correctly
}
}
```
---
## Common Encodings
### Asian Encodings
#### cp932 (Japanese)
```csharp
// Windows-31J, Shift-JIS variant used on Japanese Windows
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding(932)
}
};
using (var archive = ZipArchive.Open("japanese.zip", options))
{
// Correctly decodes Japanese filenames
}
```
**When to use:**
- Archives from Japanese Windows systems
- Files with Japanese characters in names
#### gb2312 (Simplified Chinese)
```csharp
// Simplified Chinese
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("gb2312")
}
};
```
#### gbk (Extended Simplified Chinese)
```csharp
// Extended Simplified Chinese (more characters than gb2312)
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("gbk")
}
};
```
#### big5 (Traditional Chinese)
```csharp
// Traditional Chinese (Taiwan, Hong Kong)
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("big5")
}
};
```
#### euc-jp (Japanese, Unix)
```csharp
// Extended Unix Code for Japanese
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("eucjp")
}
};
```
#### euc-kr (Korean)
```csharp
// Extended Unix Code for Korean
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("euc-kr")
}
};
```
### Western European Encodings
#### iso-8859-1 (Latin-1)
```csharp
// Western European (includes accented characters)
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("iso-8859-1")
}
};
```
**When to use:**
- Archives from French, German, Spanish systems
- Files with accented characters (é, ñ, ü, etc.)
#### cp1252 (Windows-1252)
```csharp
// Windows Western European
// Very similar to iso-8859-1 but with additional printable characters
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("cp1252")
}
};
```
**When to use:**
- Archives from older Western European Windows systems
- Files with smart quotes and other Windows-specific characters
#### iso-8859-15 (Latin-9)
```csharp
// Western European with Euro symbol support
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("iso-8859-15")
}
};
```
### Cyrillic Encodings
#### cp1251 (Windows Cyrillic)
```csharp
// Russian, Serbian, Bulgarian, etc.
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("cp1251")
}
};
```
#### koi8-r (KOI8 Russian)
```csharp
// Russian (Unix standard)
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("koi8-r")
}
};
```
### UTF Encodings (Modern)
#### UTF-8 (Default)
```csharp
// Modern standard - usually correct for new archives
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.UTF8
}
};
```
#### UTF-16
```csharp
// Unicode - rarely used in archives
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.Unicode
}
};
```
---
## Encoding Auto-Detection
SharpCompress attempts to auto-detect encoding, but this isn't always reliable:
```csharp
// Auto-detection (default)
using (var archive = ZipArchive.Open("file.zip")) // Uses UTF8 by default
{
// May show corrupted characters if archive uses different encoding
}
// Explicit encoding (more reliable)
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("file.zip", options))
{
// Correct characters displayed
}
```
### When Manual Override is Needed
| Situation | Solution |
|-----------|----------|
| Archive shows corrupted characters | Specify the encoding explicitly |
| Archives from specific region | Use that region's encoding |
| Mixed encodings in archive | Use CustomDecoder |
| Testing with international files | Try different encodings |
---
## Custom Decoder
For complex scenarios where a single encoding isn't sufficient:
### Basic Custom Decoder
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
CustomDecoder = (data, offset, length) =>
{
// Custom decoding logic
var bytes = new byte[length];
Array.Copy(data, offset, bytes, 0, length);
// Try UTF8 first
try
{
return Encoding.UTF8.GetString(bytes);
}
catch
{
// Fallback to cp932 if UTF8 fails
return Encoding.GetEncoding(932).GetString(bytes);
}
}
}
};
using (var archive = ZipArchive.Open("mixed.zip", options))
{
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry.Key); // Uses custom decoder
}
}
```
### Advanced: Detect Encoding by Content
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
CustomDecoder = DetectAndDecode
}
};
private static string DetectAndDecode(byte[] data, int offset, int length)
{
var bytes = new byte[length];
Array.Copy(data, offset, bytes, 0, length);
// Try UTF8 (most modern archives)
try
{
var str = Encoding.UTF8.GetString(bytes);
// Verify it decoded correctly (no replacement characters)
if (!str.Contains('\uFFFD'))
return str;
}
catch { }
// Try cp932 (Japanese)
try
{
var str = Encoding.GetEncoding(932).GetString(bytes);
if (!str.Contains('\uFFFD'))
return str;
}
catch { }
// Fallback to iso-8859-1 (always succeeds)
return Encoding.GetEncoding("iso-8859-1").GetString(bytes);
}
```
---
## Code Examples
### Extract Archive with Japanese Filenames
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding(932) // cp932
}
};
using (var archive = ZipArchive.Open("japanese_files.zip", options))
{
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
// Files extracted with correct Japanese names
```
### Extract Archive with Western European Filenames
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("iso-8859-1")
}
};
using (var archive = ZipArchive.Open("french_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
// Accented characters (é, è, ê, etc.) display correctly
```
### Extract Archive with Chinese Filenames
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("gbk") // Simplified Chinese
}
};
using (var archive = ZipArchive.Open("chinese_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
```
### Extract Archive with Russian Filenames
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("cp1251") // Windows Cyrillic
}
};
using (var archive = ZipArchive.Open("russian_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
```
### Reader API with Encoding
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding(932)
}
};
using (var stream = File.OpenRead("japanese.zip"))
using (var reader = ReaderFactory.Open(stream, options))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Console.WriteLine(reader.Entry.Key); // Correct characters
reader.WriteEntryToDirectory(@"C:\output");
}
}
}
```
---
## Creating Archives with Correct Encoding
When creating archives, SharpCompress uses UTF8 by default (recommended):
```csharp
// Create with UTF8 (default, recommended)
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(@"D:\my_files");
archive.SaveTo("output.zip", CompressionType.Deflate);
// Archives created with UTF8 encoding
}
```
If you need to create archives for systems that expect specific encodings:
```csharp
// Note: SharpCompress Writer API uses UTF8 for encoding
// To create archives with other encodings, consider:
// 1. Let users on those systems create archives
// 2. Use system tools (7-Zip, WinRAR) with desired encoding
// 3. Post-process archives if absolutely necessary
// For now, recommend modern UTF8-based archives
```
---
## Troubleshooting Encoding Issues
### Filenames Show Question Marks (?)
```
✗ Wrong encoding detected
test文件.txt → test???.txt
```
**Solution:** Specify correct encoding explicitly
```csharp
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
Default = Encoding.GetEncoding("gbk") // Try different encodings
}
};
```
### Filenames Show Replacement Character (￿)
```
✗ Invalid bytes for selected encoding
café.txt → caf￿.txt
```
**Solution:**
1. Try a different encoding (see Common Encodings table)
2. Use CustomDecoder with fallback encoding
3. Archive might be corrupted
### Mixed Encodings in Single Archive
```csharp
// Use CustomDecoder to handle mixed encodings
var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding
{
CustomDecoder = (data, offset, length) =>
{
// Try multiple encodings in priority order
var bytes = new byte[length];
Array.Copy(data, offset, bytes, 0, length);
foreach (var encoding in new[]
{
Encoding.UTF8,
Encoding.GetEncoding(932),
Encoding.GetEncoding("iso-8859-1")
})
{
try
{
var str = encoding.GetString(bytes);
if (!str.Contains('\uFFFD'))
return str;
}
catch { }
}
// Final fallback
return Encoding.GetEncoding("iso-8859-1").GetString(bytes);
}
}
};
```
---
## Encoding Reference Table
| Encoding | Code | Use Case |
|----------|------|----------|
| UTF-8 | (default) | Modern archives, recommended |
| cp932 | 932 | Japanese Windows |
| gb2312 | "gb2312" | Simplified Chinese |
| gbk | "gbk" | Extended Simplified Chinese |
| big5 | "big5" | Traditional Chinese |
| iso-8859-1 | "iso-8859-1" | Western European |
| cp1252 | "cp1252" | Windows Western European |
| cp1251 | "cp1251" | Russian/Cyrillic |
| euc-jp | "euc-jp" | Japanese Unix |
| euc-kr | "euc-kr" | Korean |
---
## Best Practices
1. **Use UTF-8 for new archives** - Most modern systems support it
2. **Ask the archive creator** - When receiving archives with corrupted names
3. **Provide encoding options** - If your app handles user archives
4. **Document your assumption** - Tell users what encoding you're using
5. **Test with international files** - Before releasing production code
---
## Related Documentation
- [USAGE.md](USAGE.md#extract-zip-which-has-non-utf8-encoded-filenamycp932) - Usage examples

81
docs/FORMATS.md Normal file
View File

@@ -0,0 +1,81 @@
# Formats
## Accessing Archives
* Archive classes allow random access to a seekable stream.
* Reader classes allow forward-only reading on a stream.
* Writer classes allow forward-only Writing on a stream.
## Supported Format Table
| Archive Format | Compression Format(s) | Compress/Decompress | Archive API | Reader API | Writer API |
| ---------------------- | ------------------------------------------------- | ------------------- | --------------- | ---------- | ------------- |
| Ace | None | Decompress | N/A | AceReader | N/A |
| Arc | None, Packed, Squeezed, Crunched | Decompress | N/A | ArcReader | N/A |
| Arj | None | Decompress | N/A | ArjReader | N/A |
| Rar | Rar | Decompress | RarArchive | RarReader | N/A |
| Zip (2) | None, Shrink, Reduce, Implode, DEFLATE, Deflate64, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
| Tar | None | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.GZip | DEFLATE | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.BZip2 | BZip2 | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.Zstandard | ZStandard | Decompress | TarArchive | TarReader | N/A |
| Tar.LZip | LZMA | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.XZ | LZMA2 | Decompress | TarArchive | TarReader | TarWriter (3) |
| GZip (single file) | DEFLATE | Both | GZipArchive | GZipReader | GZipWriter |
| 7Zip (4) | LZMA, LZMA2, BZip2, PPMd, BCJ, BCJ2, Deflate | Decompress | SevenZipArchive | N/A | N/A |
1. SOLID Rars are only supported in the RarReader API.
2. Zip format supports pkware and WinzipAES encryption. However, encrypted LZMA is not supported. Zip64 reading/writing is supported but only with seekable streams as the Zip spec doesn't support Zip64 data in post data descriptors. Deflate64 is only supported for reading. See [Zip Format Notes](#zip-format-notes) for details on multi-volume archives and streaming behavior.
3. The Tar format requires a file size in the header. If no size is specified to the TarWriter and the stream is not seekable, then an exception will be thrown.
4. The 7Zip format doesn't allow for reading as a forward-only stream so 7Zip is only supported through the Archive API. See [7Zip Format Notes](#7zip-format-notes) for details on async extraction behavior.
5. LZip has no support for extra data like the file name or timestamp. There is a default filename used when looking at the entry Key on the archive.
### Zip Format Notes
- Multi-volume/split ZIP archives require ZipArchive (seekable streams) as ZipReader cannot seek across volume files.
- ZipReader processes entries from LocalEntry headers (which include directory entries ending with `/`) and intentionally skips DirectoryEntry headers from the central directory, as they are redundant in streaming mode - all entry data comes from LocalEntry headers which ZipReader has already processed.
### 7Zip Format Notes
- **Async Extraction Performance**: When using async extraction methods (e.g., `ExtractAllEntries()` with `MoveToNextEntryAsync()`), each file creates its own decompression stream to avoid state corruption in the LZMA decoder. This is less efficient than synchronous extraction, which can reuse a single decompression stream for multiple files in the same folder.
**Performance Impact**: For archives with many small files in the same compression folder, async extraction will be slower than synchronous extraction because it must:
1. Create a new LZMA decoder for each file
2. Skip through the decompressed data to reach each file's starting position
**Recommendation**: For best performance with 7Zip archives, use synchronous extraction methods (`MoveToNextEntry()` and `WriteEntryToDirectory()`) when possible. Use async methods only when you need to avoid blocking the thread (e.g., in UI applications or async-only contexts).
**Technical Details**: 7Zip archives group files into "folders" (compression units), where all files in a folder share one continuous LZMA-compressed stream. The LZMA decoder maintains internal state (dictionary window, decoder positions) that assumes sequential, non-interruptible processing. Async operations can yield control during awaits, which would corrupt this shared state. To avoid this, async extraction creates a fresh decoder stream for each file.
## Compression Streams
For those who want to directly compress/decompress bits. The single file formats are represented here as well. However, BZip2, LZip and XZ have no metadata (GZip has a little) so using them without something like a Tar file makes little sense.
| Compressor | Compress/Decompress |
| --------------- | ------------------- |
| BZip2Stream | Both |
| GZipStream | Both |
| DeflateStream | Both |
| Deflate64Stream | Decompress |
| LZMAStream | Both |
| PPMdStream | Both |
| ADCStream | Decompress |
| LZipStream | Both |
| XZStream | Decompress |
| ZStandardStream | Decompress |
## Archive Formats vs Compression
Sometimes the terminology gets mixed.
### Compression
DEFLATE, LZMA are pure compression algorithms
### Formats
Formats like Zip, 7Zip, Rar are archive formats only. They use other compression methods (e.g. DEFLATE, LZMA, etc.) or propriatory (e.g RAR)
### Overlap
GZip, BZip2 and LZip are single file archival formats. The overlap in the API happens because Tar uses the single file formats as "compression" methods and the API tries to hide this a bit.

142
docs/OLD_CHANGELOG.md Normal file
View File

@@ -0,0 +1,142 @@
# Version Log
* [Releases](https://github.com/adamhathcock/sharpcompress/releases)
## Version 0.18
* [Now on Github releases](https://github.com/adamhathcock/sharpcompress/releases/tag/0.18)
## Version 0.17.1
* Fix - [Bug Fix for .NET Core on Windows](https://github.com/adamhathcock/sharpcompress/pull/257)
## Version 0.17.0
* New - Full LZip support! Can read and write LZip files and Tars inside LZip files. [Make LZip a first class citizen. #241](https://github.com/adamhathcock/sharpcompress/issues/241)
* New - XZ read support! Can read XZ files and Tars inside XZ files. [XZ in SharpCompress #91](https://github.com/adamhathcock/sharpcompress/issues/94)
* Fix - [Regression - zip file writing on seekable streams always assumed stream start was 0. Introduced with Zip64 writing.](https://github.com/adamhathcock/sharpcompress/issues/244)
* Fix - [Zip files with post-data descriptors can be properly skipped via decompression](https://github.com/adamhathcock/sharpcompress/issues/162)
## Version 0.16.2
* Fix [.NET 3.5 should support files and cryptography (was a regression from 0.16.0)](https://github.com/adamhathcock/sharpcompress/pull/251)
* Fix [Zip per entry compression customization wrote the wrong method into the zip archive](https://github.com/adamhathcock/sharpcompress/pull/249)
## Version 0.16.1
* Fix [Preserve compression method when getting a compressed stream](https://github.com/adamhathcock/sharpcompress/pull/235)
* Fix [RAR entry key normalization fix](https://github.com/adamhathcock/sharpcompress/issues/201)
## Version 0.16.0
* Breaking - [Progress Event Tracking rethink](https://github.com/adamhathcock/sharpcompress/pull/226)
* Update to VS2017 - [VS2017](https://github.com/adamhathcock/sharpcompress/pull/231) - Framework targets have been changed.
* New - [Add Zip64 writing](https://github.com/adamhathcock/sharpcompress/pull/211)
* [Fix invalid/mismatching Zip version flags.](https://github.com/adamhathcock/sharpcompress/issues/164) - This allows nuget/System.IO.Packaging to read zip files generated by SharpCompress
* [Fix 7Zip directory hiding](https://github.com/adamhathcock/sharpcompress/pull/215/files)
* [Verify RAR CRC headers](https://github.com/adamhathcock/sharpcompress/pull/220)
## Version 0.15.2
* [Fix invalid headers](https://github.com/adamhathcock/sharpcompress/pull/210) - fixes an issue creating large-ish zip archives that was introduced with zip64 reading.
## Version 0.15.1
* [Zip64 extending information and ZipReader](https://github.com/adamhathcock/sharpcompress/pull/206)
## Version 0.15.0
* [Add zip64 support for ZipArchive extraction](https://github.com/adamhathcock/sharpcompress/pull/205)
## Version 0.14.1
* [.NET Assemblies aren't strong named](https://github.com/adamhathcock/sharpcompress/issues/158)
* [Pkware encryption for Zip files didn't allow for multiple reads of an entry](https://github.com/adamhathcock/sharpcompress/issues/197)
* [GZip Entry couldn't be read multiple times](https://github.com/adamhathcock/sharpcompress/issues/198)
## Version 0.14.0
* [Support for LZip reading in for Tars](https://github.com/adamhathcock/sharpcompress/pull/191)
## Version 0.13.1
* [Fix null password on ReaderFactory. Fix null options on SevenZipArchive](https://github.com/adamhathcock/sharpcompress/pull/188)
* [Make PpmdProperties lazy to avoid unnecessary allocations.](https://github.com/adamhathcock/sharpcompress/pull/185)
## Version 0.13.0
* Breaking change: Big refactor of Options on API.
* 7Zip supports Deflate
## Version 0.12.4
* Forward only zip issue fix https://github.com/adamhathcock/sharpcompress/issues/160
* Try to fix frameworks again by copying targets from JSON.NET
## Version 0.12.3
* 7Zip fixes https://github.com/adamhathcock/sharpcompress/issues/73
* Maybe all profiles will work with project.json now
## Version 0.12.2
* Support Profile 259 again
## Version 0.12.1
* Support Silverlight 5
## Version 0.12.0
* .NET Core RTM!
* Bug fix for Tar long paths
## Version 0.11.6
* Bug fix for global header in Tar
* Writers now have a leaveOpen `bool` overload. They won't close streams if not-requested to.
## Version 0.11.5
* Bug fix in Skip method
## Version 0.11.4
* SharpCompress is now endian neutral (matters for Mono platforms)
* Fix for Inflate (need to change implementation)
* Fixes for RAR detection
## Version 0.11.1
* Added Cancel on IReader
* Removed .NET 2.0 support and LinqBridge dependency
## Version 0.11
* Been over a year, contains mainly fixes from contributors!
* Possible breaking change: ArchiveEncoding is UTF8 by default now.
* TAR supports writing long names using longlink
* RAR Protect Header added
## Version 0.10.3
* Finally fixed Disposal issue when creating a new archive with the Archive API
## Version 0.10.2
* Fixed Rar Header reading for invalid extended time headers.
* Windows Store assembly is now strong named
* Known issues with Long Tar names being worked on
* Updated to VS2013
* Portable targets SL5 and Windows Phone 8 (up from SL4 and WP7)
## Version 0.10.1
* Fixed 7Zip extraction performance problem
## Version 0.10:
* Added support for RAR Decryption (thanks to https://github.com/hrasyid)
* Embedded some BouncyCastle crypto classes to allow RAR Decryption and Winzip AES Decryption in Portable and Windows Store DLLs
* Built in Release (I think)

474
docs/PERFORMANCE.md Normal file
View File

@@ -0,0 +1,474 @@
# SharpCompress Performance Guide
This guide helps you optimize SharpCompress for performance in various scenarios.
## API Selection Guide
### Archive API vs Reader API
Choose the right API based on your use case:
| Aspect | Archive API | Reader API |
|--------|------------|-----------|
| **Stream Type** | Seekable only | Non-seekable OK |
| **Memory Usage** | All entries in memory | One entry at a time |
| **Random Access** | ✓ Yes | ✗ No |
| **Best For** | Small-to-medium archives | Large or streaming data |
| **Performance** | Fast for random access | Better for large files |
### Archive API (Fast for Random Access)
```csharp
// Use when:
// - Archive fits in memory
// - You need random access to entries
// - Stream is seekable (file, MemoryStream)
using (var archive = ZipArchive.Open("archive.zip"))
{
// Random access - all entries available
var specific = archive.Entries.FirstOrDefault(e => e.Key == "file.txt");
if (specific != null)
{
specific.WriteToFile(@"C:\output\file.txt");
}
}
```
**Performance Characteristics:**
- ✓ Instant entry lookup
- ✓ Parallel extraction possible
- ✗ Entire archive in memory
- ✗ Can't process while downloading
### Reader API (Best for Large Files)
```csharp
// Use when:
// - Processing large archives (>100 MB)
// - Streaming from network/pipe
// - Memory is constrained
// - Forward-only processing is acceptable
using (var stream = File.OpenRead("large.zip"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
// Process one entry at a time
reader.WriteEntryToDirectory(@"C:\output");
}
}
```
**Performance Characteristics:**
- ✓ Minimal memory footprint
- ✓ Works with non-seekable streams
- ✓ Can process while downloading
- ✗ Forward-only (no random access)
- ✗ Entry lookup requires iteration
---
## Buffer Sizing
### Understanding Buffers
SharpCompress uses internal buffers for reading compressed data. Buffer size affects:
- **Speed:** Larger buffers = fewer I/O operations = faster
- **Memory:** Larger buffers = higher memory usage
### Recommended Buffer Sizes
| Scenario | Size | Notes |
|----------|------|-------|
| Embedded/IoT devices | 4-8 KB | Minimal memory usage |
| Memory-constrained | 16-32 KB | Conservative default |
| Standard use (default) | 64 KB | Recommended default |
| Large file streaming | 256 KB | Better throughput |
| High-speed SSD | 512 KB - 1 MB | Maximum throughput |
### How Buffer Size Affects Performance
```csharp
// SharpCompress manages buffers internally
// You can't directly set buffer size, but you can:
// 1. Use Stream.CopyTo with explicit buffer size
using (var entryStream = reader.OpenEntryStream())
using (var fileStream = File.Create(@"C:\output\file.txt"))
{
// 64 KB buffer (default)
entryStream.CopyTo(fileStream);
// Or specify larger buffer for faster copy
entryStream.CopyTo(fileStream, bufferSize: 262144); // 256 KB
}
// 2. Use custom buffer for writing
using (var entryStream = reader.OpenEntryStream())
using (var fileStream = File.Create(@"C:\output\file.txt"))
{
byte[] buffer = new byte[262144]; // 256 KB
int bytesRead;
while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, bytesRead);
}
}
```
---
## Streaming Large Files
### Non-Seekable Stream Patterns
For processing archives from downloads or pipes:
```csharp
// Download stream (non-seekable)
using (var httpStream = await httpClient.GetStreamAsync(url))
using (var reader = ReaderFactory.Open(httpStream))
{
// Process entries as they arrive
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
}
```
**Performance Tips:**
- Don't try to buffer the entire stream
- Process entries immediately
- Use async APIs for better responsiveness
### Download-Then-Extract vs Streaming
Choose based on your constraints:
| Approach | When to Use |
|----------|------------|
| **Download then extract** | Moderate size, need random access |
| **Stream during download** | Large files, bandwidth limited, memory constrained |
```csharp
// Download then extract (requires disk space)
var archivePath = await DownloadFile(url, @"C:\temp\archive.zip");
using (var archive = ZipArchive.Open(archivePath))
{
archive.WriteToDirectory(@"C:\output");
}
// Stream during download (on-the-fly extraction)
using (var httpStream = await httpClient.GetStreamAsync(url))
using (var reader = ReaderFactory.Open(httpStream))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
```
---
## Solid Archive Optimization
### Why Solid Archives Are Slow
Solid archives (Rar, 7Zip) group files together in a single compressed stream:
```
Solid Archive Layout:
[Header] [Compressed Stream] [Footer]
├─ File1 compressed data
├─ File2 compressed data
├─ File3 compressed data
└─ File4 compressed data
```
Extracting File3 requires decompressing File1 and File2 first.
### Sequential vs Random Extraction
**Random Extraction (Slow):**
```csharp
using (var archive = RarArchive.Open("solid.rar"))
{
foreach (var entry in archive.Entries)
{
entry.WriteToFile(@"C:\output\" + entry.Key); // ✗ Slow!
// Each entry triggers full decompression from start
}
}
```
**Sequential Extraction (Fast):**
```csharp
using (var archive = RarArchive.Open("solid.rar"))
{
// Method 1: Use WriteToDirectory (recommended)
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
// Method 2: Use ExtractAllEntries
archive.ExtractAllEntries();
// Method 3: Use Reader API (also sequential)
using (var reader = RarReader.Open(File.OpenRead("solid.rar")))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(@"C:\output");
}
}
}
```
**Performance Impact:**
- Random extraction: O(n²) - very slow for many files
- Sequential extraction: O(n) - 10-100x faster
### Best Practices for Solid Archives
1. **Always extract sequentially** when possible
2. **Use Reader API** for large solid archives
3. **Process entries in order** from the archive
4. **Consider using 7Zip command-line** for scripted extractions
---
## Compression Level Trade-offs
### Deflate/GZip Levels
```csharp
// Level 1 = Fastest, largest size
// Level 6 = Default (balanced)
// Level 9 = Slowest, best compression
// Write with different compression levels
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(@"D:\data");
// Fast compression (level 1)
archive.SaveTo("fast.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 1
});
// Default compression (level 6)
archive.SaveTo("default.zip", CompressionType.Deflate);
// Best compression (level 9)
archive.SaveTo("best.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9
});
}
```
**Speed vs Size:**
| Level | Speed | Size | Use Case |
|-------|-------|------|----------|
| 1 | 10x | 90% | Network, streaming |
| 6 | 1x | 75% | Default (good balance) |
| 9 | 0.1x | 65% | Archival, static storage |
### BZip2 Block Size
```csharp
// BZip2 block size affects memory and compression
// 100K to 900K (default 900K)
// Smaller block size = lower memory, faster
// Larger block size = better compression, slower
using (var archive = TarArchive.Create())
{
archive.AddAllFromDirectory(@"D:\data");
// These are preset in WriterOptions via CompressionLevel
archive.SaveTo("archive.tar.bz2", CompressionType.BZip2);
}
```
### LZMA Settings
LZMA compression is very powerful but memory-intensive:
```csharp
// LZMA (7Zip, .tar.lzma):
// - Dictionary size: 16 KB to 1 GB (default 32 MB)
// - Faster preset: smaller dictionary
// - Better compression: larger dictionary
// Preset via CompressionType
using (var archive = TarArchive.Create())
{
archive.AddAllFromDirectory(@"D:\data");
archive.SaveTo("archive.tar.xz", CompressionType.LZMA); // Default settings
}
```
---
## Async Performance
### When Async Helps
Async is beneficial when:
- **Long I/O operations** (network, slow disks)
- **UI responsiveness** needed (Windows Forms, WPF, Blazor)
- **Server applications** (ASP.NET, multiple concurrent operations)
```csharp
// Async extraction (non-blocking)
using (var archive = ZipArchive.Open("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true },
cancellationToken
);
}
// Thread can handle other work while I/O happens
```
### When Async Doesn't Help
Async doesn't improve performance for:
- **CPU-bound operations** (already fast)
- **Local SSD I/O** (I/O is fast enough)
- **Single-threaded scenarios** (no parallelism benefit)
```csharp
// Sync extraction (simpler, same performance on fast I/O)
using (var archive = ZipArchive.Open("archive.zip"))
{
archive.WriteToDirectory(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
// Simple and fast - no async needed
```
### Cancellation Pattern
```csharp
var cts = new CancellationTokenSource();
// Cancel after 5 minutes
cts.CancelAfter(TimeSpan.FromMinutes(5));
try
{
using (var archive = ZipArchive.Open("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
new ExtractionOptions { ExtractFullPath = true, Overwrite = true },
cts.Token
);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Extraction cancelled");
// Clean up partial extraction if needed
}
```
---
## Practical Performance Tips
### 1. Choose the Right API
| Scenario | API | Why |
|----------|-----|-----|
| Small archives | Archive | Faster random access |
| Large archives | Reader | Lower memory |
| Streaming | Reader | Works on non-seekable streams |
| Download streams | Reader | Async extraction while downloading |
### 2. Batch Operations
```csharp
// ✗ Slow - opens each archive separately
foreach (var file in files)
{
using (var archive = ZipArchive.Open("archive.zip"))
{
archive.WriteToDirectory(@"C:\output");
}
}
// ✓ Better - process multiple entries at once
using (var archive = ZipArchive.Open("archive.zip"))
{
archive.WriteToDirectory(@"C:\output");
}
```
### 3. Profile Your Code
```csharp
var sw = Stopwatch.StartNew();
using (var archive = ZipArchive.Open("large.zip"))
{
archive.WriteToDirectory(@"C:\output");
}
sw.Stop();
Console.WriteLine($"Extraction took {sw.ElapsedMilliseconds}ms");
// Measure memory before/after
var beforeMem = GC.GetTotalMemory(true);
// ... do work ...
var afterMem = GC.GetTotalMemory(true);
Console.WriteLine($"Memory used: {(afterMem - beforeMem) / 1024 / 1024}MB");
```
---
## Troubleshooting Performance
### Extraction is Slow
1. **Check if solid archive** → Use sequential extraction
2. **Check API** → Reader API might be faster for large files
3. **Check compression level** → Higher levels are slower to decompress
4. **Check I/O** → Network drives are much slower than SSD
5. **Check buffer size** → May need larger buffers for network
### High Memory Usage
1. **Use Reader API** instead of Archive API
2. **Process entries immediately** rather than buffering
3. **Reduce compression level** if writing
4. **Check for memory leaks** in your code
### CPU Usage at 100%
1. **Normal for compression** - especially with high compression levels
2. **Consider lower level** for faster processing
3. **Reduce parallelism** if processing multiple archives
4. **Check if awaiting properly** in async code
---
## Related Documentation
- [PERFORMANCE.md](USAGE.md) - Usage examples with performance considerations
- [FORMATS.md](FORMATS.md) - Format-specific performance notes

335
docs/USAGE.md Normal file
View File

@@ -0,0 +1,335 @@
# SharpCompress Usage
## Async/Await Support (Beta)
SharpCompress now provides full async/await support for all I/O operations. All `Read`, `Write`, and extraction operations have async equivalents ending in `Async` that accept an optional `CancellationToken`. This enables better performance and scalability for I/O-bound operations.
**Key Async Methods:**
- `reader.WriteEntryToAsync(stream, cancellationToken)` - Extract entry asynchronously
- `reader.WriteAllToDirectoryAsync(path, options, cancellationToken)` - Extract all asynchronously
- `writer.WriteAsync(filename, stream, modTime, cancellationToken)` - Write entry asynchronously
- `writer.WriteAllAsync(directory, pattern, searchOption, cancellationToken)` - Write directory asynchronously
- `entry.OpenEntryStreamAsync(cancellationToken)` - Open entry stream asynchronously
See [Async Examples](#async-examples) section below for usage patterns.
## Stream Rules
When dealing with Streams, the rule should be that you don't close a stream you didn't create. This, in effect, should mean you should always put a Stream in a using block to dispose it.
However, the .NET Framework often has classes that will dispose streams by default to make things "easy" like the following:
```C#
using (var reader = new StreamReader(File.Open("foo")))
{
...
}
```
In this example, reader should get disposed. However, stream rules should say the the `FileStream` created by `File.Open` should remain open. However, the .NET Framework closes it for you by default unless you override the constructor. In general, you should be writing Stream code like this:
```C#
using (var fileStream = File.Open("foo"))
using (var reader = new StreamReader(fileStream))
{
...
}
```
To deal with the "correct" rules as well as the expectations of users, I've decided to always close wrapped streams as of 0.21.
To be explicit though, consider always using the overloads that use `ReaderOptions` or `WriterOptions` and explicitly set `LeaveStreamOpen` the way you want.
If using Compression Stream classes directly and you don't want the wrapped stream to be closed. Use the `NonDisposingStream` as a wrapper to prevent the stream being disposed. The change in 0.21 simplified a lot even though the usage is a bit more convoluted.
## Samples
Also, look over the tests for more thorough [examples](https://github.com/adamhathcock/sharpcompress/tree/master/tests/SharpCompress.Test)
### Create Zip Archive from multiple files
```C#
using(var archive = ZipArchive.Create())
{
archive.AddEntry("file01.txt", "C:\\file01.txt");
archive.AddEntry("file02.txt", "C:\\file02.txt");
...
archive.SaveTo("C:\\temp.zip", CompressionType.Deflate);
}
```
### Create Zip Archive from all files in a directory to a file
```C#
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo("C:\\temp.zip", CompressionType.Deflate);
}
```
### Create Zip Archive from all files in a directory and save in memory
```C#
var memoryStream = new MemoryStream();
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo(memoryStream, new WriterOptions(CompressionType.Deflate)
{
LeaveStreamOpen = true
});
}
//reset memoryStream to be usable now
memoryStream.Position = 0;
```
### Extract all files from a rar file to a directory using RarArchive
Note: Extracting a solid rar or 7z file needs to be done in sequential order to get acceptable decompression speed.
`ExtractAllEntries` is primarily intended for solid archives (like solid Rar) or 7Zip archives, where sequential extraction provides the best performance. For general/simple extraction with any supported archive type, use `archive.WriteToDirectory()` instead.
```C#
using (var archive = RarArchive.Open("Test.rar"))
{
// Simple extraction with RarArchive; this WriteToDirectory pattern works for all archive types
archive.WriteToDirectory(@"D:\temp", new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
```
### Iterate over all files from a Rar file using RarArchive
```C#
using (var archive = RarArchive.Open("Test.rar"))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
Console.WriteLine($"{entry.Key}: {entry.Size} bytes");
}
}
```
### Extract solid Rar or 7Zip archives with progress reporting
`ExtractAllEntries` only works for solid archives (Rar) or 7Zip archives. For optimal performance with these archive types, use this method:
```C#
using SharpCompress.Common;
using SharpCompress.Readers;
var progress = new Progress<ProgressReport>(report =>
{
Console.WriteLine($"Extracting {report.EntryPath}: {report.PercentComplete}%");
});
using (var archive = RarArchive.Open("archive.rar", new ReaderOptions { Progress = progress })) // Must be solid Rar or 7Zip
{
archive.WriteToDirectory(@"D:\output", new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
```
### Use ReaderFactory to autodetect archive type and Open the entry stream
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Console.WriteLine(reader.Entry.Key);
reader.WriteEntryToDirectory(@"C:\temp", new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
}
```
### Use ReaderFactory to autodetect archive type and Open the entry stream
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
using (var entryStream = reader.OpenEntryStream())
{
entryStream.CopyTo(...);
}
}
}
}
```
### Use WriterFactory to write all files from a directory in a streaming manner.
```C#
using (Stream stream = File.OpenWrite("C:\\temp.tgz"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)
{
LeaveOpenStream = true
}))
{
writer.WriteAll("D:\\temp", "*", SearchOption.AllDirectories);
}
```
### Extract zip which has non-utf8 encoded filename(cp932)
```C#
var opts = new SharpCompress.Readers.ReaderOptions();
var encoding = Encoding.GetEncoding(932);
opts.ArchiveEncoding = new SharpCompress.Common.ArchiveEncoding();
opts.ArchiveEncoding.CustomDecoder = (data, x, y) =>
{
return encoding.GetString(data);
};
var tr = SharpCompress.Archives.Zip.ZipArchive.Open("test.zip", opts);
foreach(var entry in tr.Entries)
{
Console.WriteLine($"{entry.Key}");
}
```
## Async Examples
### Async Reader Examples
**Extract single entry asynchronously:**
```C#
using (Stream stream = File.OpenRead("archive.zip"))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
using (var entryStream = reader.OpenEntryStream())
{
using (var outputStream = File.Create("output.bin"))
{
await reader.WriteEntryToAsync(outputStream, cancellationToken);
}
}
}
}
}
```
**Extract all entries asynchronously:**
```C#
using (Stream stream = File.OpenRead("archive.tar.gz"))
using (var reader = ReaderFactory.Open(stream))
{
await reader.WriteAllToDirectoryAsync(
@"D:\temp",
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
},
cancellationToken
);
}
```
**Open and process entry stream asynchronously:**
```C#
using (var archive = ZipArchive.Open("archive.zip"))
{
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
{
using (var entryStream = await entry.OpenEntryStreamAsync(cancellationToken))
{
// Process the decompressed stream asynchronously
await ProcessStreamAsync(entryStream, cancellationToken);
}
}
}
```
### Async Writer Examples
**Write single file asynchronously:**
```C#
using (Stream archiveStream = File.OpenWrite("output.zip"))
using (var writer = WriterFactory.Open(archiveStream, ArchiveType.Zip, CompressionType.Deflate))
{
using (Stream fileStream = File.OpenRead("input.txt"))
{
await writer.WriteAsync("entry.txt", fileStream, DateTime.Now, cancellationToken);
}
}
```
**Write entire directory asynchronously:**
```C#
using (Stream stream = File.OpenWrite("backup.tar.gz"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)))
{
await writer.WriteAllAsync(
@"D:\files",
"*",
SearchOption.AllDirectories,
cancellationToken
);
}
```
**Write with progress tracking and cancellation:**
```C#
var cts = new CancellationTokenSource();
// Set timeout or cancel from UI
cts.CancelAfter(TimeSpan.FromMinutes(5));
using (Stream stream = File.OpenWrite("archive.zip"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
{
try
{
await writer.WriteAllAsync(@"D:\data", "*", SearchOption.AllDirectories, cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation was cancelled");
}
}
```
### Archive Async Examples
**Extract from archive asynchronously:**
```C#
using (var archive = ZipArchive.Open("archive.zip"))
{
// Simple async extraction - works for all archive types
await archive.WriteToDirectoryAsync(
@"C:\output",
new ExtractionOptions() { ExtractFullPath = true, Overwrite = true },
cancellationToken
);
}
```
**Benefits of Async Operations:**
- Non-blocking I/O for better application responsiveness
- Improved scalability for server applications
- Support for cancellation via CancellationToken
- Better resource utilization in async/await contexts
- Compatible with modern .NET async patterns

View File

@@ -1,3 +1,6 @@
{
"projects": ["src","test"]
"sdk": {
"version": "10.0.100",
"rollForward": "latestFeature"
}
}

3497
reference/APPNOTE.TXT Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,279 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{95CC809B-03FC-4EDB-BB20-FD07A698C05F}</ProjectGuid>
<RootNamespace>UnRAR</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>build\unrar32\$(Configuration)\</OutDir>
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>build\unrar64\$(Configuration)\</OutDir>
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>build\unrar32\$(Configuration)\</OutDir>
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>build\unrar64\$(Configuration)\</OutDir>
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>Default</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="archive.cpp" />
<ClCompile Include="arcread.cpp" />
<ClCompile Include="blake2s.cpp" />
<ClCompile Include="cmddata.cpp" />
<ClCompile Include="consio.cpp" />
<ClCompile Include="crc.cpp" />
<ClCompile Include="crypt.cpp" />
<ClCompile Include="encname.cpp" />
<ClCompile Include="errhnd.cpp" />
<ClCompile Include="extinfo.cpp" />
<ClCompile Include="extract.cpp" />
<ClCompile Include="filcreat.cpp" />
<ClCompile Include="file.cpp" />
<ClCompile Include="filefn.cpp" />
<ClCompile Include="filestr.cpp" />
<ClCompile Include="find.cpp" />
<ClCompile Include="getbits.cpp" />
<ClCompile Include="global.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="hash.cpp" />
<ClCompile Include="headers.cpp" />
<ClCompile Include="isnt.cpp" />
<ClCompile Include="list.cpp" />
<ClCompile Include="match.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="pathfn.cpp" />
<ClCompile Include="qopen.cpp" />
<ClCompile Include="rar.cpp" />
<ClCompile Include="rarpch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rarvm.cpp" />
<ClCompile Include="rawread.cpp" />
<ClCompile Include="rdwrfn.cpp" />
<ClCompile Include="recvol.cpp" />
<ClCompile Include="resource.cpp" />
<ClCompile Include="rijndael.cpp" />
<ClCompile Include="rs.cpp" />
<ClCompile Include="rs16.cpp" />
<ClCompile Include="scantree.cpp" />
<ClCompile Include="secpassword.cpp" />
<ClCompile Include="sha1.cpp" />
<ClCompile Include="sha256.cpp" />
<ClCompile Include="smallfn.cpp" />
<ClCompile Include="strfn.cpp" />
<ClCompile Include="strlist.cpp" />
<ClCompile Include="system.cpp" />
<ClCompile Include="threadpool.cpp" />
<ClCompile Include="timefn.cpp" />
<ClCompile Include="ui.cpp" />
<ClCompile Include="unicode.cpp" />
<ClCompile Include="unpack.cpp" />
<ClCompile Include="volume.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,420 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release_nocrypt|Win32">
<Configuration>release_nocrypt</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release_nocrypt|x64">
<Configuration>release_nocrypt</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>UnRAR</ProjectName>
<ProjectGuid>{E815C46C-36C4-499F-BBC2-E772C6B17971}</ProjectGuid>
<RootNamespace>UnRAR</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="archive.cpp" />
<ClCompile Include="arcread.cpp" />
<ClCompile Include="blake2s.cpp" />
<ClCompile Include="cmddata.cpp" />
<ClCompile Include="consio.cpp" />
<ClCompile Include="crc.cpp" />
<ClCompile Include="crypt.cpp" />
<ClCompile Include="dll.cpp" />
<ClCompile Include="encname.cpp" />
<ClCompile Include="errhnd.cpp" />
<ClCompile Include="extinfo.cpp" />
<ClCompile Include="extract.cpp" />
<ClCompile Include="filcreat.cpp" />
<ClCompile Include="file.cpp" />
<ClCompile Include="filefn.cpp" />
<ClCompile Include="filestr.cpp" />
<ClCompile Include="find.cpp" />
<ClCompile Include="getbits.cpp" />
<ClCompile Include="global.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="hash.cpp" />
<ClCompile Include="headers.cpp" />
<ClCompile Include="isnt.cpp" />
<ClCompile Include="match.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="pathfn.cpp" />
<ClCompile Include="qopen.cpp" />
<ClCompile Include="rar.cpp" />
<ClCompile Include="rarpch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rarvm.cpp" />
<ClCompile Include="rawread.cpp" />
<ClCompile Include="rdwrfn.cpp" />
<ClCompile Include="rijndael.cpp" />
<ClCompile Include="rs.cpp" />
<ClCompile Include="rs16.cpp" />
<ClCompile Include="scantree.cpp" />
<ClCompile Include="secpassword.cpp" />
<ClCompile Include="sha1.cpp" />
<ClCompile Include="sha256.cpp" />
<ClCompile Include="smallfn.cpp" />
<ClCompile Include="strfn.cpp" />
<ClCompile Include="strlist.cpp" />
<ClCompile Include="system.cpp" />
<ClCompile Include="threadpool.cpp" />
<ClCompile Include="timefn.cpp" />
<ClCompile Include="ui.cpp" />
<ClCompile Include="unicode.cpp" />
<ClCompile Include="unpack.cpp" />
<ClCompile Include="volume.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="rar.hpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="dll.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,92 @@
ACKNOWLEDGMENTS
* We used "Screaming Fast Galois Field Arithmetic Using Intel
SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
and Ethan L. Miller to improve Reed-Solomon coding performance.
Also we are grateful to Artem Drobanov and Bulat Ziganshin
for samples and ideas allowed to make Reed-Solomon coding
more efficient.
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
and Dmitry Subbotin carryless rangecoder public domain source code.
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
* RAR encryption includes parts of code from Szymon Stefanek
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Source code of this package also as other cryptographic technology
and computing project related links are available on Brian Gladman's
web site: http://www.gladman.me.uk
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
Original Intel Slicing-by-8 code is available here:
http://sourceforge.net/projects/slicing-by-8/
Original Intel Slicing-by-8 code is licensed under BSD License
available at http://www.opensource.org/licenses/bsd-license.html
Copyright (c) 2004-2006 Intel Corporation.
All Rights Reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
and Christian Winnerlein.
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
to significantly improve RAR compression and speed.

166
reference/unrar/arccmt.cpp Normal file
View File

@@ -0,0 +1,166 @@
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
bool Archive::GetComment(Array<wchar> *CmtData)
{
if (!MainComment)
return false;
SaveFilePos SavePos(*this);
#ifndef SFX_MODULE
uint CmtLength;
if (Format==RARFMT14)
{
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
CmtLength=GetByte();
CmtLength+=(GetByte()<<8);
}
else
#endif
{
if (MainHead.CommentInHeader)
{
// Old style (RAR 2.9) archive comment embedded into the main
// archive header.
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
ReadHeader();
}
else
{
// Current (RAR 3.0+) version of archive comment.
Seek(GetStartPos(),SEEK_SET);
return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
}
#ifndef SFX_MODULE
// Old style (RAR 2.9) comment header embedded into the main
// archive header.
if (BrokenHeader)
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
}
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
#endif
}
#ifndef SFX_MODULE
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
{
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
return false;
ComprDataIO DataIO;
DataIO.SetTestMode(true);
uint UnpCmtLength;
if (Format==RARFMT14)
{
#ifdef RAR_NOCRYPT
return false;
#else
UnpCmtLength=GetByte();
UnpCmtLength+=(GetByte()<<8);
CmtLength-=2;
DataIO.SetCmt13Encryption();
CommHead.UnpVer=15;
#endif
}
else
UnpCmtLength=CommHead.UnpSize;
DataIO.SetFiles(this,NULL);
DataIO.EnableShowProgress(false);
DataIO.SetPackedSizeToRead(CmtLength);
DataIO.UnpHash.Init(HASH_CRC32,1);
Unpack CmtUnpack(&DataIO);
CmtUnpack.Init(0x10000,false);
CmtUnpack.SetDestSize(UnpCmtLength);
CmtUnpack.DoUnpack(CommHead.UnpVer,false);
if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
}
else
{
byte *UnpData;
size_t UnpDataSize;
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
#ifdef _WIN_ALL
// If we ever decide to extend it to Android, we'll need to alloc
// 4x memory for OEM to UTF-8 output here.
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
#endif
CmtData->Alloc(UnpDataSize+1);
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
CmtData->Alloc(wcslen(CmtData->Addr(0)));
}
}
else
{
if (CmtLength==0)
return false;
Array<byte> CmtRaw(CmtLength);
Read(&CmtRaw[0],CmtLength);
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
}
CmtData->Alloc(CmtLength+1);
CmtRaw.Push(0);
#ifdef _WIN_ALL
// If we ever decide to extend it to Android, we'll need to alloc
// 4x memory for OEM to UTF-8 output here.
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
#endif
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength);
CmtData->Alloc(wcslen(CmtData->Addr(0)));
}
#endif
return CmtData->Size() > 0;
}
bool Archive::ReadCommentData(Array<wchar> *CmtData)
{
Array<byte> CmtRaw;
if (!ReadSubData(&CmtRaw,NULL))
return false;
size_t CmtSize=CmtRaw.Size();
CmtRaw.Push(0);
CmtData->Alloc(CmtSize+1);
if (Format==RARFMT50)
UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
else
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
{
RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
(*CmtData)[CmtSize/2]=0;
}
else
{
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
}
CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
return true;
}
void Archive::ViewComment()
{
if (Cmd->DisableComment)
return;
Array<wchar> CmtBuf;
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
{
size_t CmtSize=CmtBuf.Size();
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
if (ChPtr!=NULL)
CmtSize=ChPtr-&CmtBuf[0];
mprintf(L"\n");
OutComment(&CmtBuf[0],CmtSize);
}
}

332
reference/unrar/archive.cpp Normal file
View File

@@ -0,0 +1,332 @@
#include "rar.hpp"
#include "arccmt.cpp"
Archive::Archive(RAROptions *InitCmd)
{
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
DummyCmd=(InitCmd==NULL);
Cmd=DummyCmd ? (new RAROptions):InitCmd;
OpenShared=Cmd->OpenShared;
Format=RARFMT15;
Solid=false;
Volume=false;
MainComment=false;
Locked=false;
Signed=false;
FirstVolume=false;
NewNumbering=false;
SFXSize=0;
LatestTime.Reset();
Protected=false;
Encrypted=false;
FailedHeaderDecryption=false;
BrokenHeader=false;
LastReadBlock=0;
CurBlockPos=0;
NextBlockPos=0;
RecoverySize=-1;
RecoveryPercent=-1;
memset(&MainHead,0,sizeof(MainHead));
memset(&CryptHead,0,sizeof(CryptHead));
memset(&EndArcHead,0,sizeof(EndArcHead));
VolNumber=0;
VolWrite=0;
AddingFilesSize=0;
AddingHeadersSize=0;
*FirstVolumeName=0;
Splitting=false;
NewArchive=false;
SilentOpen=false;
}
Archive::~Archive()
{
if (DummyCmd)
delete Cmd;
}
void Archive::CheckArc(bool EnableBroken)
{
if (!IsArchive(EnableBroken))
{
// If FailedHeaderDecryption is set, we already reported that archive
// password is incorrect.
if (!FailedHeaderDecryption)
uiMsg(UIERROR_BADARCHIVE,FileName);
ErrHandler.Exit(RARX_FATAL);
}
}
#if !defined(SFX_MODULE)
void Archive::CheckOpen(const wchar *Name)
{
TOpen(Name);
CheckArc(false);
}
#endif
bool Archive::WCheckOpen(const wchar *Name)
{
if (!WOpen(Name))
return false;
if (!IsArchive(false))
{
uiMsg(UIERROR_BADARCHIVE,FileName);
Close();
return false;
}
return true;
}
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
{
RARFORMAT Type=RARFMT_NONE;
if (Size>=1 && D[0]==0x52)
#ifndef SFX_MODULE
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
Type=RARFMT14;
else
#endif
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
{
// We check the last signature byte, so we can return a sensible
// warning in case we'll want to change the archive format
// sometimes in the future.
if (D[6]==0)
Type=RARFMT15;
else
if (D[6]==1)
Type=RARFMT50;
else
if (D[6]==2)
Type=RARFMT_FUTURE;
}
return Type;
}
bool Archive::IsArchive(bool EnableBroken)
{
Encrypted=false;
BrokenHeader=false; // Might be left from previous volume.
#ifndef SFX_MODULE
if (IsDevice())
{
uiMsg(UIERROR_INVALIDNAME,FileName,FileName);
return false;
}
#endif
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
return false;
SFXSize=0;
RARFORMAT Type;
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
{
Format=Type;
if (Format==RARFMT14)
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
}
else
{
Array<char> Buffer(MAXSFXSIZE);
long CurPos=(long)Tell();
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
for (int I=0;I<ReadSize;I++)
if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
{
Format=Type;
if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
{
char *D=&Buffer[28-CurPos];
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
continue;
}
SFXSize=CurPos+I;
Seek(SFXSize,SEEK_SET);
if (Format==RARFMT15 || Format==RARFMT50)
Read(MarkHead.Mark,SIZEOF_MARKHEAD3);
break;
}
if (SFXSize==0)
return false;
}
if (Format==RARFMT_FUTURE)
{
uiMsg(UIERROR_NEWRARFORMAT,FileName);
return false;
}
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
{
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
return false;
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
}
else
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
#ifdef RARDLL
// If callback function is not set, we cannot get the password,
// so we skip the initial header processing for encrypted header archive.
// It leads to skipped archive comment, but the rest of archive data
// is processed correctly.
if (Cmd->Callback==NULL)
SilentOpen=true;
#endif
// Skip the archive encryption header if any and read the main header.
while (ReadHeader()!=0)
{
HEADER_TYPE Type=GetHeaderType();
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
// avoid the password prompt.
if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT)
break;
SeekToNext();
}
// This check allows to make RS based recovery even if password is incorrect.
// But we should not do it for EnableBroken or we'll get 'not RAR archive'
// messages when extracting encrypted archives with wrong password.
if (FailedHeaderDecryption && !EnableBroken)
return false;
SeekToNext();
if (BrokenHeader) // Main archive header is corrupt.
{
uiMsg(UIERROR_MHEADERBROKEN,FileName);
if (!EnableBroken)
return false;
}
MainComment=MainHead.CommentInHeader;
// If we process non-encrypted archive or can request a password,
// we set 'first volume' flag based on file attributes below.
// It is necessary for RAR 2.x archives, which did not have 'first volume'
// flag in main header. Also for all RAR formats we need to scan until
// first file header to set "comment" flag when reading service header.
// Unless we are in silent mode, we need to know about presence of comment
// immediately after IsArchive call.
if (!SilentOpen || !Encrypted)
{
SaveFilePos SavePos(*this);
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
while (ReadHeader()!=0)
{
HEADER_TYPE HeaderType=GetHeaderType();
if (HeaderType==HEAD_SERVICE)
{
// If we have a split service headers, it surely indicates non-first
// volume. But not split service header does not guarantee the first
// volume, because we can have split file after non-split archive
// comment. So we do not quit from loop here.
FirstVolume=Volume && !SubHead.SplitBefore;
}
else
if (HeaderType==HEAD_FILE)
{
FirstVolume=Volume && !FileHead.SplitBefore;
break;
}
else
if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
break;
SeekToNext();
}
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
CurHeaderType=SaveCurHeaderType;
}
if (!Volume || FirstVolume)
wcscpy(FirstVolumeName,FileName);
return true;
}
void Archive::SeekToNext()
{
Seek(NextBlockPos,SEEK_SET);
}
// Calculate the block size including encryption fields and padding if any.
uint Archive::FullHeaderSize(size_t Size)
{
if (Encrypted)
{
Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
if (Format == RARFMT50)
Size += SIZE_INITV;
else
Size += SIZE_SALT30;
}
return uint(Size);
}
#ifdef USE_QOPEN
bool Archive::Open(const wchar *Name,uint Mode)
{
// Important if we reuse Archive object and it has virtual QOpen
// file position not matching real. For example, for 'l -v volname'.
QOpen.Unload();
return File::Open(Name,Mode);
}
int Archive::Read(void *Data,size_t Size)
{
size_t Result;
if (QOpen.Read(Data,Size,Result))
return (int)Result;
return File::Read(Data,Size);
}
void Archive::Seek(int64 Offset,int Method)
{
if (!QOpen.Seek(Offset,Method))
File::Seek(Offset,Method);
}
int64 Archive::Tell()
{
int64 QPos;
if (QOpen.Tell(&QPos))
return QPos;
return File::Tell();
}
#endif

151
reference/unrar/archive.hpp Normal file
View File

@@ -0,0 +1,151 @@
#ifndef _RAR_ARCHIVE_
#define _RAR_ARCHIVE_
class PPack;
class RawRead;
class RawWrite;
enum NOMODIFY_FLAGS
{
NMDF_ALLOWLOCK=1,NMDF_ALLOWANYVOLUME=2,NMDF_ALLOWFIRSTVOLUME=4
};
enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
enum ADDSUBDATA_FLAGS
{
ASDF_SPLIT = 1, // Allow to split archive just before header if necessary.
ASDF_COMPRESS = 2, // Allow to compress data following subheader.
ASDF_CRYPT = 4, // Encrypt data after subheader if password is set.
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
};
class Archive:public File
{
private:
void UpdateLatestTime(FileHeader *CurBlock);
void ConvertNameCase(wchar *Name);
void ConvertFileHeader(FileHeader *hd);
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
size_t ReadHeader14();
size_t ReadHeader15();
size_t ReadHeader50();
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
void RequestArcPassword();
void UnexpEndArcMsg();
void BrokenHeaderMsg();
void UnkEncVerMsg(const wchar *Name);
void UnkEncVerMsg();
bool ReadCommentData(Array<wchar> *CmtData);
#if !defined(RAR_NOCRYPT)
CryptData HeadersCrypt;
#endif
ComprDataIO SubDataIO;
bool DummyCmd;
RAROptions *Cmd;
int64 RecoverySize;
int RecoveryPercent;
RarTime LatestTime;
int LastReadBlock;
HEADER_TYPE CurHeaderType;
bool SilentOpen;
#ifdef USE_QOPEN
QuickOpen QOpen;
#endif
public:
Archive(RAROptions *InitCmd=NULL);
~Archive();
static RARFORMAT IsSignature(const byte *D,size_t Size);
bool IsArchive(bool EnableBroken);
size_t SearchBlock(HEADER_TYPE HeaderType);
size_t SearchSubBlock(const wchar *Type);
size_t SearchRR();
void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false);
void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);}
size_t ReadHeader();
void CheckArc(bool EnableBroken);
void CheckOpen(const wchar *Name);
bool WCheckOpen(const wchar *Name);
bool GetComment(Array<wchar> *CmtData);
void ViewComment();
void SetLatestTime(RarTime *NewTime);
void SeekToNext();
bool CheckAccess();
bool IsArcDir();
void ConvertAttributes();
void VolSubtractHeaderSize(size_t SubSize);
uint FullHeaderSize(size_t Size);
int64 GetStartPos();
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
const wchar *Name,uint Flags);
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
RAROptions* GetRAROptions() {return Cmd;}
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
#if 0
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
#endif
#ifdef USE_QOPEN
bool Open(const wchar *Name,uint Mode=FMF_READ);
int Read(void *Data,size_t Size);
void Seek(int64 Offset,int Method);
int64 Tell();
void QOpenUnload() {QOpen.Unload();}
#endif
BaseBlock ShortBlock;
MarkHeader MarkHead;
MainHeader MainHead;
CryptHeader CryptHead;
FileHeader FileHead;
EndArcHeader EndArcHead;
SubBlockHeader SubBlockHead;
FileHeader SubHead;
CommentHeader CommHead;
ProtectHeader ProtectHead;
AVHeader AVHead;
SignHeader SignHead;
UnixOwnersHeader UOHead;
MacFInfoHeader MACHead;
EAHeader EAHead;
StreamHeader StreamHead;
int64 CurBlockPos;
int64 NextBlockPos;
RARFORMAT Format;
bool Solid;
bool Volume;
bool MainComment;
bool Locked;
bool Signed;
bool FirstVolume;
bool NewNumbering;
bool Protected;
bool Encrypted;
size_t SFXSize;
bool BrokenHeader;
bool FailedHeaderDecryption;
#if !defined(RAR_NOCRYPT)
byte ArcSalt[SIZE_SALT50];
#endif
bool Splitting;
uint VolNumber;
int64 VolWrite;
uint64 AddingFilesSize;
uint64 AddingHeadersSize;
bool NewArchive;
wchar FirstVolumeName[NM];
};
#endif

1437
reference/unrar/arcread.cpp Normal file

File diff suppressed because it is too large Load Diff

191
reference/unrar/array.hpp Normal file
View File

@@ -0,0 +1,191 @@
#ifndef _RAR_ARRAY_
#define _RAR_ARRAY_
extern ErrorHandler ErrHandler;
template <class T> class Array
{
private:
T *Buffer;
size_t BufSize;
size_t AllocSize;
size_t MaxSize;
bool Secure; // Clean memory if true.
public:
Array();
Array(size_t Size);
Array(const Array &Src); // Copy constructor.
~Array();
inline void CleanData();
inline T& operator [](size_t Item) const;
inline T* operator + (size_t Pos);
inline size_t Size(); // Returns the size in items, not in bytes.
void Add(size_t Items);
void Alloc(size_t Items);
void Reset();
void SoftReset();
void operator = (Array<T> &Src);
void Push(T Item);
void Append(T *Item,size_t Count);
T* Addr(size_t Item) {return Buffer+Item;}
void SetMaxSize(size_t Size) {MaxSize=Size;}
T* Begin() {return Buffer;}
T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
void SetSecure() {Secure=true;}
};
template <class T> void Array<T>::CleanData()
{
Buffer=NULL;
BufSize=0;
AllocSize=0;
MaxSize=0;
Secure=false;
}
template <class T> Array<T>::Array()
{
CleanData();
}
template <class T> Array<T>::Array(size_t Size)
{
CleanData();
Add(Size);
}
// Copy constructor in case we need to pass an object as value.
template <class T> Array<T>::Array(const Array &Src)
{
CleanData();
Alloc(Src.BufSize);
if (Src.BufSize!=0)
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
}
template <class T> Array<T>::~Array()
{
if (Buffer!=NULL)
{
if (Secure)
cleandata(Buffer,AllocSize*sizeof(T));
free(Buffer);
}
}
template <class T> inline T& Array<T>::operator [](size_t Item) const
{
return Buffer[Item];
}
template <class T> inline T* Array<T>::operator +(size_t Pos)
{
return Buffer+Pos;
}
template <class T> inline size_t Array<T>::Size()
{
return BufSize;
}
template <class T> void Array<T>::Add(size_t Items)
{
BufSize+=Items;
if (BufSize>AllocSize)
{
if (MaxSize!=0 && BufSize>MaxSize)
{
ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize);
ErrHandler.MemoryError();
}
size_t Suggested=AllocSize+AllocSize/4+32;
size_t NewSize=Max(BufSize,Suggested);
T *NewBuffer;
if (Secure)
{
NewBuffer=(T *)malloc(NewSize*sizeof(T));
if (NewBuffer==NULL)
ErrHandler.MemoryError();
if (Buffer!=NULL)
{
memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
cleandata(Buffer,AllocSize*sizeof(T));
free(Buffer);
}
}
else
{
NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
if (NewBuffer==NULL)
ErrHandler.MemoryError();
}
Buffer=NewBuffer;
AllocSize=NewSize;
}
}
template <class T> void Array<T>::Alloc(size_t Items)
{
if (Items>AllocSize)
Add(Items-BufSize);
else
BufSize=Items;
}
template <class T> void Array<T>::Reset()
{
if (Buffer!=NULL)
{
free(Buffer);
Buffer=NULL;
}
BufSize=0;
AllocSize=0;
}
// Reset buffer size, but preserve already allocated memory if any,
// so we can reuse it without wasting time to allocation.
template <class T> void Array<T>::SoftReset()
{
BufSize=0;
}
template <class T> void Array<T>::operator =(Array<T> &Src)
{
Reset();
Alloc(Src.BufSize);
if (Src.BufSize!=0)
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
}
template <class T> void Array<T>::Push(T Item)
{
Add(1);
(*this)[Size()-1]=Item;
}
template <class T> void Array<T>::Append(T *Items,size_t Count)
{
size_t CurSize=Size();
Add(Count);
memcpy(Buffer+CurSize,Items,Count*sizeof(T));
}
#endif

183
reference/unrar/blake2s.cpp Normal file
View File

@@ -0,0 +1,183 @@
// Based on public domain code written in 2012 by Samuel Neves
#include "rar.hpp"
#ifdef USE_SSE
#include "blake2s_sse.cpp"
#endif
static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
static void blake2s_final( blake2s_state *S, byte *digest );
#include "blake2sp.cpp"
static const uint32 blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const byte blake2s_sigma[10][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
static inline void blake2s_set_lastnode( blake2s_state *S )
{
S->f[1] = ~0U;
}
/* Some helper functions, not necessarily useful */
static inline void blake2s_set_lastblock( blake2s_state *S )
{
if( S->last_node ) blake2s_set_lastnode( S );
S->f[0] = ~0U;
}
static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
/* init2 xors IV with input parameter block */
void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
{
#ifdef USE_SSE
if (_SSE_Version>=SSE_SSE2)
blake2s_init_sse();
#endif
S->init(); // Clean data.
for( int i = 0; i < 8; ++i )
S->h[i] = blake2s_IV[i];
S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
S->h[2] ^= node_offset;
S->h[3] ^= (node_depth<<16)|0x20000000;
}
#define G(r,i,m,a,b,c,d) \
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
d = rotr32(d ^ a, 16); \
c = c + d; \
b = rotr32(b ^ c, 12); \
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
d = rotr32(d ^ a, 8); \
c = c + d; \
b = rotr32(b ^ c, 7);
static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
{
uint32 m[16];
uint32 v[16];
for( size_t i = 0; i < 16; ++i )
m[i] = RawGet4( block + i * 4 );
for( size_t i = 0; i < 8; ++i )
v[i] = S->h[i];
v[ 8] = blake2s_IV[0];
v[ 9] = blake2s_IV[1];
v[10] = blake2s_IV[2];
v[11] = blake2s_IV[3];
v[12] = S->t[0] ^ blake2s_IV[4];
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
{
G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
}
for( size_t i = 0; i < 8; ++i )
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
{
while( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
memcpy( S->buf + left, in, fill ); // Fill buffer
S->buflen += fill;
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
#ifdef USE_SSE
#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
if (_SSE_Version>=SSE_SSE2)
#else
if (_SSE_Version>=SSE_SSSE3)
#endif
blake2s_compress_sse( S, S->buf );
else
blake2s_compress( S, S->buf ); // Compress
#else
blake2s_compress( S, S->buf ); // Compress
#endif
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
S->buflen -= BLAKE2S_BLOCKBYTES;
in += fill;
inlen -= fill;
}
else // inlen <= fill
{
memcpy( S->buf + left, in, (size_t)inlen );
S->buflen += (size_t)inlen; // Be lazy, do not compress
in += inlen;
inlen = 0;
}
}
}
void blake2s_final( blake2s_state *S, byte *digest )
{
if( S->buflen > BLAKE2S_BLOCKBYTES )
{
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
blake2s_compress( S, S->buf );
S->buflen -= BLAKE2S_BLOCKBYTES;
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
}
blake2s_increment_counter( S, ( uint32 )S->buflen );
blake2s_set_lastblock( S );
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
blake2s_compress( S, S->buf );
for( int i = 0; i < 8; ++i ) /* Output full hash */
RawPut4( S->h[i], digest + 4 * i );
}

101
reference/unrar/blake2s.hpp Normal file
View File

@@ -0,0 +1,101 @@
// Based on public domain code written in 2012 by Samuel Neves
#ifndef _RAR_BLAKE2_
#define _RAR_BLAKE2_
#define BLAKE2_DIGEST_SIZE 32
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32
};
// Alignment to 64 improves performance of both SSE and non-SSE versions.
// Alignment to n*16 is required for SSE version, so we selected 64.
// We use the custom alignment scheme instead of __declspec(align(x)),
// because it is less compiler dependent. Also the compiler directive
// does not help if structure is a member of class allocated through
// 'new' operator.
struct blake2s_state
{
enum { BLAKE_ALIGNMENT = 64 };
// buffer and uint32 h[8], t[2], f[2];
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
size_t buflen;
byte last_node;
blake2s_state()
{
set_pointers();
}
// Required when we declare and assign in the same command.
blake2s_state(blake2s_state &st)
{
set_pointers();
*this=st;
}
void set_pointers()
{
// Set aligned pointers. Must be done in constructor, not in Init(),
// so assignments like 'blake2sp_state res=blake2ctx' work correctly
// even if blake2sp_init is not called for 'res'.
buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
t = h + 8;
f = t + 2;
}
void init()
{
memset( ubuf, 0, sizeof( ubuf ) );
buflen = 0;
last_node = 0;
}
// Since we use pointers, the default = would work incorrectly.
blake2s_state& operator = (blake2s_state &st)
{
if (this != &st)
{
memcpy(buf, st.buf, BLAKE_DATA_SIZE);
buflen = st.buflen;
last_node = st.last_node;
}
return *this;
}
};
#ifdef RAR_SMP
class ThreadPool;
#endif
struct blake2sp_state
{
blake2s_state S[8];
blake2s_state R;
byte buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
#ifdef RAR_SMP
ThreadPool *ThPool;
uint MaxThreads;
#endif
};
void blake2sp_init( blake2sp_state *S );
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
void blake2sp_final( blake2sp_state *S, byte *digest );
#endif

View File

@@ -0,0 +1,129 @@
// Based on public domain code written in 2012 by Samuel Neves
extern const byte blake2s_sigma[10][16];
// Initialization vector.
static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
#ifdef _WIN_64
// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
static __m128i crotr8, crotr16;
#endif
static void blake2s_init_sse()
{
// We cannot initialize these 128 bit variables in place when declaring
// them globally, because global scope initialization is performed before
// our SSE check and it would make code incompatible with older non-SSE2
// CPUs. Also we cannot initialize them as static inside of function
// using these variables, because SSE static initialization is not thread
// safe: first thread starts initialization and sets "init done" flag even
// if it is not done yet, second thread can attempt to access half-init
// SSE data. So we moved init code here.
blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
#ifdef _WIN_64
crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
#endif
}
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
#ifdef _WIN_32
// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
// to not use _mm_shuffle_epi8 here.
#define mm_rotr_epi32(r, c) ( \
_mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
#else
#define mm_rotr_epi32(r, c) ( \
c==8 ? _mm_shuffle_epi8(r,crotr8) \
: c==16 ? _mm_shuffle_epi8(r,crotr16) \
: _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
#endif
#define G1(row1,row2,row3,row4,buf) \
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
row4 = _mm_xor_si128( row4, row1 ); \
row4 = mm_rotr_epi32(row4, 16); \
row3 = _mm_add_epi32( row3, row4 ); \
row2 = _mm_xor_si128( row2, row3 ); \
row2 = mm_rotr_epi32(row2, 12);
#define G2(row1,row2,row3,row4,buf) \
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
row4 = _mm_xor_si128( row4, row1 ); \
row4 = mm_rotr_epi32(row4, 8); \
row3 = _mm_add_epi32( row3, row4 ); \
row2 = _mm_xor_si128( row2, row3 ); \
row2 = mm_rotr_epi32(row2, 7);
#define DIAGONALIZE(row1,row2,row3,row4) \
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
#define UNDIAGONALIZE(row1,row2,row3,row4) \
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
#ifdef _WIN_64
// MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
// from stack operations, which are slower than this code.
#define _mm_set_epi32(i3,i2,i1,i0) \
_mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
_mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
#endif
// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
// and about the same in x64 mode in our test. Perhaps depends on compiler.
// We also tried _mm_i32gather_epi32 and _mm256_i32gather_epi32 AVX2 gather
// instructions here, but they did not show any speed gain on i7-6700K.
#define SSE_ROUND(m,row,r) \
{ \
__m128i buf; \
buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
G1(row[0],row[1],row[2],row[3],buf); \
buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
G2(row[0],row[1],row[2],row[3],buf); \
DIAGONALIZE(row[0],row[1],row[2],row[3]); \
buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
G1(row[0],row[1],row[2],row[3],buf); \
buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
G2(row[0],row[1],row[2],row[3],buf); \
UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
}
static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
{
__m128i row[4];
__m128i ff0, ff1;
const uint32 *m = ( uint32 * )block;
row[0] = ff0 = LOAD( &S->h[0] );
row[1] = ff1 = LOAD( &S->h[4] );
row[2] = blake2s_IV_0_3;
row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
SSE_ROUND( m, row, 0 );
SSE_ROUND( m, row, 1 );
SSE_ROUND( m, row, 2 );
SSE_ROUND( m, row, 3 );
SSE_ROUND( m, row, 4 );
SSE_ROUND( m, row, 5 );
SSE_ROUND( m, row, 6 );
SSE_ROUND( m, row, 7 );
SSE_ROUND( m, row, 8 );
SSE_ROUND( m, row, 9 );
STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
return 0;
}

View File

@@ -0,0 +1,153 @@
/*
BLAKE2 reference source code package - reference C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#define PARALLELISM_DEGREE 8
void blake2sp_init( blake2sp_state *S )
{
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
blake2s_init_param( &S->R, 0, 1 ); // Init root.
for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
S->R.last_node = 1;
S->S[PARALLELISM_DEGREE - 1].last_node = 1;
}
struct Blake2ThreadData
{
void Update();
blake2s_state *S;
const byte *in;
size_t inlen;
};
void Blake2ThreadData::Update()
{
size_t inlen__ = inlen;
const byte *in__ = ( const byte * )in;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
#ifdef USE_SSE
// We gain 5% in i7 SSE mode by prefetching next data block.
if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
_mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
#endif
blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
}
#ifdef RAR_SMP
THREAD_PROC(Blake2Thread)
{
Blake2ThreadData *td=(Blake2ThreadData *)Data;
td->Update();
}
#endif
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
{
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
in += fill;
inlen -= fill;
left = 0;
}
Blake2ThreadData btd_array[PARALLELISM_DEGREE];
#ifdef RAR_SMP
uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
ThreadNumber=4;
#else
uint ThreadNumber=1;
#endif
for (size_t id__=0;id__<PARALLELISM_DEGREE;)
{
for (uint Thread=0;Thread<ThreadNumber && id__<PARALLELISM_DEGREE;Thread++)
{
Blake2ThreadData *btd=btd_array+Thread;
btd->inlen = inlen;
btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
btd->S = &S->S[id__];
#ifdef RAR_SMP
if (ThreadNumber>1)
S->ThPool->AddTask(Blake2Thread,(void*)btd);
else
btd->Update();
#else
btd->Update();
#endif
id__++;
}
#ifdef RAR_SMP
if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
S->ThPool->WaitDone();
#endif // RAR_SMP
}
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
if( inlen > 0 )
memcpy( S->buf + left, in, (size_t)inlen );
S->buflen = left + (size_t)inlen;
}
void blake2sp_final( blake2sp_state *S, byte *digest )
{
byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
{
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
}
blake2s_final( &S->S[i], hash[i] );
}
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
blake2s_final( &S->R, digest );
}

1400
reference/unrar/cmddata.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
#ifndef _RAR_CMDDATA_
#define _RAR_CMDDATA_
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tgz;xz;z;zip;zipx"
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
class CommandData:public RAROptions
{
private:
void ProcessSwitchesString(const wchar *Str);
void ProcessSwitch(const wchar *Switch);
void BadSwitch(const wchar *Switch);
uint GetExclAttr(const wchar *Str);
bool FileLists;
bool NoMoreSwitches;
RAR_CMD_LIST_MODE ListMode;
bool BareOutput;
public:
CommandData();
void Init();
void ParseCommandLine(bool Preprocess,int argc, char *argv[]);
void ParseArg(wchar *ArgW);
void ParseDone();
void ParseEnvVar();
void ReadConfig();
void PreprocessArg(const wchar *Arg);
void OutTitle();
void OutHelp(RAR_EXIT ExitCode);
bool IsSwitch(int Ch);
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
bool ExclDirByAttr(uint FileAttr);
bool TimeCheck(RarTime &ft);
bool SizeCheck(int64 Size);
bool AnyFiltersActive();
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH,
wchar *MatchedArg=NULL,uint MatchedArgSize=0);
void ProcessCommand();
void AddArcName(const wchar *Name);
bool GetArcName(wchar *Name,int MaxSize);
bool CheckWinSize();
int GetRecoverySize(const wchar *Str,int DefSize);
#ifndef SFX_MODULE
void ReportWrongSwitches(RARFORMAT Format);
#endif
wchar Command[NM+16];
wchar ArcName[NM];
StringList FileArgs;
StringList ExclArgs;
StringList InclArgs;
StringList ArcNames;
StringList StoreArgs;
};
#endif

48
reference/unrar/coder.cpp Normal file
View File

@@ -0,0 +1,48 @@
inline unsigned int RangeCoder::GetChar()
{
return(UnpackRead->GetChar());
}
void RangeCoder::InitDecoder(Unpack *UnpackRead)
{
RangeCoder::UnpackRead=UnpackRead;
low=code=0;
range=uint(-1);
for (int i=0;i < 4;i++)
code=(code << 8) | GetChar();
}
// (int) cast before "low" added only to suppress compiler warnings.
#define ARI_DEC_NORMALIZE(code,low,range,read) \
{ \
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
{ \
code=(code << 8) | read->GetChar(); \
range <<= 8; \
low <<= 8; \
} \
}
inline int RangeCoder::GetCurrentCount()
{
return (code-low)/(range /= SubRange.scale);
}
inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT)
{
return (code-low)/(range >>= SHIFT);
}
inline void RangeCoder::Decode()
{
low += range*SubRange.LowCount;
range *= SubRange.HighCount-SubRange.LowCount;
}

23
reference/unrar/coder.hpp Normal file
View File

@@ -0,0 +1,23 @@
/****************************************************************************
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
****************************************************************************/
class RangeCoder
{
public:
void InitDecoder(Unpack *UnpackRead);
inline int GetCurrentCount();
inline uint GetCurrentShiftCount(uint SHIFT);
inline void Decode();
inline void PutChar(unsigned int c);
inline unsigned int GetChar();
uint low, code, range;
struct SUBRANGE
{
uint LowCount, HighCount, scale;
} SubRange;
Unpack *UnpackRead;
};

View File

@@ -0,0 +1,50 @@
#ifndef _RAR_COMPRESS_
#define _RAR_COMPRESS_
// Combine pack and unpack constants to class to avoid polluting global
// namespace with numerous short names.
class PackDef
{
public:
static const uint MAX_LZ_MATCH = 0x1001;
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
static const uint LOW_DIST_REP_COUNT = 16;
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC = 64;
static const uint LDC = 16;
static const uint RC = 44;
static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
static const uint BC = 20;
static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC30 = 60;
static const uint LDC30 = 17;
static const uint RC30 = 28;
static const uint BC30 = 20;
static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC20 = 48;
static const uint RC20 = 28;
static const uint BC20 = 19;
static const uint MC20 = 257;
// Largest alphabet size among all values listed above.
static const uint LARGEST_TABLE_SIZE = 306;
enum {
CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
};
};
enum FilterType {
// These values must not be changed, because we use them directly
// in RAR5 compression and decompression code.
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
};
#endif

352
reference/unrar/consio.cpp Normal file
View File

@@ -0,0 +1,352 @@
#include "rar.hpp"
#include "log.cpp"
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
static RAR_CHARSET RedirectCharset=RCH_DEFAULT;
const int MaxMsgSize=2*NM+2048;
static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false;
#ifdef _WIN_ALL
static bool IsRedirected(DWORD nStdHandle)
{
HANDLE hStd=GetStdHandle(nStdHandle);
DWORD Mode;
return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
}
#endif
void InitConsole()
{
#ifdef _WIN_ALL
// We want messages like file names or progress percent to be printed
// immediately. Use only in Windows, in Unix they can cause wprintf %ls
// to fail with non-English strings.
setbuf(stdout,NULL);
setbuf(stderr,NULL);
// Detect if output is redirected and set output mode properly.
// We do not want to send Unicode output to files and especially to pipes
// like '|more', which cannot handle them correctly in Windows.
// In Unix console output is UTF-8 and it is handled correctly
// when redirecting, so no need to perform any adjustments.
StdoutRedirected=IsRedirected(STD_OUTPUT_HANDLE);
StderrRedirected=IsRedirected(STD_ERROR_HANDLE);
StdinRedirected=IsRedirected(STD_INPUT_HANDLE);
#ifdef _MSC_VER
if (!StdoutRedirected)
_setmode(_fileno(stdout), _O_U16TEXT);
if (!StderrRedirected)
_setmode(_fileno(stderr), _O_U16TEXT);
#endif
#elif defined(_UNIX)
StdoutRedirected=!isatty(fileno(stdout));
StderrRedirected=!isatty(fileno(stderr));
StdinRedirected=!isatty(fileno(stdin));
#endif
}
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset)
{
::MsgStream=MsgStream;
::RedirectCharset=RedirectCharset;
}
#ifndef SILENT
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
{
// This buffer is for format string only, not for entire output,
// so it can be short enough.
wchar fmtw[1024];
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
#ifdef _WIN_ALL
safebuf wchar Msg[MaxMsgSize];
if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
{
HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
DWORD Written;
if (RedirectCharset==RCH_UNICODE)
WriteFile(hOut,Msg,(DWORD)wcslen(Msg)*sizeof(*Msg),&Written,NULL);
else
{
// Avoid Unicode for redirect in Windows, it does not work with pipes.
safebuf char MsgA[MaxMsgSize];
if (RedirectCharset==RCH_UTF8)
WideToUtf(Msg,MsgA,ASIZE(MsgA));
else
WideToChar(Msg,MsgA,ASIZE(MsgA));
if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM)
CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding.
// We already converted \n to \r\n above, so we use WriteFile instead
// of C library to avoid unnecessary additional conversion.
WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL);
}
return;
}
// MSVC2008 vfwprintf writes every character to console separately
// and it is too slow. We use direct WriteConsole call instead.
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
DWORD Written;
WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL);
#else
vfwprintf(dest,fmtw,arglist);
// We do not use setbuf(NULL) in Unix (see comments in InitConsole).
fflush(dest);
#endif
}
void mprintf(const wchar *fmt,...)
{
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
return;
fflush(stderr); // Ensure proper message order.
va_list arglist;
va_start(arglist,fmt);
FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
cvt_wprintf(dest,fmt,arglist);
va_end(arglist);
}
#endif
#ifndef SILENT
void eprintf(const wchar *fmt,...)
{
if (MsgStream==MSG_NULL)
return;
fflush(stdout); // Ensure proper message order.
va_list arglist;
va_start(arglist,fmt);
cvt_wprintf(stderr,fmt,arglist);
va_end(arglist);
}
#endif
#ifndef SILENT
static void GetPasswordText(wchar *Str,uint MaxLength)
{
if (MaxLength==0)
return;
if (StdinRedirected)
getwstr(Str,MaxLength); // Read from pipe or redirected file.
else
{
#ifdef _WIN_ALL
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
DWORD ConInMode,ConOutMode;
DWORD Read=0;
GetConsoleMode(hConIn,&ConInMode);
GetConsoleMode(hConOut,&ConOutMode);
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
Str[Read]=0;
SetConsoleMode(hConIn,ConInMode);
SetConsoleMode(hConOut,ConOutMode);
#else
char StrA[MAXPASSWORD];
#if defined(_EMX) || defined (__VMS)
fgets(StrA,ASIZE(StrA)-1,stdin);
#elif defined(__sun)
strncpyz(StrA,getpassphrase(""),ASIZE(StrA));
#else
strncpyz(StrA,getpass(""),ASIZE(StrA));
#endif
CharToWide(StrA,Str,MaxLength);
cleandata(StrA,sizeof(StrA));
#endif
}
Str[MaxLength-1]=0;
RemoveLF(Str);
}
#endif
#ifndef SILENT
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
{
if (!StdinRedirected)
uiAlarm(UIALARM_QUESTION);
while (true)
{
if (!StdinRedirected)
if (Type==UIPASSWORD_GLOBAL)
eprintf(L"\n%s: ",St(MAskPsw));
else
eprintf(St(MAskPswFor),FileName);
wchar PlainPsw[MAXPASSWORD];
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL)
return false;
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
{
eprintf(St(MReAskPsw));
wchar CmpStr[MAXPASSWORD];
GetPasswordText(CmpStr,ASIZE(CmpStr));
if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0)
{
eprintf(St(MNotMatchPsw));
cleandata(PlainPsw,sizeof(PlainPsw));
cleandata(CmpStr,sizeof(CmpStr));
continue;
}
cleandata(CmpStr,sizeof(CmpStr));
}
Password->Set(PlainPsw);
cleandata(PlainPsw,sizeof(PlainPsw));
break;
}
return true;
}
#endif
#ifndef SILENT
bool getwstr(wchar *str,size_t n)
{
// Print buffered prompt title function before waiting for input.
fflush(stderr);
*str=0;
#if defined(_WIN_ALL)
// fgetws does not work well with non-English text in Windows,
// so we do not use it.
if (StdinRedirected) // ReadConsole does not work if redirected.
{
// fgets does not work well with pipes in Windows in our test.
// Let's use files.
Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
if (ReadSize<=0)
{
// Looks like stdin is a null device. We can enter to infinite loop
// calling Ask(), so let's better exit.
ErrHandler.Exit(RARX_USERBREAK);
}
StrA[ReadSize]=0;
CharToWide(&StrA[0],str,n);
cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords.
}
else
{
DWORD ReadSize=0;
if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0)
return false;
str[ReadSize]=0;
}
#else
if (fgetws(str,n,stdin)==NULL)
ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop.
#endif
RemoveLF(str);
return true;
}
#endif
#ifndef SILENT
// We allow this function to return 0 in case of invalid input,
// because it might be convenient to press Enter to some not dangerous
// prompts like "insert disk with next volume". We should call this function
// again in case of 0 in dangerous prompt such as overwriting file.
int Ask(const wchar *AskStr)
{
uiAlarm(UIALARM_QUESTION);
const int MaxItems=10;
wchar Item[MaxItems][40];
int ItemKeyPos[MaxItems],NumItems=0;
for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
{
wchar *CurItem=Item[NumItems];
wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
wchar *EndItem=wcschr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;
int KeyPos=0,CurKey;
while ((CurKey=CurItem[KeyPos])!=0)
{
bool Found=false;
for (int I=0;I<NumItems && !Found;I++)
if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
Found=true;
if (!Found && CurKey!=' ')
break;
KeyPos++;
}
ItemKeyPos[NumItems]=KeyPos;
NumItems++;
}
for (int I=0;I<NumItems;I++)
{
eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
int KeyPos=ItemKeyPos[I];
for (int J=0;J<KeyPos;J++)
eprintf(L"%c",Item[I][J]);
eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
}
eprintf(L" ");
wchar Str[50];
getwstr(Str,ASIZE(Str));
wchar Ch=toupperw(Str[0]);
for (int I=0;I<NumItems;I++)
if (Ch==Item[I][ItemKeyPos[I]])
return I+1;
return 0;
}
#endif
static bool IsCommentUnsafe(const wchar *Data,size_t Size)
{
for (size_t I=0;I<Size;I++)
if (Data[I]==27 && Data[I+1]=='[')
for (size_t J=I+2;J<Size;J++)
{
// Return true for <ESC>[{key};"{string}"p used to redefine
// a keyboard key on some terminals.
if (Data[J]=='\"')
return true;
if (!IsDigit(Data[J]) && Data[J]!=';')
break;
}
return false;
}
void OutComment(const wchar *Comment,size_t Size)
{
if (IsCommentUnsafe(Comment,Size))
return;
const size_t MaxOutSize=0x400;
for (size_t I=0;I<Size;I+=MaxOutSize)
{
wchar Msg[MaxOutSize+1];
size_t CopySize=Min(MaxOutSize,Size-I);
wcsncpy(Msg,Comment+I,CopySize);
Msg[CopySize]=0;
mprintf(L"%s",Msg);
}
mprintf(L"\n");
}

View File

@@ -0,0 +1,26 @@
#ifndef _RAR_CONSIO_
#define _RAR_CONSIO_
void InitConsole();
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset);
void OutComment(const wchar *Comment,size_t Size);
#ifndef SILENT
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
#endif
#ifdef SILENT
inline void mprintf(const wchar *fmt,...) {}
inline void eprintf(const wchar *fmt,...) {}
inline void Alarm() {}
inline int Ask(const wchar *AskStr) {return 0;}
inline bool getwstr(wchar *str,size_t n) {return false;}
#else
void mprintf(const wchar *fmt,...);
void eprintf(const wchar *fmt,...);
void Alarm();
int Ask(const wchar *AskStr);
bool getwstr(wchar *str,size_t n);
#endif
#endif

102
reference/unrar/crc.cpp Normal file
View File

@@ -0,0 +1,102 @@
// This CRC function is based on Intel Slicing-by-8 algorithm.
//
// Original Intel Slicing-by-8 code is available here:
//
// http://sourceforge.net/projects/slicing-by-8/
//
// Original Intel Slicing-by-8 code is licensed as:
//
// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
//
// This software program is licensed subject to the BSD License,
// available at http://www.opensource.org/licenses/bsd-license.html
#include "rar.hpp"
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
// Build the classic CRC32 lookup table.
// We also provide this function to legacy RAR and ZIP decryption code.
void InitCRC32(uint *CRCTab)
{
if (CRCTab[1]!=0)
return;
for (uint I=0;I<256;I++)
{
uint C=I;
for (uint J=0;J<8;J++)
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
CRCTab[I]=C;
}
}
static void InitTables()
{
InitCRC32(crc_tables[0]);
for (uint I=0;I<256;I++) // Build additional lookup tables.
{
uint C=crc_tables[0][I];
for (uint J=1;J<8;J++)
{
C=crc_tables[0][(byte)C]^(C>>8);
crc_tables[J][I]=C;
}
}
}
struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
{
byte *Data=(byte *)Addr;
// Align Data to 8 for better performance.
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
for (;Size>=8;Size-=8,Data+=8)
{
#ifdef BIG_ENDIAN
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
#else
StartCRC ^= *(uint32 *) Data;
uint NextData = *(uint32 *) (Data +4);
#endif
StartCRC = crc_tables[7][(byte) StartCRC ] ^
crc_tables[6][(byte)(StartCRC >> 8) ] ^
crc_tables[5][(byte)(StartCRC >> 16)] ^
crc_tables[4][(byte)(StartCRC >> 24)] ^
crc_tables[3][(byte) NextData ] ^
crc_tables[2][(byte)(NextData >>8 ) ] ^
crc_tables[1][(byte)(NextData >> 16)] ^
crc_tables[0][(byte)(NextData >> 24)];
}
for (;Size>0;Size--,Data++) // Process left data.
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
return StartCRC;
}
#ifndef SFX_MODULE
// For RAR 1.4 archives in case somebody still has them.
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
{
byte *Data=(byte *)Addr;
for (size_t I=0;I<Size;I++)
{
StartCRC=(StartCRC+Data[I])&0xffff;
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
}
return StartCRC;
}
#endif

15
reference/unrar/crc.hpp Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _RAR_CRC_
#define _RAR_CRC_
// This function is only to intialize external CRC tables. We do not need to
// call it before calculating CRC32.
void InitCRC32(uint *CRCTab);
uint CRC32(uint StartCRC,const void *Addr,size_t Size);
#ifndef SFX_MODULE
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
#endif
#endif

134
reference/unrar/crypt.cpp Normal file
View File

@@ -0,0 +1,134 @@
#include "rar.hpp"
#ifndef SFX_MODULE
#include "crypt1.cpp"
#include "crypt2.cpp"
#endif
#include "crypt3.cpp"
#include "crypt5.cpp"
CryptData::CryptData()
{
Method=CRYPT_NONE;
memset(KDF3Cache,0,sizeof(KDF3Cache));
memset(KDF5Cache,0,sizeof(KDF5Cache));
KDF3CachePos=0;
KDF5CachePos=0;
memset(CRCTab,0,sizeof(CRCTab));
}
CryptData::~CryptData()
{
cleandata(KDF3Cache,sizeof(KDF3Cache));
cleandata(KDF5Cache,sizeof(KDF5Cache));
}
void CryptData::DecryptBlock(byte *Buf,size_t Size)
{
switch(Method)
{
#ifndef SFX_MODULE
case CRYPT_RAR13:
Decrypt13(Buf,Size);
break;
case CRYPT_RAR15:
Crypt15(Buf,Size);
break;
case CRYPT_RAR20:
for (size_t I=0;I<Size;I+=CRYPT_BLOCK_SIZE)
DecryptBlock20(Buf+I);
break;
#endif
case CRYPT_RAR30:
case CRYPT_RAR50:
rin.blockDecrypt(Buf,Size,Buf);
break;
}
}
bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
SecPassword *Password,const byte *Salt,
const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
{
if (!Password->IsSet() || Method==CRYPT_NONE)
return false;
CryptData::Method=Method;
wchar PwdW[MAXPASSWORD];
Password->Get(PwdW,ASIZE(PwdW));
char PwdA[MAXPASSWORD];
WideToChar(PwdW,PwdA,ASIZE(PwdA));
switch(Method)
{
#ifndef SFX_MODULE
case CRYPT_RAR13:
SetKey13(PwdA);
break;
case CRYPT_RAR15:
SetKey15(PwdA);
break;
case CRYPT_RAR20:
SetKey20(PwdA);
break;
#endif
case CRYPT_RAR30:
SetKey30(Encrypt,Password,PwdW,Salt);
break;
case CRYPT_RAR50:
SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
break;
}
cleandata(PwdA,sizeof(PwdA));
cleandata(PwdW,sizeof(PwdW));
return true;
}
// Use the current system time to additionally randomize data.
static void TimeRandomize(byte *RndBuf,size_t BufSize)
{
static uint Count=0;
RarTime CurTime;
CurTime.SetCurrentTime();
uint64 Random=CurTime.GetWin()+clock();
for (size_t I=0;I<BufSize;I++)
{
byte RndByte = byte (Random >> ( (I & 7) * 8 ));
RndBuf[I]=byte( (RndByte ^ I) + Count++);
}
}
// Fill buffer with random data.
void GetRnd(byte *RndBuf,size_t BufSize)
{
bool Success=false;
#if defined(_WIN_ALL)
HCRYPTPROV hProvider = 0;
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
Success=CryptGenRandom(hProvider, (DWORD)BufSize, RndBuf) == TRUE;
CryptReleaseContext(hProvider, 0);
}
#elif defined(_UNIX)
FILE *rndf = fopen("/dev/urandom", "r");
if (rndf!=NULL)
{
Success=fread(RndBuf, BufSize, 1, rndf) == BufSize;
fclose(rndf);
}
#endif
// We use this code only as the last resort if code above failed.
if (!Success)
TimeRandomize(RndBuf,BufSize);
}

101
reference/unrar/crypt.hpp Normal file
View File

@@ -0,0 +1,101 @@
#ifndef _RAR_CRYPT_
#define _RAR_CRYPT_
enum CRYPT_METHOD {
CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
};
#define SIZE_SALT50 16
#define SIZE_SALT30 8
#define SIZE_INITV 16
#define SIZE_PSWCHECK 8
#define SIZE_PSWCHECK_CSUM 4
#define CRYPT_BLOCK_SIZE 16
#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
#define CRYPT_VERSION 0 // Supported encryption version.
class CryptData
{
struct KDF5CacheItem
{
SecPassword Pwd;
byte Salt[SIZE_SALT50];
byte Key[32];
uint Lg2Count; // Log2 of PBKDF2 repetition count.
byte PswCheckValue[SHA256_DIGEST_SIZE];
byte HashKeyValue[SHA256_DIGEST_SIZE];
};
struct KDF3CacheItem
{
SecPassword Pwd;
byte Salt[SIZE_SALT30];
byte Key[16];
byte Init[16];
bool SaltPresent;
};
private:
void SetKey13(const char *Password);
void Decrypt13(byte *Data,size_t Count);
void SetKey15(const char *Password);
void Crypt15(byte *Data,size_t Count);
void SetKey20(const char *Password);
void Swap20(byte *Ch1,byte *Ch2);
void UpdKeys20(byte *Buf);
void EncryptBlock20(byte *Buf);
void DecryptBlock20(byte *Buf);
void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
KDF3CacheItem KDF3Cache[4];
uint KDF3CachePos;
KDF5CacheItem KDF5Cache[4];
uint KDF5CachePos;
CRYPT_METHOD Method;
Rijndael rin;
uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
byte SubstTable20[256];
uint Key20[4];
byte Key13[3];
ushort Key15[4];
public:
CryptData();
~CryptData();
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
const byte *Salt,const byte *InitV,uint Lg2Cnt,
byte *HashKey,byte *PswCheck);
void SetAV15Encryption();
void SetCmt13Encryption();
void EncryptBlock(byte *Buf,size_t Size);
void DecryptBlock(byte *Buf,size_t Size);
static void SetSalt(byte *Salt,size_t SaltSize);
};
void GetRnd(byte *RndBuf,size_t BufSize);
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
size_t DataLength,byte *ResDigest);
void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
size_t salt_len,byte *key, byte *Value1, byte *Value2,
uint rounds);
void ConvertHashToMAC(HashValue *Value,byte *Key);
#endif

View File

@@ -0,0 +1,79 @@
extern uint CRCTab[256];
void CryptData::SetKey13(const char *Password)
{
Key13[0]=Key13[1]=Key13[2]=0;
for (size_t I=0;Password[I]!=0;I++)
{
byte P=Password[I];
Key13[0]+=P;
Key13[1]^=P;
Key13[2]+=P;
Key13[2]=(byte)rotls(Key13[2],1,8);
}
}
void CryptData::SetKey15(const char *Password)
{
InitCRC32(CRCTab);
uint PswCRC=CRC32(0xffffffff,Password,strlen(Password));
Key15[0]=PswCRC&0xffff;
Key15[1]=(PswCRC>>16)&0xffff;
Key15[2]=Key15[3]=0;
for (size_t I=0;Password[I]!=0;I++)
{
byte P=Password[I];
Key15[2]^=P^CRCTab[P];
Key15[3]+=P+(CRCTab[P]>>16);
}
}
void CryptData::SetAV15Encryption()
{
InitCRC32(CRCTab);
Method=CRYPT_RAR15;
Key15[0]=0x4765;
Key15[1]=0x9021;
Key15[2]=0x7382;
Key15[3]=0x5215;
}
void CryptData::SetCmt13Encryption()
{
Method=CRYPT_RAR13;
Key13[0]=0;
Key13[1]=7;
Key13[2]=77;
}
void CryptData::Decrypt13(byte *Data,size_t Count)
{
while (Count--)
{
Key13[1]+=Key13[2];
Key13[0]+=Key13[1];
*Data-=Key13[0];
Data++;
}
}
void CryptData::Crypt15(byte *Data,size_t Count)
{
while (Count--)
{
Key15[0]+=0x1234;
Key15[1]^=CRCTab[(Key15[0] & 0x1fe)>>1];
Key15[2]-=CRCTab[(Key15[0] & 0x1fe)>>1]>>16;
Key15[0]^=Key15[2];
Key15[3]=rotrs(Key15[3]&0xffff,1,16)^Key15[1];
Key15[3]=rotrs(Key15[3]&0xffff,1,16);
Key15[0]^=Key15[3];
*Data^=(byte)(Key15[0]>>8);
Data++;
}
}

133
reference/unrar/crypt2.cpp Normal file
View File

@@ -0,0 +1,133 @@
#define NROUNDS 32
#define substLong(t) ( (uint)SubstTable20[(uint)t&255] | \
((uint)SubstTable20[(int)(t>> 8)&255]<< 8) | \
((uint)SubstTable20[(int)(t>>16)&255]<<16) | \
((uint)SubstTable20[(int)(t>>24)&255]<<24) )
static byte InitSubstTable20[256]={
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
};
void CryptData::SetKey20(const char *Password)
{
InitCRC32(CRCTab);
char Psw[MAXPASSWORD];
strncpyz(Psw,Password,ASIZE(Psw)); // We'll need to modify it below.
size_t PswLength=strlen(Psw);
Key20[0]=0xD3A3B879L;
Key20[1]=0x3F6D12F7L;
Key20[2]=0x7515A235L;
Key20[3]=0xA4E7F123L;
memcpy(SubstTable20,InitSubstTable20,sizeof(SubstTable20));
for (uint J=0;J<256;J++)
for (size_t I=0;I<PswLength;I+=2)
{
uint N1=(byte)CRCTab [ (byte(Password[I]) - J) &0xff];
uint N2=(byte)CRCTab [ (byte(Password[I+1]) + J) &0xff];
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
Swap20(&SubstTable20[N1],&SubstTable20[(N1+I+K)&0xff]);
}
// Incomplete last block of password must be zero padded.
if ((PswLength & CRYPT_BLOCK_MASK)!=0)
for (size_t I=PswLength;I<=(PswLength|CRYPT_BLOCK_MASK);I++)
Psw[I]=0;
for (size_t I=0;I<PswLength;I+=CRYPT_BLOCK_SIZE)
EncryptBlock20((byte *)Psw+I);
}
void CryptData::EncryptBlock20(byte *Buf)
{
uint A,B,C,D,T,TA,TB;
A=RawGet4(Buf+0)^Key20[0];
B=RawGet4(Buf+4)^Key20[1];
C=RawGet4(Buf+8)^Key20[2];
D=RawGet4(Buf+12)^Key20[3];
for(int I=0;I<NROUNDS;I++)
{
T=((C+rotls(D,11,32))^Key20[I&3]);
TA=A^substLong(T);
T=((D^rotls(C,17,32))+Key20[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
RawPut4(C^Key20[0],Buf+0);
RawPut4(D^Key20[1],Buf+4);
RawPut4(A^Key20[2],Buf+8);
RawPut4(B^Key20[3],Buf+12);
UpdKeys20(Buf);
}
void CryptData::DecryptBlock20(byte *Buf)
{
byte InBuf[16];
uint A,B,C,D,T,TA,TB;
A=RawGet4(Buf+0)^Key20[0];
B=RawGet4(Buf+4)^Key20[1];
C=RawGet4(Buf+8)^Key20[2];
D=RawGet4(Buf+12)^Key20[3];
memcpy(InBuf,Buf,sizeof(InBuf));
for(int I=NROUNDS-1;I>=0;I--)
{
T=((C+rotls(D,11,32))^Key20[I&3]);
TA=A^substLong(T);
T=((D^rotls(C,17,32))+Key20[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
RawPut4(C^Key20[0],Buf+0);
RawPut4(D^Key20[1],Buf+4);
RawPut4(A^Key20[2],Buf+8);
RawPut4(B^Key20[3],Buf+12);
UpdKeys20(InBuf);
}
void CryptData::UpdKeys20(byte *Buf)
{
for (int I=0;I<16;I+=4)
{
Key20[0]^=CRCTab[Buf[I]];
Key20[1]^=CRCTab[Buf[I+1]];
Key20[2]^=CRCTab[Buf[I+2]];
Key20[3]^=CRCTab[Buf[I+3]];
}
}
void CryptData::Swap20(byte *Ch1,byte *Ch2)
{
byte Ch=*Ch1;
*Ch1=*Ch2;
*Ch2=Ch;
}

View File

@@ -0,0 +1,68 @@
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
{
byte AESKey[16],AESInit[16];
bool Cached=false;
for (uint I=0;I<ASIZE(KDF3Cache);I++)
if (KDF3Cache[I].Pwd==*Password &&
(Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
{
memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
SecHideData(AESKey,sizeof(AESKey),false,false);
memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
Cached=true;
break;
}
if (!Cached)
{
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
size_t RawLength=2*wcslen(PwdW);
if (Salt!=NULL)
{
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
RawLength+=SIZE_SALT30;
}
sha1_context c;
sha1_init(&c);
const int HashRounds=0x40000;
for (int I=0;I<HashRounds;I++)
{
sha1_process_rar29( &c, RawPsw, RawLength );
byte PswNum[3];
PswNum[0]=(byte)I;
PswNum[1]=(byte)(I>>8);
PswNum[2]=(byte)(I>>16);
sha1_process(&c, PswNum, 3);
if (I%(HashRounds/16)==0)
{
sha1_context tempc=c;
uint32 digest[5];
sha1_done( &tempc, digest );
AESInit[I/(HashRounds/16)]=(byte)digest[4];
}
}
uint32 digest[5];
sha1_done( &c, digest );
for (int I=0;I<4;I++)
for (int J=0;J<4;J++)
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
KDF3Cache[KDF3CachePos].Pwd=*Password;
if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
SecHideData(KDF3Cache[KDF3CachePos].Key,sizeof(KDF3Cache[KDF3CachePos].Key),true,false);
memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);
cleandata(RawPsw,sizeof(RawPsw));
}
rin.Init(Encrypt, AESKey, 128, AESInit);
cleandata(AESKey,sizeof(AESKey));
cleandata(AESInit,sizeof(AESInit));
}

233
reference/unrar/crypt5.cpp Normal file
View File

@@ -0,0 +1,233 @@
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
size_t DataLength,byte *ResDigest,
sha256_context *ICtxOpt,bool *SetIOpt,
sha256_context *RCtxOpt,bool *SetROpt)
{
const size_t Sha256BlockSize=64; // As defined in RFC 4868.
byte KeyHash[SHA256_DIGEST_SIZE];
if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
{
sha256_context KCtx;
sha256_init(&KCtx);
sha256_process(&KCtx, Key, KeyLength);
sha256_done(&KCtx, KeyHash);
Key = KeyHash;
KeyLength = SHA256_DIGEST_SIZE;
}
byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
sha256_context ICtx;
if (ICtxOpt!=NULL && *SetIOpt)
ICtx=*ICtxOpt; // Use already calculated first block context.
else
{
// This calculation is the same for all iterations with same password.
// So for PBKDF2 we can calculate it only for first block and then reuse
// to improve performance.
for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
KeyBuf[I] = Key[I] ^ 0x36;
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
KeyBuf[I] = 0x36;
sha256_init(&ICtx);
sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
}
if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
{
*ICtxOpt=ICtx;
*SetIOpt=true;
}
sha256_process(&ICtx, Data, DataLength); // Hash data.
byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
sha256_done(&ICtx, IDig);
sha256_context RCtx;
if (RCtxOpt!=NULL && *SetROpt)
RCtx=*RCtxOpt; // Use already calculated first block context.
else
{
// This calculation is the same for all iterations with same password.
// So for PBKDF2 we can calculate it only for first block and then reuse
// to improve performance.
for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
KeyBuf[I] = Key[I] ^ 0x5c;
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
KeyBuf[I] = 0x5c;
sha256_init(&RCtx);
sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
}
if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
{
*RCtxOpt=RCtx;
*SetROpt=true;
}
sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.
sha256_done(&RCtx, ResDigest);
}
// PBKDF2 for 32 byte key length. We generate the key for specified number
// of iteration count also as two supplementary values (key for checksums
// and password verification) for iterations+16 and iterations+32.
void pbkdf2(const byte *Pwd, size_t PwdLength,
const byte *Salt, size_t SaltLength,
byte *Key, byte *V1, byte *V2, uint Count)
{
const size_t MaxSalt=64;
byte SaltData[MaxSalt+4];
memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
SaltData[SaltLength + 1] = 0;
SaltData[SaltLength + 2] = 0;
SaltData[SaltLength + 3] = 1;
// First iteration: HMAC of password, salt and block index (1).
byte U1[SHA256_DIGEST_SIZE];
hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL);
byte Fn[SHA256_DIGEST_SIZE]; // Current function value.
memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration.
uint CurCount[] = { Count-1, 16, 16 };
byte *CurValue[] = { Key , V1, V2 };
sha256_context ICtxOpt,RCtxOpt;
bool SetIOpt=false,SetROpt=false;
byte U2[SHA256_DIGEST_SIZE];
for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values.
{
for (uint J = 0; J < CurCount[I]; J++)
{
// U2 = PRF (P, U1).
hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt);
memcpy(U1, U2, sizeof(U1));
for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U.
Fn[K] ^= U1[K];
}
memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE);
}
cleandata(SaltData, sizeof(SaltData));
cleandata(Fn, sizeof(Fn));
cleandata(U1, sizeof(U1));
cleandata(U2, sizeof(U2));
}
void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,
byte *PswCheck)
{
if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
return;
byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
bool Found=false;
for (uint I=0;I<ASIZE(KDF5Cache);I++)
{
KDF5CacheItem *Item=KDF5Cache+I;
if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
{
memcpy(Key,Item->Key,sizeof(Key));
SecHideData(Key,sizeof(Key),false,false);
memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue));
memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue));
Found=true;
break;
}
}
if (!Found)
{
char PwdUtf[MAXPASSWORD*4];
WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf));
pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt));
cleandata(PwdUtf,sizeof(PwdUtf));
KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache));
Item->Lg2Count=Lg2Cnt;
Item->Pwd=*Password;
memcpy(Item->Salt,Salt,SIZE_SALT50);
memcpy(Item->Key,Key,sizeof(Item->Key));
memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue));
memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue));
SecHideData(Item->Key,sizeof(Item->Key),true,false);
}
if (HashKey!=NULL)
memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE);
if (PswCheck!=NULL)
{
memset(PswCheck,0,SIZE_PSWCHECK);
for (uint I=0;I<SHA256_DIGEST_SIZE;I++)
PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I];
cleandata(PswCheckValue,sizeof(PswCheckValue));
}
// NULL initialization vector is possible if we only need the password
// check value for archive encryption header.
if (InitV!=NULL)
rin.Init(Encrypt, Key, 256, InitV);
cleandata(Key,sizeof(Key));
}
void ConvertHashToMAC(HashValue *Value,byte *Key)
{
if (Value->Type==HASH_CRC32)
{
byte RawCRC[4];
RawPut4(Value->CRC32,RawCRC);
byte Digest[SHA256_DIGEST_SIZE];
hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL);
Value->CRC32=0;
for (uint I=0;I<ASIZE(Digest);I++)
Value->CRC32^=Digest[I] << ((I & 3) * 8);
}
if (Value->Type==HASH_BLAKE2)
{
byte Digest[BLAKE2_DIGEST_SIZE];
hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL);
memcpy(Value->Digest,Digest,sizeof(Value->Digest));
}
}
#if 0
static void TestPBKDF2();
struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
void TestPBKDF2() // Test PBKDF2 HMAC-SHA256
{
byte Key[32],V1[32],V2[32];
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1);
byte Res1[32]={0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b };
mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed");
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096);
byte Res2[32]={0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a };
mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed");
pbkdf2((byte *)"just some long string pretending to be a password", 49, (byte *)"salt, salt, salt, a lot of salt", 31, Key, V1, V2, 65536);
byte Res3[32]={0x08, 0x0f, 0xa3, 0x1d, 0x42, 0x2d, 0xb0, 0x47, 0x83, 0x9b, 0xce, 0x3a, 0x3b, 0xce, 0x49, 0x51, 0xe2, 0x62, 0xb9, 0xff, 0x76, 0x2f, 0x57, 0xe9, 0xc4, 0x71, 0x96, 0xce, 0x4b, 0x6b, 0x6e, 0xbf};
mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed");
}
#endif

474
reference/unrar/dll.cpp Normal file
View File

@@ -0,0 +1,474 @@
#include "rar.hpp"
static int RarErrorToDll(RAR_EXIT ErrCode);
struct DataSet
{
CommandData Cmd;
Archive Arc;
CmdExtract Extract;
int OpenMode;
int HeaderSize;
DataSet():Arc(&Cmd),Extract(&Cmd) {};
};
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
{
RAROpenArchiveDataEx rx;
memset(&rx,0,sizeof(rx));
rx.ArcName=r->ArcName;
rx.OpenMode=r->OpenMode;
rx.CmtBuf=r->CmtBuf;
rx.CmtBufSize=r->CmtBufSize;
HANDLE hArc=RAROpenArchiveEx(&rx);
r->OpenResult=rx.OpenResult;
r->CmtSize=rx.CmtSize;
r->CmtState=rx.CmtState;
return hArc;
}
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
{
DataSet *Data=NULL;
try
{
r->OpenResult=0;
Data=new DataSet;
Data->Cmd.DllError=0;
Data->OpenMode=r->OpenMode;
Data->Cmd.FileArgs.AddString(L"*");
char AnsiArcName[NM];
*AnsiArcName=0;
if (r->ArcName!=NULL)
{
strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
#ifdef _WIN_ALL
if (!AreFileApisANSI())
{
OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
AnsiArcName[ASIZE(AnsiArcName)-1]=0;
}
#endif
}
wchar ArcName[NM];
GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
Data->Cmd.AddArcName(ArcName);
Data->Cmd.Overwrite=OVERWRITE_ALL;
Data->Cmd.VersionControl=1;
Data->Cmd.Callback=r->Callback;
Data->Cmd.UserData=r->UserData;
// Open shared mode is added by request of dll users, who need to
// browse and unpack archives while downloading.
Data->Cmd.OpenShared = true;
if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
{
r->OpenResult=ERAR_EOPEN;
delete Data;
return NULL;
}
if (!Data->Arc.IsArchive(true))
{
if (Data->Cmd.DllError!=0)
r->OpenResult=Data->Cmd.DllError;
else
{
RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
r->OpenResult=RarErrorToDll(ErrCode);
else
r->OpenResult=ERAR_BAD_ARCHIVE;
}
delete Data;
return NULL;
}
r->Flags=0;
if (Data->Arc.Volume)
r->Flags|=0x01;
if (Data->Arc.Locked)
r->Flags|=0x04;
if (Data->Arc.Solid)
r->Flags|=0x08;
if (Data->Arc.NewNumbering)
r->Flags|=0x10;
if (Data->Arc.Signed)
r->Flags|=0x20;
if (Data->Arc.Protected)
r->Flags|=0x40;
if (Data->Arc.Encrypted)
r->Flags|=0x80;
if (Data->Arc.FirstVolume)
r->Flags|=0x100;
Array<wchar> CmtDataW;
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
{
Array<char> CmtData(CmtDataW.Size()*4+1);
memset(&CmtData[0],0,CmtData.Size());
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
size_t Size=strlen(&CmtData[0])+1;
r->Flags|=2;
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
if (Size<=r->CmtBufSize)
r->CmtBuf[r->CmtSize-1]=0;
}
else
r->CmtState=r->CmtSize=0;
Data->Extract.ExtractArchiveInit(Data->Arc);
return (HANDLE)Data;
}
catch (RAR_EXIT ErrCode)
{
if (Data!=NULL && Data->Cmd.DllError!=0)
r->OpenResult=Data->Cmd.DllError;
else
r->OpenResult=RarErrorToDll(ErrCode);
if (Data != NULL)
delete Data;
return NULL;
}
catch (std::bad_alloc&) // Catch 'new' exception.
{
r->OpenResult=ERAR_NO_MEMORY;
if (Data != NULL)
delete Data;
}
return NULL; // To make compilers happy.
}
int PASCAL RARCloseArchive(HANDLE hArcData)
{
DataSet *Data=(DataSet *)hArcData;
bool Success=Data==NULL ? false:Data->Arc.Close();
delete Data;
return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
}
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
{
struct RARHeaderDataEx X;
memset(&X,0,sizeof(X));
int Code=RARReadHeaderEx(hArcData,&X);
strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
D->Flags=X.Flags;
D->PackSize=X.PackSize;
D->UnpSize=X.UnpSize;
D->HostOS=X.HostOS;
D->FileCRC=X.FileCRC;
D->FileTime=X.FileTime;
D->UnpVer=X.UnpVer;
D->Method=X.Method;
D->FileAttr=X.FileAttr;
D->CmtSize=0;
D->CmtState=0;
return Code;
}
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
{
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
Data->Arc.EndArcHead.NextVolume)
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return RARReadHeaderEx(hArcData,D);
}
else
return ERAR_EOPEN;
if (Data->Arc.BrokenHeader)
return ERAR_BAD_DATA;
// Might be necessary if RARSetPassword is still called instead of
// open callback for RAR5 archives and if password is invalid.
if (Data->Arc.FailedHeaderDecryption)
return ERAR_BAD_PASSWORD;
return ERAR_END_ARCHIVE;
}
FileHeader *hd=&Data->Arc.FileHead;
if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
{
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
if (Code==0)
return RARReadHeaderEx(hArcData,D);
else
return Code;
}
wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
#ifdef _WIN_ALL
CharToOemA(D->FileName,D->FileName);
#endif
D->Flags=0;
if (hd->SplitBefore)
D->Flags|=RHDF_SPLITBEFORE;
if (hd->SplitAfter)
D->Flags|=RHDF_SPLITAFTER;
if (hd->Encrypted)
D->Flags|=RHDF_ENCRYPTED;
if (hd->Solid)
D->Flags|=RHDF_SOLID;
if (hd->Dir)
D->Flags|=RHDF_DIRECTORY;
D->PackSize=uint(hd->PackSize & 0xffffffff);
D->PackSizeHigh=uint(hd->PackSize>>32);
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
D->UnpSizeHigh=uint(hd->UnpSize>>32);
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
if (Data->Arc.Format==RARFMT50)
D->UnpVer=Data->Arc.FileHead.UnpVer==0 ? 50 : 200; // If it is not 0, just set it to something big.
else
D->UnpVer=Data->Arc.FileHead.UnpVer;
D->FileCRC=hd->FileHash.CRC32;
D->FileTime=hd->mtime.GetDos();
uint64 MRaw=hd->mtime.GetWin();
D->MtimeLow=(uint)MRaw;
D->MtimeHigh=(uint)(MRaw>>32);
uint64 CRaw=hd->ctime.GetWin();
D->CtimeLow=(uint)CRaw;
D->CtimeHigh=(uint)(CRaw>>32);
uint64 ARaw=hd->atime.GetWin();
D->AtimeLow=(uint)ARaw;
D->AtimeHigh=(uint)(ARaw>>32);
D->Method=hd->Method+0x30;
D->FileAttr=hd->FileAttr;
D->CmtSize=0;
D->CmtState=0;
D->DictSize=uint(hd->WinSize/1024);
switch (hd->FileHash.Type)
{
case HASH_RAR14:
case HASH_CRC32:
D->HashType=RAR_HASH_CRC32;
break;
case HASH_BLAKE2:
D->HashType=RAR_HASH_BLAKE2;
memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
break;
default:
D->HashType=RAR_HASH_NONE;
break;
}
D->RedirType=hd->RedirType;
// RedirNameSize sanity check is useful in case some developer
// did not initialize Reserved area with 0 as required in docs.
// We have taken 'Redir*' fields from Reserved area. We may remove
// this RedirNameSize check sometimes later.
if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
D->RedirNameSize>0 && D->RedirNameSize<100000)
wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
D->DirTarget=hd->DirTarget;
}
catch (RAR_EXIT ErrCode)
{
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
}
return ERAR_SUCCESS;
}
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
{
DataSet *Data=(DataSet *)hArcData;
try
{
Data->Cmd.DllError=0;
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
Operation==RAR_SKIP && !Data->Arc.Solid)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
Data->Arc.FileHead.SplitAfter)
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return ERAR_SUCCESS;
}
else
return ERAR_EOPEN;
Data->Arc.SeekToNext();
}
else
{
Data->Cmd.DllOpMode=Operation;
*Data->Cmd.ExtrPath=0;
*Data->Cmd.DllDestName=0;
if (DestPath!=NULL)
{
char ExtrPathA[NM];
strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
#ifdef _WIN_ALL
// We must not apply OemToCharBuffA directly to DestPath,
// because we do not know DestPath length and OemToCharBuffA
// does not stop at 0.
OemToCharA(ExtrPathA,ExtrPathA);
#endif
CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
}
if (DestName!=NULL)
{
char DestNameA[NM];
strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
#ifdef _WIN_ALL
// We must not apply OemToCharBuffA directly to DestName,
// because we do not know DestName length and OemToCharBuffA
// does not stop at 0.
OemToCharA(DestNameA,DestNameA);
#endif
CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
}
if (DestPathW!=NULL)
{
wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
}
if (DestNameW!=NULL)
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T");
Data->Cmd.Test=Operation!=RAR_EXTRACT;
bool Repeat=false;
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
// Now we process extra file information if any.
//
// Archive can be closed if we process volumes, next volume is missing
// and current one is already removed or deleted. So we need to check
// if archive is still open to avoid calling file operations on
// the invalid file handle. Some of our file operations like Seek()
// process such invalid handle correctly, some not.
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
Data->Arc.GetHeaderType()==HEAD_SERVICE)
{
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
Data->Arc.SeekToNext();
}
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
}
}
catch (std::bad_alloc&)
{
return ERAR_NO_MEMORY;
}
catch (RAR_EXIT ErrCode)
{
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
}
return Data->Cmd.DllError;
}
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
{
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
}
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
{
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
}
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.ChangeVolProc=ChangeVolProc;
}
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.Callback=Callback;
Data->Cmd.UserData=UserData;
}
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.ProcessDataProc=ProcessDataProc;
}
#ifndef RAR_NOCRYPT
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
{
DataSet *Data=(DataSet *)hArcData;
wchar PasswordW[MAXPASSWORD];
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
Data->Cmd.Password.Set(PasswordW);
cleandata(PasswordW,sizeof(PasswordW));
}
#endif
int PASCAL RARGetDllVersion()
{
return RAR_DLL_VERSION;
}
static int RarErrorToDll(RAR_EXIT ErrCode)
{
switch(ErrCode)
{
case RARX_FATAL:
return ERAR_EREAD;
case RARX_CRC:
return ERAR_BAD_DATA;
case RARX_WRITE:
return ERAR_EWRITE;
case RARX_OPEN:
return ERAR_EOPEN;
case RARX_CREATE:
return ERAR_ECREATE;
case RARX_MEMORY:
return ERAR_NO_MEMORY;
case RARX_BADPWD:
return ERAR_BAD_PASSWORD;
case RARX_SUCCESS:
return ERAR_SUCCESS; // 0.
default:
return ERAR_UNKNOWN;
}
}

12
reference/unrar/dll.def Normal file
View File

@@ -0,0 +1,12 @@
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion

185
reference/unrar/dll.hpp Normal file
View File

@@ -0,0 +1,185 @@
#ifndef _UNRAR_DLL_
#define _UNRAR_DLL_
#pragma pack(1)
#define ERAR_SUCCESS 0
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_MISSING_PASSWORD 22
#define ERAR_EREFERENCE 23
#define ERAR_BAD_PASSWORD 24
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_OM_LIST_INCSPLIT 2
#define RAR_SKIP 0
#define RAR_TEST 1
#define RAR_EXTRACT 2
#define RAR_VOL_ASK 0
#define RAR_VOL_NOTIFY 1
#define RAR_DLL_VERSION 8
#define RAR_HASH_NONE 0
#define RAR_HASH_CRC32 1
#define RAR_HASH_BLAKE2 2
#ifdef _UNIX
#define CALLBACK
#define PASCAL
#define LONG long
#define HANDLE void *
#define LPARAM long
#define UINT unsigned int
#endif
#define RHDF_SPLITBEFORE 0x01
#define RHDF_SPLITAFTER 0x02
#define RHDF_ENCRYPTED 0x04
#define RHDF_SOLID 0x10
#define RHDF_DIRECTORY 0x20
struct RARHeaderData
{
char ArcName[260];
char FileName[260];
unsigned int Flags;
unsigned int PackSize;
unsigned int UnpSize;
unsigned int HostOS;
unsigned int FileCRC;
unsigned int FileTime;
unsigned int UnpVer;
unsigned int Method;
unsigned int FileAttr;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
};
struct RARHeaderDataEx
{
char ArcName[1024];
wchar_t ArcNameW[1024];
char FileName[1024];
wchar_t FileNameW[1024];
unsigned int Flags;
unsigned int PackSize;
unsigned int PackSizeHigh;
unsigned int UnpSize;
unsigned int UnpSizeHigh;
unsigned int HostOS;
unsigned int FileCRC;
unsigned int FileTime;
unsigned int UnpVer;
unsigned int Method;
unsigned int FileAttr;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int DictSize;
unsigned int HashType;
char Hash[32];
unsigned int RedirType;
wchar_t *RedirName;
unsigned int RedirNameSize;
unsigned int DirTarget;
unsigned int MtimeLow;
unsigned int MtimeHigh;
unsigned int CtimeLow;
unsigned int CtimeHigh;
unsigned int AtimeLow;
unsigned int AtimeHigh;
unsigned int Reserved[988];
};
struct RAROpenArchiveData
{
char *ArcName;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
#define ROADF_VOLUME 0x0001
#define ROADF_COMMENT 0x0002
#define ROADF_LOCK 0x0004
#define ROADF_SOLID 0x0008
#define ROADF_NEWNUMBERING 0x0010
#define ROADF_SIGNED 0x0020
#define ROADF_RECOVERY 0x0040
#define ROADF_ENCHEADERS 0x0080
#define ROADF_FIRSTVOLUME 0x0100
struct RAROpenArchiveDataEx
{
char *ArcName;
wchar_t *ArcNameW;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Flags;
UNRARCALLBACK Callback;
LPARAM UserData;
unsigned int Reserved[28];
};
enum UNRARCALLBACK_MESSAGES {
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
UCM_NEEDPASSWORDW
};
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
#ifdef __cplusplus
extern "C" {
#endif
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
int PASCAL RARCloseArchive(HANDLE hArcData);
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
int PASCAL RARGetDllVersion();
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

28
reference/unrar/dll.rc Normal file
View File

@@ -0,0 +1,28 @@
#include <windows.h>
#include <commctrl.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 5, 50, 100, 2418
PRODUCTVERSION 5, 50, 100, 2418
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
VALUE "FileVersion", "5.50.0\0"
VALUE "ProductVersion", "5.50.0\0"
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2017\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04E4
}
}

View File

@@ -0,0 +1,69 @@
#include "rar.hpp"
EncodeFileName::EncodeFileName()
{
Flags=0;
FlagBits=0;
FlagsPos=0;
DestSize=0;
}
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
size_t MaxDecSize)
{
size_t EncPos=0,DecPos=0;
byte HighByte=EncPos<EncSize ? EncName[EncPos++] : 0;
while (EncPos<EncSize && DecPos<MaxDecSize)
{
if (FlagBits==0)
{
if (EncPos>=EncSize)
break;
Flags=EncName[EncPos++];
FlagBits=8;
}
switch(Flags>>6)
{
case 0:
if (EncPos>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos++];
break;
case 1:
if (EncPos>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8);
break;
case 2:
if (EncPos+1>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8);
EncPos+=2;
break;
case 3:
{
if (EncPos>=EncSize)
break;
int Length=EncName[EncPos++];
if ((Length & 0x80)!=0)
{
if (EncPos>=EncSize)
break;
byte Correction=EncName[EncPos++];
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8);
}
else
for (Length+=2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=Name[DecPos];
}
break;
}
Flags<<=2;
FlagBits-=2;
}
NameW[DecPos<MaxDecSize ? DecPos:MaxDecSize-1]=0;
}

View File

@@ -0,0 +1,20 @@
#ifndef _RAR_ENCNAME_
#define _RAR_ENCNAME_
class EncodeFileName
{
private:
void AddFlags(int Value);
byte *EncName;
byte Flags;
uint FlagBits;
size_t FlagsPos;
size_t DestSize;
public:
EncodeFileName();
size_t Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
};
#endif

391
reference/unrar/errhnd.cpp Normal file
View File

@@ -0,0 +1,391 @@
#include "rar.hpp"
ErrorHandler::ErrorHandler()
{
Clean();
}
void ErrorHandler::Clean()
{
ExitCode=RARX_SUCCESS;
ErrCount=0;
EnableBreak=true;
Silent=false;
UserBreak=false;
MainExit=false;
DisableShutdown=false;
}
void ErrorHandler::MemoryError()
{
MemoryErrorMsg();
Exit(RARX_MEMORY);
}
void ErrorHandler::OpenError(const wchar *FileName)
{
#ifndef SILENT
OpenErrorMsg(FileName);
Exit(RARX_OPEN);
#endif
}
void ErrorHandler::CloseError(const wchar *FileName)
{
if (!UserBreak)
{
uiMsg(UIERROR_FILECLOSE,FileName);
SysErrMsg();
}
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_FATAL);
#endif
}
void ErrorHandler::ReadError(const wchar *FileName)
{
#ifndef SILENT
ReadErrorMsg(FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_FATAL);
#endif
}
bool ErrorHandler::AskRepeatRead(const wchar *FileName)
{
#if !defined(SILENT) && !defined(SFX_MODULE)
if (!Silent)
{
SysErrMsg();
bool Repeat=uiAskRepeatRead(FileName);
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
DisableShutdown=true;
return Repeat;
}
#endif
return false;
}
void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName)
{
#ifndef SILENT
WriteErrorMsg(ArcName,FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_WRITE);
#endif
}
#ifdef _WIN_ALL
void ErrorHandler::WriteErrorFAT(const wchar *FileName)
{
SysErrMsg();
uiMsg(UIERROR_NTFSREQUIRED,FileName);
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
Exit(RARX_WRITE);
#endif
}
#endif
bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull)
{
#ifndef SILENT
if (!Silent)
{
// We do not display "repeat write" prompt in Android, so we do not
// need the matching system error message.
SysErrMsg();
bool Repeat=uiAskRepeatWrite(FileName,DiskFull);
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
DisableShutdown=true;
return Repeat;
}
#endif
return false;
}
void ErrorHandler::SeekError(const wchar *FileName)
{
if (!UserBreak)
{
uiMsg(UIERROR_FILESEEK,FileName);
SysErrMsg();
}
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_FATAL);
#endif
}
void ErrorHandler::GeneralErrMsg(const wchar *fmt,...)
{
va_list arglist;
va_start(arglist,fmt);
wchar Msg[1024];
vswprintf(Msg,ASIZE(Msg),fmt,arglist);
uiMsg(UIERROR_GENERALERRMSG,Msg);
SysErrMsg();
va_end(arglist);
}
void ErrorHandler::MemoryErrorMsg()
{
uiMsg(UIERROR_MEMORY);
SetErrorCode(RARX_MEMORY);
}
void ErrorHandler::OpenErrorMsg(const wchar *FileName)
{
OpenErrorMsg(NULL,FileName);
}
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
SysErrMsg();
SetErrorCode(RARX_OPEN);
}
void ErrorHandler::CreateErrorMsg(const wchar *FileName)
{
CreateErrorMsg(NULL,FileName);
}
void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_FILECREATE,ArcName,FileName);
SysErrMsg();
SetErrorCode(RARX_CREATE);
}
void ErrorHandler::ReadErrorMsg(const wchar *FileName)
{
ReadErrorMsg(NULL,FileName);
}
void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_FILEREAD,ArcName,FileName);
SysErrMsg();
SetErrorCode(RARX_FATAL);
}
void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_FILEWRITE,ArcName,FileName);
SysErrMsg();
SetErrorCode(RARX_WRITE);
}
void ErrorHandler::ArcBrokenMsg(const wchar *ArcName)
{
uiMsg(UIERROR_ARCBROKEN,ArcName);
SetErrorCode(RARX_CRC);
}
void ErrorHandler::ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_CHECKSUM,ArcName,FileName);
SetErrorCode(RARX_CRC);
}
void ErrorHandler::UnknownMethodMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_UNKNOWNMETHOD,ArcName,FileName);
ErrHandler.SetErrorCode(RARX_FATAL);
}
void ErrorHandler::Exit(RAR_EXIT ExitCode)
{
uiAlarm(UIALARM_ERROR);
Throw(ExitCode);
}
void ErrorHandler::SetErrorCode(RAR_EXIT Code)
{
switch(Code)
{
case RARX_WARNING:
case RARX_USERBREAK:
if (ExitCode==RARX_SUCCESS)
ExitCode=Code;
break;
case RARX_CRC:
if (ExitCode!=RARX_BADPWD)
ExitCode=Code;
break;
case RARX_FATAL:
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
ExitCode=RARX_FATAL;
break;
default:
ExitCode=Code;
break;
}
ErrCount++;
}
#ifdef _WIN_ALL
BOOL __stdcall ProcessSignal(DWORD SigType)
#else
#if defined(__sun)
extern "C"
#endif
void _stdfunction ProcessSignal(int SigType)
#endif
{
#ifdef _WIN_ALL
// When a console application is run as a service, this allows the service
// to continue running after the user logs off.
if (SigType==CTRL_LOGOFF_EVENT)
return TRUE;
#endif
ErrHandler.UserBreak=true;
mprintf(St(MBreak));
#ifdef _WIN_ALL
// Let the main thread to handle 'throw' and destroy file objects.
for (uint I=0;!ErrHandler.MainExit && I<50;I++)
Sleep(100);
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(RARDLL)
ExtRes.UnloadDLL();
#endif
exit(RARX_USERBREAK);
#endif
#ifdef _UNIX
static uint BreakCount=0;
// User continues to press Ctrl+C, exit immediately without cleanup.
if (++BreakCount>1)
exit(RARX_USERBREAK);
// Otherwise return from signal handler and let Wait() function to close
// files and quit. We cannot use the same approach as in Windows,
// because Unix signal handler can block execution of our main code.
#endif
#if defined(_WIN_ALL) && !defined(_MSC_VER)
// never reached, just to avoid a compiler warning
return TRUE;
#endif
}
void ErrorHandler::SetSignalHandlers(bool Enable)
{
EnableBreak=Enable;
#ifdef _WIN_ALL
SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE);
#else
signal(SIGINT,Enable ? ProcessSignal:SIG_IGN);
signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN);
#endif
}
void ErrorHandler::Throw(RAR_EXIT Code)
{
if (Code==RARX_USERBREAK && !EnableBreak)
return;
#if !defined(SILENT)
// Do not write "aborted" when just displaying online help.
if (Code!=RARX_SUCCESS && Code!=RARX_USERERROR)
mprintf(L"\n%s\n",St(MProgAborted));
#endif
SetErrorCode(Code);
throw Code;
}
void ErrorHandler::SysErrMsg()
{
#if !defined(SFX_MODULE) && !defined(SILENT)
#ifdef _WIN_ALL
wchar *lpMsgBuf=NULL;
int ErrType=GetLastError();
if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,0,NULL))
{
wchar *CurMsg=lpMsgBuf;
while (CurMsg!=NULL)
{
while (*CurMsg=='\r' || *CurMsg=='\n')
CurMsg++;
if (*CurMsg==0)
break;
wchar *EndMsg=wcschr(CurMsg,'\r');
if (EndMsg==NULL)
EndMsg=wcschr(CurMsg,'\n');
if (EndMsg!=NULL)
{
*EndMsg=0;
EndMsg++;
}
uiMsg(UIERROR_SYSERRMSG,CurMsg);
CurMsg=EndMsg;
}
}
LocalFree( lpMsgBuf );
#endif
#if defined(_UNIX) || defined(_EMX)
if (errno!=0)
{
char *err=strerror(errno);
if (err!=NULL)
{
wchar Msg[1024];
CharToWide(err,Msg,ASIZE(Msg));
uiMsg(UIERROR_SYSERRMSG,Msg);
}
}
#endif
#endif
}
int ErrorHandler::GetSystemErrorCode()
{
#ifdef _WIN_ALL
return GetLastError();
#else
return errno;
#endif
}
void ErrorHandler::SetSystemErrorCode(int Code)
{
#ifdef _WIN_ALL
SetLastError(Code);
#else
errno=Code;
#endif
}

View File

@@ -0,0 +1,70 @@
#ifndef _RAR_ERRHANDLER_
#define _RAR_ERRHANDLER_
enum RAR_EXIT // RAR exit code.
{
RARX_SUCCESS = 0,
RARX_WARNING = 1,
RARX_FATAL = 2,
RARX_CRC = 3,
RARX_LOCK = 4,
RARX_WRITE = 5,
RARX_OPEN = 6,
RARX_USERERROR = 7,
RARX_MEMORY = 8,
RARX_CREATE = 9,
RARX_NOFILES = 10,
RARX_BADPWD = 11,
RARX_USERBREAK = 255
};
class ErrorHandler
{
private:
RAR_EXIT ExitCode;
uint ErrCount;
bool EnableBreak;
bool Silent;
bool DisableShutdown; // Shutdown is not suitable after last error.
public:
ErrorHandler();
void Clean();
void MemoryError();
void OpenError(const wchar *FileName);
void CloseError(const wchar *FileName);
void ReadError(const wchar *FileName);
bool AskRepeatRead(const wchar *FileName);
void WriteError(const wchar *ArcName,const wchar *FileName);
void WriteErrorFAT(const wchar *FileName);
bool AskRepeatWrite(const wchar *FileName,bool DiskFull);
void SeekError(const wchar *FileName);
void GeneralErrMsg(const wchar *fmt,...);
void MemoryErrorMsg();
void OpenErrorMsg(const wchar *FileName);
void OpenErrorMsg(const wchar *ArcName,const wchar *FileName);
void CreateErrorMsg(const wchar *FileName);
void CreateErrorMsg(const wchar *ArcName,const wchar *FileName);
void ReadErrorMsg(const wchar *FileName);
void ReadErrorMsg(const wchar *ArcName,const wchar *FileName);
void WriteErrorMsg(const wchar *ArcName,const wchar *FileName);
void ArcBrokenMsg(const wchar *ArcName);
void ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName);
void UnknownMethodMsg(const wchar *ArcName,const wchar *FileName);
void Exit(RAR_EXIT ExitCode);
void SetErrorCode(RAR_EXIT Code);
RAR_EXIT GetErrorCode() {return ExitCode;}
uint GetErrorCount() {return ErrCount;}
void SetSignalHandlers(bool Enable);
void Throw(RAR_EXIT Code);
void SetSilent(bool Mode) {Silent=Mode;};
void SysErrMsg();
int GetSystemErrorCode();
void SetSystemErrorCode(int Code);
bool IsShutdownEnabled() {return !DisableShutdown;}
bool UserBreak; // Ctrl+Break is pressed.
bool MainExit; // main() is completed.
};
#endif

178
reference/unrar/extinfo.cpp Normal file
View File

@@ -0,0 +1,178 @@
#include "rar.hpp"
#include "hardlinks.cpp"
#include "win32stm.cpp"
#ifdef _WIN_ALL
#include "win32acl.cpp"
#include "win32lnk.cpp"
#endif
#ifdef _UNIX
#include "uowners.cpp"
#ifdef SAVE_LINKS
#include "ulinks.cpp"
#endif
#endif
// RAR2 service header extra records.
#ifndef SFX_MODULE
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
{
if (Cmd->Test)
return;
switch(Arc.SubBlockHead.SubType)
{
#ifdef _UNIX
case UO_HEAD:
if (Cmd->ProcessOwners)
ExtractUnixOwner20(Arc,Name);
break;
#endif
#ifdef _WIN_ALL
case NTACL_HEAD:
if (Cmd->ProcessOwners)
ExtractACL20(Arc,Name);
break;
case STREAM_HEAD:
ExtractStreams20(Arc,Name);
break;
#endif
}
}
#endif
// RAR3 and RAR5 service header extra records.
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name)
{
#ifdef _UNIX
if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwner30(Arc,Name);
#endif
#ifdef _WIN_ALL
if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
ExtractACL(Arc,Name);
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
ExtractStreams(Arc,Name,Cmd->Test);
#endif
}
// Extra data stored directly in file header.
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name)
{
#ifdef _UNIX
if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
SetUnixOwner(Arc,Name);
#endif
}
// Calculate a number of path components except \. and \..
static int CalcAllowedDepth(const wchar *Name)
{
int AllowedDepth=0;
while (*Name!=0)
{
if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
{
bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
if (!Dot && !Dot2)
AllowedDepth++;
}
Name++;
}
return AllowedDepth;
}
// Check if all existing path components are directories and not links.
static bool LinkInPath(const wchar *Name)
{
wchar Path[NM];
if (wcslen(Name)>=ASIZE(Path))
return true; // It should not be that long, skip.
wcsncpyz(Path,Name,ASIZE(Path));
for (wchar *s=Path+wcslen(Path)-1;s>Path;s--)
if (IsPathDiv(*s))
{
*s=0;
FindData FD;
if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir))
return true;
}
return false;
}
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
{
// Catch root dir based /path/file paths also as stuff like \\?\.
// Do not check PrepSrcName here, it can be root based if destination path
// is a root based.
if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
return false;
// Number of ".." in link target.
int UpLevels=0;
for (int Pos=0;*TargetName!=0;Pos++)
{
bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' &&
(IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
(Pos==0 || IsPathDiv(*(TargetName-1)));
if (Dot2)
UpLevels++;
TargetName++;
}
// If link target includes "..", it must not have another links
// in the path, because they can bypass our safety check. For example,
// suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next
// or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next.
if (UpLevels>0 && LinkInPath(PrepSrcName))
return false;
// We could check just prepared src name, but for extra safety
// we check both original (as from archive header) and prepared
// (after applying the destination path and -ep switches) names.
int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.
// Remove the destination path from prepared name if any. We should not
// count the destination path depth, because the link target must point
// inside of this path, not outside of it.
size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
{
PrepSrcName+=ExtrPathLength;
while (IsPathDiv(*PrepSrcName))
PrepSrcName++;
}
int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
}
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
{
#if defined(SAVE_LINKS) && defined(_UNIX)
// For RAR 3.x archives we process links even in test mode to skip link data.
if (Arc.Format==RARFMT15)
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
if (Arc.Format==RARFMT50)
return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
#elif defined _WIN_ALL
// RAR 5.0 archives store link information in file header, so there is
// no need to additionally test it if we do not create a file.
if (Arc.Format==RARFMT50)
return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead);
#endif
return false;
}

View File

@@ -0,0 +1,23 @@
#ifndef _RAR_EXTINFO_
#define _RAR_EXTINFO_
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName);
#ifdef _UNIX
void SetUnixOwner(Archive &Arc,const wchar *FileName);
#endif
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize);
#ifdef _WIN_ALL
bool SetPrivilege(LPCTSTR PrivName);
#endif
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name);
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name);
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name);
#endif

1167
reference/unrar/extract.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
#ifndef _RAR_EXTRACT_
#define _RAR_EXTRACT_
enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
class CmdExtract
{
private:
EXTRACT_ARC_CODE ExtractArchive();
bool ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize);
#ifdef RARDLL
bool ExtrDllGetPassword();
#else
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd);
#endif
void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName);
bool ExtrCreateFile(Archive &Arc,File &CurFile);
bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
RarTime StartTime; // time when extraction started
CommandData *Cmd;
ComprDataIO DataIO;
Unpack *Unp;
unsigned long TotalFileCount;
unsigned long FileCount;
unsigned long MatchedArgs;
bool FirstFile;
bool AllMatchesExact;
bool ReconstructDone;
// If any non-zero solid file was successfully unpacked before current.
// If true and if current encrypted file is broken, obviously
// the password is correct and we can report broken CRC without
// any wrong password hints.
bool AnySolidDataUnpackedWell;
wchar ArcName[NM];
bool PasswordAll;
bool PrevProcessed; // If previous file was successfully extracted or tested.
wchar DestFileName[NM];
bool PasswordCancelled;
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
bool Fat32,NotFat32;
#endif
public:
CmdExtract(CommandData *Cmd);
~CmdExtract();
void DoExtract();
void ExtractArchiveInit(Archive &Arc);
bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
};
#endif

View File

@@ -0,0 +1,163 @@
#include "rar.hpp"
// If NewFile==NULL, we delete created file after user confirmation.
// It is useful we we need to overwrite an existing folder or file,
// but need user confirmation for that.
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
{
if (UserReject!=NULL)
*UserReject=false;
#ifdef _WIN_ALL
bool ShortNameChanged=false;
#endif
while (FileExist(Name))
{
#if defined(_WIN_ALL)
if (!ShortNameChanged)
{
// Avoid the infinite loop if UpdateExistingShortName returns
// the same name.
ShortNameChanged=true;
// Maybe our long name matches the short name of existing file.
// Let's check if we can change the short name.
if (UpdateExistingShortName(Name))
continue;
}
// Allow short name check again. It is necessary, because rename and
// autorename below can change the name, so we need to check it again.
ShortNameChanged=false;
#endif
UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0));
if (Choice==UIASKREP_R_REPLACE)
break;
if (Choice==UIASKREP_R_SKIP)
{
if (UserReject!=NULL)
*UserReject=true;
return false;
}
if (Choice==UIASKREP_R_CANCEL)
ErrHandler.Exit(RARX_USERBREAK);
}
// Try to truncate the existing file first instead of delete,
// so we preserve existing file permissions such as NTFS permissions.
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
if (NewFile!=NULL && NewFile->Create(Name,FileMode))
return true;
CreatePath(Name,true);
return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name);
}
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize)
{
wchar NewName[NM];
size_t NameLength=wcslen(Name);
wchar *Ext=GetExt(Name);
if (Ext==NULL)
Ext=Name+NameLength;
for (uint FileVer=1;;FileVer++)
{
swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext);
if (!FileExist(NewName))
{
wcsncpyz(Name,NewName,MaxNameSize);
break;
}
if (FileVer>=1000000)
return false;
}
return true;
}
#if defined(_WIN_ALL)
// If we find a file, which short name is equal to 'Name', we try to change
// its short name, while preserving the long name. It helps when unpacking
// an archived file, which long name is equal to short name of already
// existing file. Otherwise we would overwrite the already existing file,
// even though its long name does not match the name of unpacking file.
bool UpdateExistingShortName(const wchar *Name)
{
wchar LongPathName[NM];
DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName));
if (Res==0 || Res>=ASIZE(LongPathName))
return false;
wchar ShortPathName[NM];
Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName));
if (Res==0 || Res>=ASIZE(ShortPathName))
return false;
wchar *LongName=PointToName(LongPathName);
wchar *ShortName=PointToName(ShortPathName);
// We continue only if file has a short name, which does not match its
// long name, and this short name is equal to name of file which we need
// to create.
if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
wcsicomp(PointToName(Name),ShortName)!=0)
return false;
// Generate the temporary new name for existing file.
wchar NewName[NM];
*NewName=0;
for (int I=0;I<10000 && *NewName==0;I+=123)
{
// Here we copy the path part of file to create. We'll make the temporary
// file in the same folder.
wcsncpyz(NewName,Name,ASIZE(NewName));
// Here we set the random name part.
swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
// If such file is already exist, try next random name.
if (FileExist(NewName))
*NewName=0;
}
// If we could not generate the name not used by any other file, we return.
if (*NewName==0)
return false;
// FastFind returns the name without path, but we need the fully qualified
// name for renaming, so we use the path from file to create and long name
// from existing file.
wchar FullName[NM];
wcsncpyz(FullName,Name,ASIZE(FullName));
SetName(FullName,LongName,ASIZE(FullName));
// Rename the existing file to randomly generated name. Normally it changes
// the short name too.
if (!MoveFile(FullName,NewName))
return false;
// Now we need to create the temporary empty file with same name as
// short name of our already existing file. We do it to occupy its previous
// short name and not allow to use it again when renaming the file back to
// its original long name.
File KeepShortFile;
bool Created=false;
if (!FileExist(Name))
Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
// Now we rename the existing file from temporary name to original long name.
// Since its previous short name is occupied by another file, it should
// get another short name.
MoveFile(NewName,FullName);
if (Created)
{
// Delete the temporary zero length file occupying the short name,
KeepShortFile.Close();
KeepShortFile.Delete();
}
// We successfully changed the short name. Maybe sometimes we'll simplify
// this function by use of SetFileShortName Windows API call.
// But SetFileShortName is not available in older Windows.
return true;
}
#endif

View File

@@ -0,0 +1,14 @@
#ifndef _RAR_FILECREATE_
#define _RAR_FILECREATE_
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
bool *UserReject,int64 FileSize=INT64NDF,
RarTime *FileTime=NULL,bool WriteOnly=false);
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize);
#if defined(_WIN_ALL)
bool UpdateExistingShortName(const wchar *Name);
#endif
#endif

729
reference/unrar/file.cpp Normal file
View File

@@ -0,0 +1,729 @@
#include "rar.hpp"
File::File()
{
hFile=FILE_BAD_HANDLE;
*FileName=0;
NewFile=false;
LastWrite=false;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
IgnoreReadErrors=false;
ErrorType=FILE_SUCCESS;
OpenShared=false;
AllowDelete=true;
AllowExceptions=true;
#ifdef _WIN_ALL
NoSequentialRead=false;
CreateMode=FMF_UNDEFINED;
#endif
}
File::~File()
{
if (hFile!=FILE_BAD_HANDLE && !SkipClose)
if (NewFile)
Delete();
else
Close();
}
void File::operator = (File &SrcFile)
{
hFile=SrcFile.hFile;
NewFile=SrcFile.NewFile;
LastWrite=SrcFile.LastWrite;
HandleType=SrcFile.HandleType;
wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName));
SrcFile.SkipClose=true;
}
bool File::Open(const wchar *Name,uint Mode)
{
ErrorType=FILE_SUCCESS;
FileHandle hNewFile;
bool OpenShared=File::OpenShared || (Mode & FMF_OPENSHARED)!=0;
bool UpdateMode=(Mode & FMF_UPDATE)!=0;
bool WriteMode=(Mode & FMF_WRITE)!=0;
#ifdef _WIN_ALL
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
if (UpdateMode)
Access|=GENERIC_WRITE;
uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
if (OpenShared)
ShareMode|=FILE_SHARE_WRITE;
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
DWORD LastError;
if (hNewFile==FILE_BAD_HANDLE)
{
LastError=GetLastError();
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
{
hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
// For archive names longer than 260 characters first CreateFile
// (without \\?\) fails and sets LastError to 3 (access denied).
// We need the correct "file not found" error code to decide
// if we create a new archive or quit with "cannot create" error.
// So we need to check the error code after \\?\ CreateFile again,
// otherwise we'll fail to create new archives with long names.
// But we cannot simply assign the new code to LastError,
// because it would break "..\arcname.rar" relative names processing.
// First CreateFile returns the correct "file not found" code for such
// names, but "\\?\" CreateFile returns ERROR_INVALID_NAME treating
// dots as a directory name. So we check only for "file not found"
// error here and for other errors use the first CreateFile result.
if (GetLastError()==ERROR_FILE_NOT_FOUND)
LastError=ERROR_FILE_NOT_FOUND;
}
}
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
ErrorType=FILE_NOTFOUND;
#else
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
#ifdef O_BINARY
flags|=O_BINARY;
#if defined(_AIX) && defined(_LARGE_FILE_API)
flags|=O_LARGEFILE;
#endif
#endif
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
int handle=open(NameA,flags);
#ifdef LOCK_EX
#ifdef _OSF_SOURCE
extern "C" int flock(int, int);
#endif
if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
{
close(handle);
return false;
}
#endif
if (handle==-1)
hNewFile=FILE_BAD_HANDLE;
else
{
#ifdef FILE_USE_OPEN
hNewFile=handle;
#else
hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
#endif
}
if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT)
ErrorType=FILE_NOTFOUND;
#endif
NewFile=false;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
bool Success=hNewFile!=FILE_BAD_HANDLE;
if (Success)
{
hFile=hNewFile;
wcsncpyz(FileName,Name,ASIZE(FileName));
}
return Success;
}
#if !defined(SFX_MODULE)
void File::TOpen(const wchar *Name)
{
if (!WOpen(Name))
ErrHandler.Exit(RARX_OPEN);
}
#endif
bool File::WOpen(const wchar *Name)
{
if (Open(Name))
return true;
ErrHandler.OpenErrorMsg(Name);
return false;
}
bool File::Create(const wchar *Name,uint Mode)
{
// OpenIndiana based NAS and CIFS shares fail to set the file time if file
// was created in read+write mode and some data was written and not flushed
// before SetFileTime call. So we should use the write only mode if we plan
// SetFileTime call and do not need to read from file.
bool WriteMode=(Mode & FMF_WRITE)!=0;
bool ShareRead=(Mode & FMF_SHAREREAD)!=0 || File::OpenShared;
#ifdef _WIN_ALL
CreateMode=Mode;
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
// Windows automatically removes dots and spaces in the end of file name,
// So we detect such names and process them with \\?\ prefix.
wchar *LastChar=PointToLastChar(Name);
bool Special=*LastChar=='.' || *LastChar==' ';
if (Special && (Mode & FMF_STANDARDNAMES)==0)
hFile=FILE_BAD_HANDLE;
else
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
if (hFile==FILE_BAD_HANDLE)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
hFile=CreateFile(LongName,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
}
#else
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
#ifdef FILE_USE_OPEN
hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR),0666);
#else
hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY);
#endif
#endif
NewFile=true;
HandleType=FILE_HANDLENORMAL;
SkipClose=false;
wcsncpyz(FileName,Name,ASIZE(FileName));
return hFile!=FILE_BAD_HANDLE;
}
#if !defined(SFX_MODULE)
void File::TCreate(const wchar *Name,uint Mode)
{
if (!WCreate(Name,Mode))
ErrHandler.Exit(RARX_FATAL);
}
#endif
bool File::WCreate(const wchar *Name,uint Mode)
{
if (Create(Name,Mode))
return true;
ErrHandler.CreateErrorMsg(Name);
return false;
}
bool File::Close()
{
bool Success=true;
if (hFile!=FILE_BAD_HANDLE)
{
if (!SkipClose)
{
#ifdef _WIN_ALL
// We use the standard system handle for stdout in Windows
// and it must not be closed here.
if (HandleType==FILE_HANDLENORMAL)
Success=CloseHandle(hFile)==TRUE;
#else
#ifdef FILE_USE_OPEN
Success=close(hFile)!=-1;
#else
Success=fclose(hFile)!=EOF;
#endif
#endif
}
hFile=FILE_BAD_HANDLE;
}
HandleType=FILE_HANDLENORMAL;
if (!Success && AllowExceptions)
ErrHandler.CloseError(FileName);
return Success;
}
bool File::Delete()
{
if (HandleType!=FILE_HANDLENORMAL)
return false;
if (hFile!=FILE_BAD_HANDLE)
Close();
if (!AllowDelete)
return false;
return DelFile(FileName);
}
bool File::Rename(const wchar *NewName)
{
// No need to rename if names are already same.
bool Success=wcscmp(FileName,NewName)==0;
if (!Success)
Success=RenameFile(FileName,NewName);
if (Success)
wcscpy(FileName,NewName);
return Success;
}
bool File::Write(const void *Data,size_t Size)
{
if (Size==0)
return true;
if (HandleType==FILE_HANDLESTD)
{
#ifdef _WIN_ALL
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
#else
// Cannot use the standard stdout here, because it already has wide orientation.
if (hFile==FILE_BAD_HANDLE)
{
#ifdef FILE_USE_OPEN
hFile=dup(STDOUT_FILENO); // Open new stdout stream.
#else
hFile=fdopen(dup(STDOUT_FILENO),"w"); // Open new stdout stream.
#endif
}
#endif
}
bool Success;
while (1)
{
Success=false;
#ifdef _WIN_ALL
DWORD Written=0;
if (HandleType!=FILE_HANDLENORMAL)
{
// writing to stdout can fail in old Windows if data block is too large
const size_t MaxSize=0x4000;
for (size_t I=0;I<Size;I+=MaxSize)
{
Success=WriteFile(hFile,(byte *)Data+I,(DWORD)Min(Size-I,MaxSize),&Written,NULL)==TRUE;
if (!Success)
break;
}
}
else
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
#else
#ifdef FILE_USE_OPEN
ssize_t Written=write(hFile,Data,Size);
Success=Written==Size;
#else
int Written=fwrite(Data,1,Size,hFile);
Success=Written==Size && !ferror(hFile);
#endif
#endif
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
{
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(RARDLL)
int ErrCode=GetLastError();
int64 FilePos=Tell();
uint64 FreeSize=GetFreeDisk(FileName);
SetLastError(ErrCode);
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
ErrHandler.WriteErrorFAT(FileName);
#endif
if (ErrHandler.AskRepeatWrite(FileName,false))
{
#if !defined(_WIN_ALL) && !defined(FILE_USE_OPEN)
clearerr(hFile);
#endif
if (Written<Size && Written>0)
Seek(Tell()-Written,SEEK_SET);
continue;
}
ErrHandler.WriteError(NULL,FileName);
}
break;
}
LastWrite=true;
return Success; // It can return false only if AllowExceptions is disabled.
}
int File::Read(void *Data,size_t Size)
{
int64 FilePos=0; // Initialized only to suppress some compilers warning.
if (IgnoreReadErrors)
FilePos=Tell();
int ReadSize;
while (true)
{
ReadSize=DirectRead(Data,Size);
if (ReadSize==-1)
{
ErrorType=FILE_READERROR;
if (AllowExceptions)
if (IgnoreReadErrors)
{
ReadSize=0;
for (size_t I=0;I<Size;I+=512)
{
Seek(FilePos+I,SEEK_SET);
size_t SizeToRead=Min(Size-I,512);
int ReadCode=DirectRead(Data,SizeToRead);
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
}
}
else
{
if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
continue;
ErrHandler.ReadError(FileName);
}
}
break;
}
return ReadSize;
}
// Returns -1 in case of error.
int File::DirectRead(void *Data,size_t Size)
{
#ifdef _WIN_ALL
const size_t MaxDeviceRead=20000;
const size_t MaxLockedRead=32768;
#endif
if (HandleType==FILE_HANDLESTD)
{
#ifdef _WIN_ALL
// if (Size>MaxDeviceRead)
// Size=MaxDeviceRead;
hFile=GetStdHandle(STD_INPUT_HANDLE);
#else
#ifdef FILE_USE_OPEN
hFile=STDIN_FILENO;
#else
hFile=stdin;
#endif
#endif
}
#ifdef _WIN_ALL
// For pipes like 'type file.txt | rar -si arcname' ReadFile may return
// data in small ~4KB blocks. It may slightly reduce the compression ratio.
DWORD Read;
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
{
if (IsDevice() && Size>MaxDeviceRead)
return DirectRead(Data,MaxDeviceRead);
if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
return 0;
// We had a bug report about failure to archive 1C database lock file
// 1Cv8tmp.1CL, which is a zero length file with a region above 200 KB
// permanently locked. If our first read request uses too large buffer
// and if we are in -dh mode, so we were able to open the file,
// we'll fail with "Read error". So now we use try a smaller buffer size
// in case of lock error.
if (HandleType==FILE_HANDLENORMAL && Size>MaxLockedRead &&
GetLastError()==ERROR_LOCK_VIOLATION)
return DirectRead(Data,MaxLockedRead);
return -1;
}
return Read;
#else
#ifdef FILE_USE_OPEN
ssize_t ReadSize=read(hFile,Data,Size);
if (ReadSize==-1)
return -1;
return (int)ReadSize;
#else
if (LastWrite)
{
fflush(hFile);
LastWrite=false;
}
clearerr(hFile);
size_t ReadSize=fread(Data,1,Size,hFile);
if (ferror(hFile))
return -1;
return (int)ReadSize;
#endif
#endif
}
void File::Seek(int64 Offset,int Method)
{
if (!RawSeek(Offset,Method) && AllowExceptions)
ErrHandler.SeekError(FileName);
}
bool File::RawSeek(int64 Offset,int Method)
{
if (hFile==FILE_BAD_HANDLE)
return true;
if (Offset<0 && Method!=SEEK_SET)
{
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
Method=SEEK_SET;
}
#ifdef _WIN_ALL
LONG HighDist=(LONG)(Offset>>32);
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
GetLastError()!=NO_ERROR)
return false;
#else
LastWrite=false;
#ifdef FILE_USE_OPEN
if (lseek(hFile,(off_t)Offset,Method)==-1)
return false;
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
if (fseeko(hFile,Offset,Method)!=0)
return false;
#else
if (fseek(hFile,(long)Offset,Method)!=0)
return false;
#endif
#endif
return true;
}
int64 File::Tell()
{
if (hFile==FILE_BAD_HANDLE)
if (AllowExceptions)
ErrHandler.SeekError(FileName);
else
return -1;
#ifdef _WIN_ALL
LONG HighDist=0;
uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
if (AllowExceptions)
ErrHandler.SeekError(FileName);
else
return -1;
return INT32TO64(HighDist,LowDist);
#else
#ifdef FILE_USE_OPEN
return lseek(hFile,0,SEEK_CUR);
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
return ftello(hFile);
#else
return ftell(hFile);
#endif
#endif
}
void File::Prealloc(int64 Size)
{
#ifdef _WIN_ALL
if (RawSeek(Size,SEEK_SET))
{
Truncate();
Seek(0,SEEK_SET);
}
#endif
#if defined(_UNIX) && defined(USE_FALLOCATE)
// fallocate is rather new call. Only latest kernels support it.
// So we are not using it by default yet.
int fd = GetFD();
if (fd >= 0)
fallocate(fd, 0, 0, Size);
#endif
}
byte File::GetByte()
{
byte Byte=0;
Read(&Byte,1);
return Byte;
}
void File::PutByte(byte Byte)
{
Write(&Byte,1);
}
bool File::Truncate()
{
#ifdef _WIN_ALL
return SetEndOfFile(hFile)==TRUE;
#else
return ftruncate(GetFD(),(off_t)Tell())==0;
#endif
}
void File::Flush()
{
#ifdef _WIN_ALL
FlushFileBuffers(hFile);
#else
#ifndef FILE_USE_OPEN
fflush(hFile);
#endif
fsync(GetFD());
#endif
}
void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
{
#ifdef _WIN_ALL
// Workaround for OpenIndiana NAS time bug. If we cannot create a file
// in write only mode, we need to flush the write buffer before calling
// SetFileTime or file time will not be changed.
if (CreateMode!=FMF_UNDEFINED && (CreateMode & FMF_WRITE)==0)
FlushFileBuffers(hFile);
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
FILETIME fm,fc,fa;
if (sm)
ftm->GetWinFT(&fm);
if (sc)
ftc->GetWinFT(&fc);
if (sa)
fta->GetWinFT(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
#endif
}
void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
{
// Android APP_PLATFORM := android-14 does not support futimens and futimes.
// Newer platforms support futimens, but fail on Android 4.2.
// We have to use utime for Android.
// Also we noticed futimens fail to set timestamps on NTFS partition
// mounted to virtual Linux x86 machine, but utimensat worked correctly.
// So we set timestamps for already closed files in Unix.
#ifdef _UNIX
SetCloseFileTimeByName(FileName,ftm,fta);
#endif
}
void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta)
{
#ifdef _UNIX
bool setm=ftm!=NULL && ftm->IsSet();
bool seta=fta!=NULL && fta->IsSet();
if (setm || seta)
{
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
#ifdef UNIX_TIME_NS
timespec times[2];
times[0].tv_sec=seta ? fta->GetUnix() : 0;
times[0].tv_nsec=seta ? long(fta->GetUnixNS()%1000000000) : UTIME_NOW;
times[1].tv_sec=setm ? ftm->GetUnix() : 0;
times[1].tv_nsec=setm ? long(ftm->GetUnixNS()%1000000000) : UTIME_NOW;
utimensat(AT_FDCWD,NameA,times,0);
#else
utimbuf ut;
if (setm)
ut.modtime=ftm->GetUnix();
else
ut.modtime=fta->GetUnix(); // Need to set something, cannot left it 0.
if (seta)
ut.actime=fta->GetUnix();
else
ut.actime=ut.modtime; // Need to set something, cannot left it 0.
utime(NameA,&ut);
#endif
}
#endif
}
void File::GetOpenFileTime(RarTime *ft)
{
#ifdef _WIN_ALL
FILETIME FileTime;
GetFileTime(hFile,NULL,NULL,&FileTime);
ft->SetWinFT(&FileTime);
#endif
#if defined(_UNIX) || defined(_EMX)
struct stat st;
fstat(GetFD(),&st);
ft->SetUnix(st.st_mtime);
#endif
}
int64 File::FileLength()
{
SaveFilePos SavePos(*this);
Seek(0,SEEK_END);
return Tell();
}
bool File::IsDevice()
{
if (hFile==FILE_BAD_HANDLE)
return false;
#ifdef _WIN_ALL
uint Type=GetFileType(hFile);
return Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE;
#else
return isatty(GetFD());
#endif
}
#ifndef SFX_MODULE
int64 File::Copy(File &Dest,int64 Length)
{
Array<char> Buffer(0x40000);
int64 CopySize=0;
bool CopyAll=(Length==INT64NDF);
while (CopyAll || Length>0)
{
Wait();
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
char *Buf=&Buffer[0];
int ReadSize=Read(Buf,SizeToRead);
if (ReadSize==0)
break;
size_t WriteSize=ReadSize;
#ifdef _WIN_ALL
// For FAT32 USB flash drives in Windows if first write is 4 KB or more,
// write caching is disabled and "write through" is enabled, resulting
// in bad performance, especially for many small files. It happens when
// we create SFX archive on USB drive, because SFX module is written first.
// So we split the first write to small 1 KB followed by rest of data.
if (CopySize==0 && WriteSize>=4096)
{
const size_t FirstWrite=1024;
Dest.Write(Buf,FirstWrite);
Buf+=FirstWrite;
WriteSize-=FirstWrite;
}
#endif
Dest.Write(Buf,WriteSize);
CopySize+=ReadSize;
if (!CopyAll)
Length-=ReadSize;
}
return CopySize;
}
#endif

126
reference/unrar/file.hpp Normal file
View File

@@ -0,0 +1,126 @@
#ifndef _RAR_FILE_
#define _RAR_FILE_
#define FILE_USE_OPEN
#ifdef _WIN_ALL
typedef HANDLE FileHandle;
#define FILE_BAD_HANDLE INVALID_HANDLE_VALUE
#elif defined(FILE_USE_OPEN)
typedef off_t FileHandle;
#define FILE_BAD_HANDLE -1
#else
typedef FILE* FileHandle;
#define FILE_BAD_HANDLE NULL
#endif
class RAROptions;
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD};
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
enum FILE_MODE_FLAGS {
// Request read only access to file. Default for Open.
FMF_READ=0,
// Request both read and write access to file. Default for Create.
FMF_UPDATE=1,
// Request write only access to file.
FMF_WRITE=2,
// Open files which are already opened for write by other programs.
FMF_OPENSHARED=4,
// Open files only if no other program is opened it even in shared mode.
FMF_OPENEXCLUSIVE=8,
// Provide read access to created file for other programs.
FMF_SHAREREAD=16,
// Use standard NTFS names without trailing dots and spaces.
FMF_STANDARDNAMES=32,
// Mode flags are not defined yet.
FMF_UNDEFINED=256
};
class File
{
private:
FileHandle hFile;
bool LastWrite;
FILE_HANDLETYPE HandleType;
bool SkipClose;
bool IgnoreReadErrors;
bool NewFile;
bool AllowDelete;
bool AllowExceptions;
#ifdef _WIN_ALL
bool NoSequentialRead;
uint CreateMode;
#endif
protected:
bool OpenShared; // Set by 'Archive' class.
public:
wchar FileName[NM];
FILE_ERRORTYPE ErrorType;
public:
File();
virtual ~File();
void operator = (File &SrcFile);
virtual bool Open(const wchar *Name,uint Mode=FMF_READ);
void TOpen(const wchar *Name);
bool WOpen(const wchar *Name);
bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool Close();
bool Delete();
bool Rename(const wchar *NewName);
bool Write(const void *Data,size_t Size);
virtual int Read(void *Data,size_t Size);
int DirectRead(void *Data,size_t Size);
virtual void Seek(int64 Offset,int Method);
bool RawSeek(int64 Offset,int Method);
virtual int64 Tell();
void Prealloc(int64 Size);
byte GetByte();
void PutByte(byte Byte);
bool Truncate();
void Flush();
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
void GetOpenFileTime(RarTime *ft);
bool IsOpened() {return hFile!=FILE_BAD_HANDLE;};
int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
FILE_HANDLETYPE GetHandleType() {return HandleType;}
bool IsDevice();
static bool RemoveCreated();
FileHandle GetHandle() {return hFile;}
void SetHandle(FileHandle Handle) {Close();hFile=Handle;}
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}
int64 Copy(File &Dest,int64 Length=INT64NDF);
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
#ifdef _WIN_ALL
void RemoveSequentialFlag() {NoSequentialRead=true;}
#endif
#ifdef _UNIX
int GetFD()
{
#ifdef FILE_USE_OPEN
return hFile;
#else
return fileno(hFile);
#endif
}
#endif
};
#endif

510
reference/unrar/filefn.cpp Normal file
View File

@@ -0,0 +1,510 @@
#include "rar.hpp"
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
{
#ifdef _WIN_ALL
// Windows automatically removes dots and spaces in the end of directory
// name. So we detect such names and process them with \\?\ prefix.
wchar *LastChar=PointToLastChar(Name);
bool Special=*LastChar=='.' || *LastChar==' ';
BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
if (RetCode==0 && !FileExist(Name))
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
RetCode=CreateDirectory(LongName,NULL);
}
if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
{
if (SetAttr)
SetFileAttr(Name,Attr);
return MKDIR_SUCCESS;
}
int ErrCode=GetLastError();
if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
return MKDIR_BADPATH;
return MKDIR_ERROR;
#elif defined(_UNIX)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
int ErrCode=mkdir(NameA,uattr);
if (ErrCode==-1)
return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
return MKDIR_SUCCESS;
#else
return MKDIR_ERROR;
#endif
}
bool CreatePath(const wchar *Path,bool SkipLastName)
{
if (Path==NULL || *Path==0)
return false;
#if defined(_WIN_ALL) || defined(_EMX)
uint DirAttr=0;
#else
uint DirAttr=0777;
#endif
bool Success=true;
for (const wchar *s=Path;*s!=0;s++)
{
wchar DirName[NM];
if (s-Path>=ASIZE(DirName))
break;
// Process all kinds of path separators, so user can enter Unix style
// path in Windows or Windows in Unix. s>Path check avoids attempting
// creating an empty directory for paths starting from path separator.
if (IsPathDiv(*s) && s>Path)
{
#ifdef _WIN_ALL
// We must not attempt to create "D:" directory, because first
// CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
// to create "D:" directory.
if (s==Path+2 && Path[1]==':')
continue;
#endif
wcsncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
if (Success)
{
mprintf(St(MCreatDir),DirName);
mprintf(L" %s",St(MOk));
}
}
}
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
return Success;
}
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
{
#if defined(_WIN_ALL)
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
uint DirAttr=GetFileAttr(Name);
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
if (ResetAttr)
SetFileAttr(Name,0);
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
}
if (hFile==INVALID_HANDLE_VALUE)
return;
FILETIME fm,fc,fa;
if (sm)
ftm->GetWinFT(&fm);
if (sc)
ftc->GetWinFT(&fc);
if (sa)
fta->GetWinFT(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
CloseHandle(hFile);
if (ResetAttr)
SetFileAttr(Name,DirAttr);
#endif
#if defined(_UNIX) || defined(_EMX)
File::SetCloseFileTimeByName(Name,ftm,fta);
#endif
}
bool IsRemovable(const wchar *Name)
{
#if defined(_WIN_ALL)
wchar Root[NM];
GetPathRoot(Name,Root,ASIZE(Root));
int Type=GetDriveType(*Root!=0 ? Root:NULL);
return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
#else
return false;
#endif
}
#ifndef SFX_MODULE
int64 GetFreeDisk(const wchar *Name)
{
#ifdef _WIN_ALL
wchar Root[NM];
GetFilePath(Name,Root,ASIZE(Root));
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
return 0;
#elif defined(_UNIX)
wchar Root[NM];
GetFilePath(Name,Root,ASIZE(Root));
char RootA[NM];
WideToChar(Root,RootA,ASIZE(RootA));
struct statvfs sfs;
if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
return 0;
int64 FreeSize=sfs.f_bsize;
FreeSize=FreeSize*sfs.f_bavail;
return FreeSize;
#else
return 0;
#endif
}
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
// Return 'true' for FAT and FAT32, so we can adjust the maximum supported
// file size to 4 GB for these file systems.
bool IsFAT(const wchar *Name)
{
wchar Root[NM];
GetPathRoot(Name,Root,ASIZE(Root));
wchar FileSystem[MAX_PATH+1];
if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
return false;
}
#endif
bool FileExist(const wchar *Name)
{
#ifdef _WIN_ALL
return GetFileAttr(Name)!=0xffffffff;
#elif defined(ENABLE_ACCESS)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
return access(NameA,0)==0;
#else
FindData FD;
return FindFile::FastFind(Name,&FD);
#endif
}
bool WildFileExist(const wchar *Name)
{
if (IsWildcard(Name))
{
FindFile Find;
Find.SetMask(Name);
FindData fd;
return Find.Next(&fd);
}
return FileExist(Name);
}
bool IsDir(uint Attr)
{
#ifdef _WIN_ALL
return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
#endif
#if defined(_UNIX)
return (Attr & 0xF000)==0x4000;
#endif
}
bool IsUnreadable(uint Attr)
{
#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
#endif
return false;
}
bool IsLink(uint Attr)
{
#ifdef _UNIX
return (Attr & 0xF000)==0xA000;
#elif defined(_WIN_ALL)
return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
#else
return false;
#endif
}
bool IsDeleteAllowed(uint FileAttr)
{
#ifdef _WIN_ALL
return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
#else
return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
#endif
}
void PrepareToDelete(const wchar *Name)
{
#if defined(_WIN_ALL) || defined(_EMX)
SetFileAttr(Name,0);
#endif
#ifdef _UNIX
if (Name!=NULL)
{
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
}
#endif
}
uint GetFileAttr(const wchar *Name)
{
#ifdef _WIN_ALL
DWORD Attr=GetFileAttributes(Name);
if (Attr==0xffffffff)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Attr=GetFileAttributes(LongName);
}
return Attr;
#else
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
struct stat st;
if (stat(NameA,&st)!=0)
return 0;
return st.st_mode;
#endif
}
bool SetFileAttr(const wchar *Name,uint Attr)
{
#ifdef _WIN_ALL
bool Success=SetFileAttributes(Name,Attr)!=0;
if (!Success)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Success=SetFileAttributes(LongName,Attr)!=0;
}
return Success;
#elif defined(_UNIX)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
return chmod(NameA,(mode_t)Attr)==0;
#else
return false;
#endif
}
#if 0
wchar *MkTemp(wchar *Name,size_t MaxSize)
{
size_t Length=wcslen(Name);
RarTime CurTime;
CurTime.SetCurrentTime();
// We cannot use CurTime.GetWin() as is, because its lowest bits can
// have low informational value, like being a zero or few fixed numbers.
uint Random=(uint)(CurTime.GetWin()/100000);
// Using PID we guarantee that different RAR copies use different temp names
// even if started in exactly the same time.
uint PID=0;
#ifdef _WIN_ALL
PID=(uint)GetCurrentProcessId();
#elif defined(_UNIX)
PID=(uint)getpid();
#endif
for (uint Attempt=0;;Attempt++)
{
uint Ext=Random%50000+Attempt;
wchar RndText[50];
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
return NULL;
wcscpy(Name+Length,RndText);
if (!FileExist(Name))
break;
}
return Name;
}
#endif
#if !defined(SFX_MODULE)
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
{
SaveFilePos SavePos(*SrcFile);
#ifndef SILENT
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
#endif
if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
uiMsg(UIEVENT_FILESUMSTART);
if ((Flags & CALCFSUM_CURPOS)==0)
SrcFile->Seek(0,SEEK_SET);
const size_t BufSize=0x100000;
Array<byte> Data(BufSize);
DataHash HashCRC,HashBlake2;
HashCRC.Init(HASH_CRC32,Threads);
HashBlake2.Init(HASH_BLAKE2,Threads);
int64 BlockCount=0;
int64 TotalRead=0;
while (true)
{
size_t SizeToRead;
if (Size==INT64NDF) // If we process the entire file.
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
else
SizeToRead=(size_t)Min((int64)BufSize,Size);
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
if (ReadSize==0)
break;
TotalRead+=ReadSize;
if ((++BlockCount & 0xf)==0)
{
#ifndef SILENT
if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
uiExtractProgress(TotalRead,FileLength,TotalRead,FileLength);
else
{
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
}
#endif
Wait();
}
if (CRC32!=NULL)
HashCRC.Update(&Data[0],ReadSize);
if (Blake2!=NULL)
HashBlake2.Update(&Data[0],ReadSize);
if (Size!=INT64NDF)
Size-=ReadSize;
}
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
uiMsg(UIEVENT_FILESUMEND);
if (CRC32!=NULL)
*CRC32=HashCRC.GetCRC32();
if (Blake2!=NULL)
{
HashValue Result;
HashBlake2.Result(&Result);
memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
}
}
#endif
bool RenameFile(const wchar *SrcName,const wchar *DestName)
{
#ifdef _WIN_ALL
bool Success=MoveFile(SrcName,DestName)!=0;
if (!Success)
{
wchar LongName1[NM],LongName2[NM];
if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
Success=MoveFile(LongName1,LongName2)!=0;
}
return Success;
#else
char SrcNameA[NM],DestNameA[NM];
WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
WideToChar(DestName,DestNameA,ASIZE(DestNameA));
bool Success=rename(SrcNameA,DestNameA)==0;
return Success;
#endif
}
bool DelFile(const wchar *Name)
{
#ifdef _WIN_ALL
bool Success=DeleteFile(Name)!=0;
if (!Success)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Success=DeleteFile(LongName)!=0;
}
return Success;
#else
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
bool Success=remove(NameA)==0;
return Success;
#endif
}
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
bool SetFileCompression(const wchar *Name,bool State)
{
HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
}
if (hFile==INVALID_HANDLE_VALUE)
return false;
SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
DWORD Result;
int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
sizeof(NewState),NULL,0,&Result,NULL);
CloseHandle(hFile);
return RetCode!=0;
}
#endif

View File

@@ -0,0 +1,50 @@
#ifndef _RAR_FILEFN_
#define _RAR_FILEFN_
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr);
bool CreatePath(const wchar *Path,bool SkipLastName);
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const wchar *Name);
#ifndef SFX_MODULE
int64 GetFreeDisk(const wchar *Name);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
bool IsFAT(const wchar *Root);
#endif
bool FileExist(const wchar *Name);
bool WildFileExist(const wchar *Name);
bool IsDir(uint Attr);
bool IsUnreadable(uint Attr);
bool IsLink(uint Attr);
void SetSFXMode(const wchar *FileName);
void EraseDiskContents(const wchar *FileName);
bool IsDeleteAllowed(uint FileAttr);
void PrepareToDelete(const wchar *Name);
uint GetFileAttr(const wchar *Name);
bool SetFileAttr(const wchar *Name,uint Attr);
#if 0
wchar* MkTemp(wchar *Name,size_t MaxSize);
#endif
enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8};
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size=INT64NDF,uint Flags=0);
bool RenameFile(const wchar *SrcName,const wchar *DestName);
bool DelFile(const wchar *Name);
bool DelDir(const wchar *Name);
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
bool SetFileCompression(const wchar *Name,bool State);
#endif
#endif

162
reference/unrar/filestr.cpp Normal file
View File

@@ -0,0 +1,162 @@
#include "rar.hpp"
bool ReadTextFile(
const wchar *Name,
StringList *List,
bool Config,
bool AbortOnError,
RAR_CHARSET SrcCharset,
bool Unquote,
bool SkipComments,
bool ExpandEnvStr)
{
wchar FileName[NM];
*FileName=0;
if (Name!=NULL)
if (Config)
GetConfigName(Name,FileName,ASIZE(FileName),true,false);
else
wcsncpyz(FileName,Name,ASIZE(FileName));
File SrcFile;
if (*FileName!=0)
{
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName,0);
if (!OpenCode)
{
if (AbortOnError)
ErrHandler.Exit(RARX_OPEN);
return false;
}
}
else
SrcFile.SetHandleType(FILE_HANDLESTD);
uint DataSize=0,ReadSize;
const int ReadBlock=4096;
Array<byte> Data(ReadBlock);
while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
{
DataSize+=ReadSize;
Data.Add(ReadSize); // Always have ReadBlock available for next data.
}
// Set to really read size, so we can zero terminate it correctly.
Data.Alloc(DataSize);
int LowEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0;
int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0;
bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf;
if (SrcCharset==RCH_DEFAULT)
{
if (LowEndian || BigEndian)
for (size_t I=2;I<DataSize;I++)
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
{
SrcCharset=RCH_UNICODE; // High byte in UTF-16 char is found.
break;
}
if (Utf8)
{
Data.Push(0); // Need a zero terminated string for UtfToWide.
if (IsTextUtf8((const char *)(Data+3)))
SrcCharset=RCH_UTF8;
}
}
Array<wchar> DataW;
if (SrcCharset==RCH_DEFAULT || SrcCharset==RCH_OEM || SrcCharset==RCH_ANSI)
{
Data.Push(0); // Zero terminate.
#if defined(_WIN_ALL)
if (SrcCharset==RCH_OEM)
OemToCharA((char *)&Data[0],(char *)&Data[0]);
#endif
DataW.Alloc(Data.Size());
CharToWide((char *)&Data[0],&DataW[0],DataW.Size());
}
if (SrcCharset==RCH_UNICODE)
{
size_t Start=2; // Skip byte order mark.
if (!LowEndian && !BigEndian) // No byte order mask.
{
Start=0;
LowEndian=1;
}
DataW.Alloc(Data.Size()/2+1);
size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16.
for (size_t I=Start;I<End;I+=2)
DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LowEndian]*256;
DataW[(End-Start)/2]=0;
}
if (SrcCharset==RCH_UTF8)
{
Data.Push(0); // Zero terminate data.
DataW.Alloc(Data.Size());
UtfToWide((const char *)(Data+(Utf8 ? 3:0)),&DataW[0],DataW.Size());
}
wchar *CurStr=&DataW[0];
while (*CurStr!=0)
{
wchar *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
{
*NextStr=0;
CmtPtr=NextStr;
}
NextStr++;
}
bool Done=*NextStr==0;
*NextStr=0;
for (wchar *SpacePtr=(CmtPtr!=NULL ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (Unquote && *CurStr=='\"')
{
size_t Length=wcslen(CurStr);
if (CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
CurStr++;
}
}
bool Expanded=false;
#if defined(_WIN_ALL)
if (ExpandEnvStr && *CurStr=='%') // Expand environment variables in Windows.
{
wchar ExpName[NM];
*ExpName=0;
DWORD Result=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
Expanded=Result!=0 && Result<ASIZE(ExpName);
if (Expanded && *ExpName!=0)
List->AddString(ExpName);
}
#endif
if (!Expanded && *CurStr!=0)
List->AddString(CurStr);
if (Done)
break;
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
return true;
}

View File

@@ -0,0 +1,15 @@
#ifndef _RAR_FILESTR_
#define _RAR_FILESTR_
bool ReadTextFile(
const wchar *Name,
StringList *List,
bool Config,
bool AbortOnError=false,
RAR_CHARSET SrcCharset=RCH_DEFAULT,
bool Unquote=false,
bool SkipComments=false,
bool ExpandEnvStr=false
);
#endif

218
reference/unrar/find.cpp Normal file
View File

@@ -0,0 +1,218 @@
#include "rar.hpp"
FindFile::FindFile()
{
*FindMask=0;
FirstCall=true;
#ifdef _WIN_ALL
hFind=INVALID_HANDLE_VALUE;
#else
dirp=NULL;
#endif
}
FindFile::~FindFile()
{
#ifdef _WIN_ALL
if (hFind!=INVALID_HANDLE_VALUE)
FindClose(hFind);
#else
if (dirp!=NULL)
closedir(dirp);
#endif
}
void FindFile::SetMask(const wchar *Mask)
{
wcscpy(FindMask,Mask);
FirstCall=true;
}
bool FindFile::Next(FindData *fd,bool GetSymLink)
{
fd->Error=false;
if (*FindMask==0)
return false;
#ifdef _WIN_ALL
if (FirstCall)
{
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
return false;
}
else
if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
return false;
#else
if (FirstCall)
{
wchar DirName[NM];
wcsncpyz(DirName,FindMask,ASIZE(DirName));
RemoveNameFromPath(DirName);
if (*DirName==0)
wcscpy(DirName,L".");
char DirNameA[NM];
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
if ((dirp=opendir(DirNameA))==NULL)
{
fd->Error=(errno!=ENOENT);
return false;
}
}
while (1)
{
struct dirent *ent=readdir(dirp);
if (ent==NULL)
return false;
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
continue;
wchar Name[NM];
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
if (CmpName(FindMask,Name,MATCH_NAMES))
{
wchar FullName[NM];
wcscpy(FullName,FindMask);
*PointToName(FullName)=0;
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
{
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
return false;
}
wcscat(FullName,Name);
if (!FastFind(FullName,fd,GetSymLink))
{
ErrHandler.OpenErrorMsg(FullName);
continue;
}
wcscpy(fd->Name,FullName);
break;
}
}
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
fd->IsLink=IsLink(fd->FileAttr);
FirstCall=false;
wchar *NameOnly=PointToName(fd->Name);
if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
return Next(fd);
return true;
}
bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
{
fd->Error=false;
#ifndef _UNIX
if (IsWildcard(FindMask))
return false;
#endif
#ifdef _WIN_ALL
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
if (hFind==INVALID_HANDLE_VALUE)
return false;
FindClose(hFind);
#else
char FindMaskA[NM];
WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
struct stat st;
if (GetSymLink)
{
#ifdef SAVE_LINKS
if (lstat(FindMaskA,&st)!=0)
#else
if (stat(FindMaskA,&st)!=0)
#endif
{
fd->Error=(errno!=ENOENT);
return false;
}
}
else
if (stat(FindMaskA,&st)!=0)
{
fd->Error=(errno!=ENOENT);
return false;
}
fd->FileAttr=st.st_mode;
fd->Size=st.st_size;
#ifdef UNIX_TIME_NS
fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
#else
fd->mtime.SetUnix(st.st_mtime);
fd->atime.SetUnix(st.st_atime);
fd->ctime.SetUnix(st.st_ctime);
#endif
wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
fd->IsLink=IsLink(fd->FileAttr);
return true;
}
#ifdef _WIN_ALL
HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
{
WIN32_FIND_DATA FindData;
if (hFind==INVALID_HANDLE_VALUE)
{
hFind=FindFirstFile(Mask,&FindData);
if (hFind==INVALID_HANDLE_VALUE)
{
wchar LongMask[NM];
if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
hFind=FindFirstFile(LongMask,&FindData);
}
if (hFind==INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
// We must not issue an error for "file not found" and "path not found",
// because it is normal to not find anything for wildcard mask when
// archiving. Also searching for non-existent file is normal in some
// other modules, like WinRAR scanning for winrar_theme_description.txt
// to check if any themes are available.
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND &&
SysErr!=ERROR_PATH_NOT_FOUND &&
SysErr!=ERROR_NO_MORE_FILES;
}
}
else
if (!FindNextFile(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
fd->ctime.SetWinFT(&FindData.ftCreationTime);
fd->atime.SetWinFT(&FindData.ftLastAccessTime);
}
fd->Flags=0;
return hFind;
}
#endif

49
reference/unrar/find.hpp Normal file
View File

@@ -0,0 +1,49 @@
#ifndef _RAR_FINDDATA_
#define _RAR_FINDDATA_
enum FINDDATA_FLAGS {
FDDF_SECONDDIR=1 // Second encounter of same directory in SCAN_GETDIRSTWICE ScanTree mode.
};
struct FindData
{
wchar Name[NM];
uint64 Size;
uint FileAttr;
bool IsDir;
bool IsLink;
RarTime mtime;
RarTime ctime;
RarTime atime;
#ifdef _WIN_ALL
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
#endif
uint Flags;
bool Error;
};
class FindFile
{
private:
#ifdef _WIN_ALL
static HANDLE Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd);
#endif
wchar FindMask[NM];
bool FirstCall;
#ifdef _WIN_ALL
HANDLE hFind;
#else
DIR *dirp;
#endif
public:
FindFile();
~FindFile();
void SetMask(const wchar *Mask);
bool Next(FindData *fd,bool GetSymLink=false);
static bool FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink=false);
};
#endif

View File

@@ -0,0 +1,52 @@
#include "rar.hpp"
BitInput::BitInput(bool AllocBuffer)
{
ExternalBuffer=false;
if (AllocBuffer)
{
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
// So let's allocate 3 additional bytes for situation, when we need to
// read only 1 byte from the last position of buffer and avoid a crash
// from access to next 3 bytes, which contents we do not need.
size_t BufSize=MAX_SIZE+3;
InBuf=new byte[BufSize];
// Ensure that we get predictable results when accessing bytes in area
// not filled with read data.
memset(InBuf,0,BufSize);
}
else
InBuf=NULL;
}
BitInput::~BitInput()
{
if (!ExternalBuffer)
delete[] InBuf;
}
void BitInput::faddbits(uint Bits)
{
// Function wrapped version of inline addbits to save code size.
addbits(Bits);
}
uint BitInput::fgetbits()
{
// Function wrapped version of inline getbits to save code size.
return getbits();
}
void BitInput::SetExternalBuffer(byte *Buf)
{
if (InBuf!=NULL && !ExternalBuffer)
delete[] InBuf;
InBuf=Buf;
ExternalBuffer=true;
}

View File

@@ -0,0 +1,68 @@
#ifndef _RAR_GETBITS_
#define _RAR_GETBITS_
class BitInput
{
public:
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
int InAddr; // Curent byte position in the buffer.
int InBit; // Current bit position in the current byte.
bool ExternalBuffer;
public:
BitInput(bool AllocBuffer);
~BitInput();
byte *InBuf; // Dynamically allocated input buffer.
void InitBitInput()
{
InAddr=InBit=0;
}
// Move forward by 'Bits' bits.
void addbits(uint Bits)
{
Bits+=InBit;
InAddr+=Bits>>3;
InBit=Bits&7;
}
// Return 16 bits from current position in the buffer.
// Bit at (InAddr,InBit) has the highest position in returning data.
uint getbits()
{
uint BitField=(uint)InBuf[InAddr] << 16;
BitField|=(uint)InBuf[InAddr+1] << 8;
BitField|=(uint)InBuf[InAddr+2];
BitField >>= (8-InBit);
return BitField & 0xffff;
}
// Return 32 bits from current position in the buffer.
// Bit at (InAddr,InBit) has the highest position in returning data.
uint getbits32()
{
uint BitField=(uint)InBuf[InAddr] << 24;
BitField|=(uint)InBuf[InAddr+1] << 16;
BitField|=(uint)InBuf[InAddr+2] << 8;
BitField|=(uint)InBuf[InAddr+3];
BitField <<= InBit;
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
return BitField & 0xffffffff;
}
void faddbits(uint Bits);
uint fgetbits();
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
// if buffer will be overflown.
bool Overflow(uint IncPtr)
{
return InAddr+IncPtr>=MAX_SIZE;
}
void SetExternalBuffer(byte *Buf);
};
#endif

View File

@@ -0,0 +1,7 @@
#define INCLUDEGLOBAL
#if defined(__BORLANDC__) || defined(_MSC_VER)
#pragma hdrstop
#endif
#include "rar.hpp"

View File

@@ -0,0 +1,14 @@
#ifndef _RAR_GLOBAL_
#define _RAR_GLOBAL_
#ifdef INCLUDEGLOBAL
#define EXTVAR
#else
#define EXTVAR extern
#endif
EXTVAR ErrorHandler ErrHandler;
#endif

View File

@@ -0,0 +1,34 @@
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
{
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
if (!FileExist(NameExisting))
return false;
CreatePath(NameNew,true);
#ifdef _WIN_ALL
bool Success=CreateHardLink(NameNew,NameExisting,NULL)!=0;
if (!Success)
{
uiMsg(UIERROR_HLINKCREATE,NameNew);
ErrHandler.SysErrMsg();
ErrHandler.SetErrorCode(RARX_CREATE);
}
return Success;
#elif defined(_UNIX)
char NameExistingA[NM],NameNewA[NM];
WideToChar(NameExisting,NameExistingA,ASIZE(NameExistingA));
WideToChar(NameNew,NameNewA,ASIZE(NameNewA));
bool Success=link(NameExistingA,NameNewA)==0;
if (!Success)
{
uiMsg(UIERROR_HLINKCREATE,NameNew);
ErrHandler.SysErrMsg();
ErrHandler.SetErrorCode(RARX_CREATE);
}
return Success;
#else
return false;
#endif
}

135
reference/unrar/hash.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include "rar.hpp"
void HashValue::Init(HASH_TYPE Type)
{
HashValue::Type=Type;
// Zero length data CRC32 is 0. It is important to set it when creating
// headers with no following data like directories or symlinks.
if (Type==HASH_RAR14 || Type==HASH_CRC32)
CRC32=0;
if (Type==HASH_BLAKE2)
{
// dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
// is BLAKE2sp hash of empty data. We init the structure to this value,
// so if we create a file or service header with no following data like
// "file copy" or "symlink", we set the checksum to proper value avoiding
// additional header type or size checks when extracting.
static byte EmptyHash[32]={
0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
};
memcpy(Digest,EmptyHash,sizeof(Digest));
}
}
bool HashValue::operator == (const HashValue &cmp)
{
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
return true;
if (Type==HASH_RAR14 && cmp.Type==HASH_RAR14 ||
Type==HASH_CRC32 && cmp.Type==HASH_CRC32)
return CRC32==cmp.CRC32;
if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
return false;
}
DataHash::DataHash()
{
blake2ctx=NULL;
HashType=HASH_NONE;
#ifdef RAR_SMP
ThPool=NULL;
MaxThreads=0;
#endif
}
DataHash::~DataHash()
{
#ifdef RAR_SMP
DestroyThreadPool(ThPool);
#endif
cleandata(&CurCRC32, sizeof(CurCRC32));
if (blake2ctx!=NULL)
{
cleandata(blake2ctx, sizeof(blake2sp_state));
delete blake2ctx;
}
}
void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
{
if (blake2ctx==NULL)
blake2ctx=new blake2sp_state;
HashType=Type;
if (Type==HASH_RAR14)
CurCRC32=0;
if (Type==HASH_CRC32)
CurCRC32=0xffffffff; // Initial CRC32 value.
if (Type==HASH_BLAKE2)
blake2sp_init(blake2ctx);
#ifdef RAR_SMP
DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
#endif
}
void DataHash::Update(const void *Data,size_t DataSize)
{
#ifndef SFX_MODULE
if (HashType==HASH_RAR14)
CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
#endif
if (HashType==HASH_CRC32)
CurCRC32=CRC32(CurCRC32,Data,DataSize);
if (HashType==HASH_BLAKE2)
{
#ifdef RAR_SMP
if (MaxThreads>1 && ThPool==NULL)
ThPool=CreateThreadPool();
blake2ctx->ThPool=ThPool;
blake2ctx->MaxThreads=MaxThreads;
#endif
blake2sp_update( blake2ctx, (byte *)Data, DataSize);
}
}
void DataHash::Result(HashValue *Result)
{
Result->Type=HashType;
if (HashType==HASH_RAR14)
Result->CRC32=CurCRC32;
if (HashType==HASH_CRC32)
Result->CRC32=CurCRC32^0xffffffff;
if (HashType==HASH_BLAKE2)
{
// Preserve the original context, so we can continue hashing if necessary.
blake2sp_state res=*blake2ctx;
blake2sp_final(&res,Result->Digest);
}
}
uint DataHash::GetCRC32()
{
return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
}
bool DataHash::Cmp(HashValue *CmpValue,byte *Key)
{
HashValue Final;
Result(&Final);
if (Key!=NULL)
ConvertHashToMAC(&Final,Key);
return Final==*CmpValue;
}

52
reference/unrar/hash.hpp Normal file
View File

@@ -0,0 +1,52 @@
#ifndef _RAR_DATAHASH_
#define _RAR_DATAHASH_
enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
struct HashValue
{
void Init(HASH_TYPE Type);
bool operator == (const HashValue &cmp);
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
HASH_TYPE Type;
union
{
uint CRC32;
byte Digest[SHA256_DIGEST_SIZE];
};
};
#ifdef RAR_SMP
class ThreadPool;
class DataHash;
#endif
class DataHash
{
private:
HASH_TYPE HashType;
uint CurCRC32;
blake2sp_state *blake2ctx;
#ifdef RAR_SMP
ThreadPool *ThPool;
uint MaxThreads;
// Upper limit for maximum threads to prevent wasting threads in pool.
static const uint MaxHashThreads=8;
#endif
public:
DataHash();
~DataHash();
void Init(HASH_TYPE Type,uint MaxThreads);
void Update(const void *Data,size_t DataSize);
void Result(HashValue *Result);
uint GetCRC32();
bool Cmp(HashValue *CmpValue,byte *Key);
HASH_TYPE Type() {return HashType;}
};
#endif

View File

@@ -0,0 +1,61 @@
#include "rar.hpp"
void FileHeader::Reset(size_t SubDataSize)
{
SubData.Alloc(SubDataSize);
BaseBlock::Reset();
FileHash.Init(HASH_NONE);
mtime.Reset();
atime.Reset();
ctime.Reset();
SplitBefore=false;
SplitAfter=false;
UnknownUnpSize=0;
SubFlags=0; // Important for RAR 3.0 subhead.
CryptMethod=CRYPT_NONE;
Encrypted=false;
SaltSet=false;
UsePswCheck=false;
UseHashKey=false;
Lg2Count=0;
Solid=false;
Dir=false;
WinSize=0;
Inherited=false;
SubBlock=false;
CommentInHeader=false;
Version=false;
LargeFile=false;
RedirType=FSREDIR_NONE;
DirTarget=false;
UnixOwnerSet=false;
}
FileHeader& FileHeader::operator = (FileHeader &hd)
{
SubData.Reset();
memcpy(this,&hd,sizeof(*this));
SubData.CleanData();
SubData=hd.SubData;
return *this;
}
void MainHeader::Reset()
{
HighPosAV=0;
PosAV=0;
CommentInHeader=false;
PackComment=false;
Locator=false;
QOpenOffset=0;
QOpenMaxSize=0;
RROffset=0;
RRMaxSize=0;
}

380
reference/unrar/headers.hpp Normal file
View File

@@ -0,0 +1,380 @@
#ifndef _RAR_HEADERS_
#define _RAR_HEADERS_
#define SIZEOF_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
#define SIZEOF_SHORTBLOCKHEAD 7
#define SIZEOF_LONGBLOCKHEAD 11
#define SIZEOF_SUBBLOCKHEAD 14
#define SIZEOF_COMMHEAD 13
#define SIZEOF_PROTECTHEAD 26
#define SIZEOF_AVHEAD 14
#define SIZEOF_SIGNHEAD 15
#define SIZEOF_UOHEAD 18
#define SIZEOF_MACHEAD 22
#define SIZEOF_EAHEAD 24
#define SIZEOF_BEEAHEAD 24
#define SIZEOF_STREAMHEAD 26
#define VER_PACK 29
#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive.
#define VER_UNPACK 29
#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive.
#define MHD_VOLUME 0x0001U
// Old style main archive comment embed into main archive header. Must not
// be used in new archives anymore.
#define MHD_COMMENT 0x0002U
#define MHD_LOCK 0x0004U
#define MHD_SOLID 0x0008U
#define MHD_PACK_COMMENT 0x0010U
#define MHD_NEWNUMBERING 0x0010U
#define MHD_AV 0x0020U
#define MHD_PROTECT 0x0040U
#define MHD_PASSWORD 0x0080U
#define MHD_FIRSTVOLUME 0x0100U
#define LHD_SPLIT_BEFORE 0x0001U
#define LHD_SPLIT_AFTER 0x0002U
#define LHD_PASSWORD 0x0004U
// Old style file comment embed into file header. Must not be used
// in new archives anymore.
#define LHD_COMMENT 0x0008U
// For non-file subheaders it denotes 'subblock having a parent file' flag.
#define LHD_SOLID 0x0010U
#define LHD_WINDOWMASK 0x00e0U
#define LHD_WINDOW64 0x0000U
#define LHD_WINDOW128 0x0020U
#define LHD_WINDOW256 0x0040U
#define LHD_WINDOW512 0x0060U
#define LHD_WINDOW1024 0x0080U
#define LHD_WINDOW2048 0x00a0U
#define LHD_WINDOW4096 0x00c0U
#define LHD_DIRECTORY 0x00e0U
#define LHD_LARGE 0x0100U
#define LHD_UNICODE 0x0200U
#define LHD_SALT 0x0400U
#define LHD_VERSION 0x0800U
#define LHD_EXTTIME 0x1000U
#define SKIP_IF_UNKNOWN 0x4000U
#define LONG_BLOCK 0x8000U
#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
enum HEADER_TYPE {
// RAR 5.0 header types.
HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
// RAR 1.5 - 4.x header types.
HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
};
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
// Internal implementation, depends on archive format version.
enum HOST_SYSTEM {
// RAR 5.0 host OS
HOST5_WINDOWS=0,HOST5_UNIX=1,
// RAR 3.0 host OS.
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
// Unified archive format independent implementation.
enum HOST_SYSTEM_TYPE {
HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
};
// We also use these values in extra field, so do not modify them.
enum FILE_SYSTEM_REDIRECT {
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
FSREDIR_HARDLINK, FSREDIR_FILECOPY
};
#define SUBHEAD_TYPE_CMT L"CMT"
#define SUBHEAD_TYPE_QOPEN L"QO"
#define SUBHEAD_TYPE_ACL L"ACL"
#define SUBHEAD_TYPE_STREAM L"STM"
#define SUBHEAD_TYPE_UOWNER L"UOW"
#define SUBHEAD_TYPE_AV L"AV"
#define SUBHEAD_TYPE_RR L"RR"
#define SUBHEAD_TYPE_OS2EA L"EA2"
/* new file inherits a subblock when updating a host file */
#define SUBHEAD_FLAGS_INHERITED 0x80000000
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
struct MarkHeader
{
byte Mark[8];
// Following fields are virtual and not present in real blocks.
uint HeadSize;
};
struct BaseBlock
{
uint HeadCRC; // 'ushort' for RAR 1.5.
HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
uint Flags; // 'ushort' for RAR 1.5.
uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
bool SkipIfUnknown;
void Reset()
{
SkipIfUnknown=false;
}
};
struct BlockHeader:BaseBlock
{
uint DataSize;
};
struct MainHeader:BaseBlock
{
ushort HighPosAV;
uint PosAV;
bool CommentInHeader;
bool PackComment; // For RAR 1.4 archive format only.
bool Locator;
uint64 QOpenOffset; // Offset of quick list record.
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
uint64 RROffset; // Offset of recovery record.
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
void Reset();
};
struct FileHeader:BlockHeader
{
byte HostOS;
byte UnpVer;
byte Method;
union {
uint FileAttr;
uint SubFlags;
};
wchar FileName[NM];
Array<byte> SubData;
RarTime mtime;
RarTime ctime;
RarTime atime;
int64 PackSize;
int64 UnpSize;
int64 MaxSize; // Reserve size bytes for vint of this size.
HashValue FileHash;
uint FileFlags;
bool SplitBefore;
bool SplitAfter;
bool UnknownUnpSize;
bool Encrypted;
CRYPT_METHOD CryptMethod;
bool SaltSet;
byte Salt[SIZE_SALT50];
byte InitV[SIZE_INITV];
bool UsePswCheck;
byte PswCheck[SIZE_PSWCHECK];
// Use HMAC calculated from HashKey and checksum instead of plain checksum.
bool UseHashKey;
// Key to convert checksum to HMAC. Derived from password with PBKDF2
// using additional iterations.
byte HashKey[SHA256_DIGEST_SIZE];
uint Lg2Count; // Log2 of PBKDF2 repetition count.
bool Solid;
bool Dir;
bool CommentInHeader; // RAR 2.0 file comment.
bool Version; // name.ext;ver file name containing the version number.
size_t WinSize;
bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
// 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
bool LargeFile;
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
bool SubBlock;
HOST_SYSTEM_TYPE HSType;
FILE_SYSTEM_REDIRECT RedirType;
wchar RedirName[NM];
bool DirTarget;
bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
char UnixOwnerName[256],UnixGroupName[256];
#ifdef _UNIX
uid_t UnixOwnerID;
gid_t UnixGroupID;
#else // Need these Unix fields in Windows too for 'list' command.
uint UnixOwnerID;
uint UnixGroupID;
#endif
void Reset(size_t SubDataSize=0);
bool CmpName(const wchar *Name)
{
return(wcscmp(FileName,Name)==0);
}
FileHeader& operator = (FileHeader &hd);
};
struct EndArcHeader:BaseBlock
{
// Optional CRC32 of entire archive up to start of EndArcHeader block.
// Present in RAR 4.x archives if EARC_DATACRC flag is set.
uint ArcDataCRC;
uint VolNumber; // Optional number of current volume.
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
bool NextVolume; // Not last volume.
bool DataCRC;
bool RevSpace;
bool StoreVolNumber;
void Reset()
{
BaseBlock::Reset();
NextVolume=false;
DataCRC=false;
RevSpace=false;
StoreVolNumber=false;
}
};
struct CryptHeader:BaseBlock
{
bool UsePswCheck;
uint Lg2Count; // Log2 of PBKDF2 repetition count.
byte Salt[SIZE_SALT50];
byte PswCheck[SIZE_PSWCHECK];
};
// SubBlockHeader and its successors were used in RAR 2.x format.
// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
struct SubBlockHeader:BlockHeader
{
ushort SubType;
byte Level;
};
struct CommentHeader:BaseBlock
{
ushort UnpSize;
byte UnpVer;
byte Method;
ushort CommCRC;
};
struct ProtectHeader:BlockHeader
{
byte Version;
ushort RecSectors;
uint TotalBlocks;
byte Mark[8];
};
struct AVHeader:BaseBlock
{
byte UnpVer;
byte Method;
byte AVVer;
uint AVInfoCRC;
};
struct SignHeader:BaseBlock
{
uint CreationTime;
ushort ArcNameSize;
ushort UserNameSize;
};
struct UnixOwnersHeader:SubBlockHeader
{
ushort OwnerNameSize;
ushort GroupNameSize;
/* dummy */
char OwnerName[256];
char GroupName[256];
};
struct EAHeader:SubBlockHeader
{
uint UnpSize;
byte UnpVer;
byte Method;
uint EACRC;
};
struct StreamHeader:SubBlockHeader
{
uint UnpSize;
byte UnpVer;
byte Method;
uint StreamCRC;
ushort StreamNameSize;
char StreamName[260];
};
struct MacFInfoHeader:SubBlockHeader
{
uint fileType;
uint fileCreator;
};
#endif

Some files were not shown because too many files have changed in this diff Show More