fix up gzip encoding

This commit is contained in:
Adam Hathcock
2026-02-13 09:51:46 +00:00
parent 6c2e27870d
commit da5cc69a06
7 changed files with 164 additions and 13 deletions

View File

@@ -8,6 +8,7 @@ using SharpCompress.Common;
using SharpCompress.Common.Tar;
using SharpCompress.Common.Tar.Headers;
using SharpCompress.IO;
using SharpCompress.Providers;
using SharpCompress.Readers;
using SharpCompress.Readers.Tar;
using SharpCompress.Writers.Tar;
@@ -44,7 +45,11 @@ public partial class TarArchive
),
CompressionType.GZip => ReaderOptions.Providers.CreateDecompressStream(
CompressionType.GZip,
stream
stream,
CompressionContext.FromStream(stream) with
{
FormatOptions = ReaderOptions,
}
),
CompressionType.ZStandard => ReaderOptions.Providers.CreateDecompressStream(
CompressionType.ZStandard,
@@ -80,6 +85,10 @@ public partial class TarArchive
CompressionType.GZip => ReaderOptions.Providers.CreateDecompressStreamAsync(
CompressionType.GZip,
stream,
CompressionContext.FromStream(stream) with
{
FormatOptions = ReaderOptions,
},
cancellationToken
),
CompressionType.ZStandard => ReaderOptions.Providers.CreateDecompressStreamAsync(

View File

@@ -32,6 +32,8 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Options;
namespace SharpCompress.Compressors.Deflate;
@@ -53,8 +55,23 @@ public partial class GZipStream : Stream
public GZipStream(Stream stream, CompressionMode mode)
: this(stream, mode, CompressionLevel.Default, Encoding.UTF8) { }
public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level)
: this(stream, mode, level, Encoding.UTF8) { }
public GZipStream(Stream stream, CompressionMode mode, IReaderOptions readerOptions)
: this(stream, mode, CompressionLevel.Default, readerOptions) { }
public GZipStream(
Stream stream,
CompressionMode mode,
CompressionLevel level,
IReaderOptions readerOptions
)
: this(
stream,
mode,
level,
(
readerOptions ?? throw new ArgumentNullException(nameof(readerOptions))
).ArchiveEncoding.GetEncoding()
) { }
public GZipStream(
Stream stream,

View File

@@ -9,6 +9,7 @@ using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Common.Options;
using SharpCompress.IO;
using SharpCompress.Providers;
using SharpCompress.Readers;
using SharpCompress.Readers.GZip;
using SharpCompress.Readers.Tar;
@@ -129,7 +130,11 @@ public class GZipFactory
sharpCompressStream.Rewind();
using var testStream = options.Providers.CreateDecompressStream(
CompressionType.GZip,
SharpCompressStream.CreateNonDisposing(sharpCompressStream)
SharpCompressStream.CreateNonDisposing(sharpCompressStream),
CompressionContext.FromStream(sharpCompressStream) with
{
FormatOptions = options,
}
);
if (TarArchive.IsTarFile(testStream))
{

View File

@@ -99,7 +99,7 @@ public class TarFactory
sharpCompressStream,
wrapper.CompressionType,
providers,
cancellationToken
cancellationToken: cancellationToken
)
.ConfigureAwait(false);
if (
@@ -122,19 +122,36 @@ public class TarFactory
private static Stream CreateProbeDecompressionStream(
Stream stream,
CompressionType compressionType,
CompressionProviderRegistry providers
CompressionProviderRegistry providers,
IReaderOptions? readerOptions = null
)
{
var nonDisposingStream = SharpCompressStream.CreateNonDisposing(stream);
return compressionType == CompressionType.None
? nonDisposingStream
: providers.CreateDecompressStream(compressionType, nonDisposingStream);
if (compressionType == CompressionType.None)
{
return nonDisposingStream;
}
if (compressionType == CompressionType.GZip && readerOptions is not null)
{
return providers.CreateDecompressStream(
compressionType,
nonDisposingStream,
CompressionContext.FromStream(nonDisposingStream) with
{
FormatOptions = readerOptions,
}
);
}
return providers.CreateDecompressStream(compressionType, nonDisposingStream);
}
private static async ValueTask<Stream> CreateProbeDecompressionStreamAsync(
Stream stream,
CompressionType compressionType,
CompressionProviderRegistry providers,
IReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
@@ -143,6 +160,22 @@ public class TarFactory
{
return nonDisposingStream;
}
if (compressionType == CompressionType.GZip && readerOptions is not null)
{
return await providers
.CreateDecompressStreamAsync(
compressionType,
nonDisposingStream,
CompressionContext.FromStream(nonDisposingStream) with
{
FormatOptions = readerOptions,
},
cancellationToken
)
.ConfigureAwait(false);
}
return await providers
.CreateDecompressStreamAsync(compressionType, nonDisposingStream, cancellationToken)
.ConfigureAwait(false);
@@ -193,7 +226,7 @@ public class TarFactory
stream,
wrapper.CompressionType,
providers,
cancellationToken
cancellationToken: cancellationToken
)
.ConfigureAwait(false);
if (
@@ -286,7 +319,8 @@ public class TarFactory
var decompressedStream = CreateProbeDecompressionStream(
sharpCompressStream,
wrapper.CompressionType,
options.Providers
options.Providers,
options
);
if (TarArchive.IsTarFile(decompressedStream))
{
@@ -323,6 +357,7 @@ public class TarFactory
sharpCompressStream,
wrapper.CompressionType,
options.Providers,
options,
cancellationToken
)
.ConfigureAwait(false);

View File

@@ -1,5 +1,9 @@
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Options;
using SharpCompress.Compressors;
using SharpCompress.Compressors.Deflate;
@@ -17,11 +21,41 @@ public sealed class GZipCompressionProvider : CompressionProviderBase
public override Stream CreateCompressStream(Stream destination, int compressionLevel)
{
var level = (CompressionLevel)compressionLevel;
return new GZipStream(destination, CompressionMode.Compress, level);
return new GZipStream(destination, CompressionMode.Compress, level, Encoding.UTF8);
}
public override Stream CreateDecompressStream(Stream source)
{
return new GZipStream(source, CompressionMode.Decompress);
}
public override Stream CreateDecompressStream(Stream source, CompressionContext context)
{
return new GZipStream(
source,
CompressionMode.Decompress,
CompressionLevel.Default,
ResolveHeaderEncoding(context)
);
}
public override ValueTask<Stream> CreateDecompressStreamAsync(
Stream source,
CompressionContext context,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new ValueTask<Stream>(CreateDecompressStream(source, context));
}
private static Encoding ResolveHeaderEncoding(CompressionContext context) =>
context.FormatOptions switch
{
IReaderOptions readerOptions => readerOptions.ArchiveEncoding.GetEncoding(),
IEncodingOptions encodingOptions => encodingOptions.ArchiveEncoding.GetEncoding(),
IArchiveEncoding archiveEncoding => archiveEncoding.GetEncoding(),
Encoding encoding => encoding,
_ => Encoding.UTF8,
};
}

View File

@@ -13,6 +13,7 @@ using SharpCompress.Compressors.Lzw;
using SharpCompress.Compressors.Xz;
using SharpCompress.Compressors.ZStandard;
using SharpCompress.IO;
using SharpCompress.Providers;
namespace SharpCompress.Readers.Tar;
@@ -41,7 +42,14 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
CompressionType.BZip2,
stream
),
CompressionType.GZip => providers.CreateDecompressStream(CompressionType.GZip, stream),
CompressionType.GZip => providers.CreateDecompressStream(
CompressionType.GZip,
stream,
CompressionContext.FromStream(stream) with
{
FormatOptions = Options,
}
),
CompressionType.ZStandard => providers.CreateDecompressStream(
CompressionType.ZStandard,
stream
@@ -71,6 +79,10 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
CompressionType.GZip => providers.CreateDecompressStreamAsync(
CompressionType.GZip,
stream,
CompressionContext.FromStream(stream) with
{
FormatOptions = Options,
},
cancellationToken
),
CompressionType.ZStandard => providers.CreateDecompressStreamAsync(

View File

@@ -293,6 +293,45 @@ public class CompressionProviderTests
result.Should().Equal(original);
}
[Fact]
public void GZipProvider_Decompress_WithReaderOptionsContext_UsesArchiveEncoding()
{
var provider = new GZipCompressionProvider();
var data = Encoding.UTF8.GetBytes("gzip filename encoding");
var expectedFileName = "café.txt";
var archiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding("iso-8859-1") };
using var compressedStream = new MemoryStream();
using (
var compressStream = new SharpCompress.Compressors.Deflate.GZipStream(
SharpCompressStream.CreateNonDisposing(compressedStream),
CompressionMode.Compress,
SharpCompress.Compressors.Deflate.CompressionLevel.Default,
archiveEncoding.Default
)
)
{
compressStream.FileName = expectedFileName;
compressStream.Write(data, 0, data.Length);
}
compressedStream.Position = 0;
var readerOptions = new ReaderOptions { ArchiveEncoding = archiveEncoding };
var context = CompressionContext.FromStream(compressedStream) with
{
FormatOptions = readerOptions,
};
using var decompressStream = provider.CreateDecompressStream(compressedStream, context);
using var resultStream = new MemoryStream();
decompressStream.CopyTo(resultStream);
resultStream.ToArray().Should().Equal(data);
decompressStream.Should().BeOfType<SharpCompress.Compressors.Deflate.GZipStream>();
var gzipStream = (SharpCompress.Compressors.Deflate.GZipStream)decompressStream;
gzipStream.FileName.Should().Be(expectedFileName);
}
[Fact]
public void BZip2Provider_SupportsCompressionAndDecompression()
{