mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
fix up gzip encoding
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user