Some restoring of functionality

This commit is contained in:
Adam Hathcock
2026-01-07 10:32:02 +00:00
parent 725503d1ce
commit bd3cda0617
7 changed files with 46 additions and 37 deletions

View File

@@ -5,27 +5,11 @@ namespace SharpCompress.Common;
public class ArchiveEncoding : IArchiveEncoding
{
public ArchiveEncoding()
{
Default = Encoding.Default;
Password = Encoding.Default;
UTF8 = Encoding.UTF8;
}
/// <summary>
/// Default encoding to use when archive format doesn't specify one.
/// </summary>
public Encoding Default { get; set; }
/// <summary>
/// ArchiveEncoding used by encryption schemes which don't comply with RFC 2898.
/// </summary>
public Encoding Password { get; set; }
/// <summary>
/// Default encoding to use when archive format specifies UTF-8 encoding.
/// </summary>
public Encoding UTF8 { get; set; }
public Encoding Default { get; set; } = Encoding.Default;
public Encoding Password { get; set; } = Encoding.Default;
public Encoding UTF8 { get; set; } = Encoding.UTF8;
public Encoding? Forced { get; set; }
public Func<byte[], int, int, string>? CustomDecoder { get; set; }
}
public interface IArchiveEncoding
@@ -44,13 +28,38 @@ public interface IArchiveEncoding
/// Default encoding to use when archive format specifies UTF-8 encoding.
/// </summary>
public Encoding UTF8 { get; set; }
/// <summary>
/// Set this encoding when you want to force it for all encoding operations.
/// </summary>
public Encoding? Forced { get; set; }
/// <summary>
/// Set this when you want to use a custom method for all decoding operations.
/// </summary>
/// <returns>string Func(bytes, index, length)</returns>
public Func<byte[], int, int, string>? CustomDecoder { get; set; }
}
public static class ArchiveEncodingExtensions
{
public static byte[] Encode(this IArchiveEncoding encoding, string str) => encoding.Default.GetBytes(str);
public static string Decode(this IArchiveEncoding encoding, byte[] bytes) => encoding.Default.GetString(bytes);
public static Encoding GetEncoding(this IArchiveEncoding encoding) =>
encoding.Forced ?? encoding.Default;
public static string Decode(this IArchiveEncoding encoding, byte[] bytes, int start, int length) =>
encoding.Default.GetString(bytes, start, length);
public static Func<byte[], int, int, string> GetDecoder(this IArchiveEncoding encoding) =>
encoding.CustomDecoder
?? ((bytes, index, count) => encoding.GetEncoding().GetString(bytes, index, count));
public static byte[] Encode(this IArchiveEncoding encoding, string str) =>
encoding.Default.GetBytes(str);
public static string Decode(this IArchiveEncoding encoding, byte[] bytes) =>
encoding.Decode(bytes, 0, bytes.Length);
public static string Decode(
this IArchiveEncoding encoding,
byte[] bytes,
int start,
int length
) => encoding.GetDecoder()(bytes, start, length);
}

View File

@@ -63,7 +63,7 @@ internal sealed class TarHeader
//ArchiveEncoding.UTF8.GetBytes("magic").CopyTo(buffer, 257);
var nameByteCount = ArchiveEncoding
.Default
.GetEncoding()
.GetByteCount(Name.NotNull("Name is null"));
if (nameByteCount > 100)
@@ -87,7 +87,7 @@ internal sealed class TarHeader
for (int i = 0; i < dirSeps.Count; i++)
{
int count = ArchiveEncoding
.Default
.GetEncoding()
.GetByteCount(fullName.Substring(0, dirSeps[i]));
if (count < 155)
{
@@ -109,12 +109,12 @@ internal sealed class TarHeader
string namePrefix = fullName.Substring(0, splitIndex);
string name = fullName.Substring(splitIndex + 1);
if (this.ArchiveEncoding.Default.GetByteCount(namePrefix) >= 155)
if (this.ArchiveEncoding.GetEncoding().GetByteCount(namePrefix) >= 155)
throw new Exception(
$"Tar header USTAR format can not fit file name \"{fullName}\" of length {nameByteCount}! Try using GNU Tar format instead!"
);
if (this.ArchiveEncoding.Default.GetByteCount(name) >= 100)
if (this.ArchiveEncoding.GetEncoding().GetByteCount(name) >= 100)
throw new Exception(
$"Tar header USTAR format can not fit file name \"{fullName}\" of length {nameByteCount}! Try using GNU Tar format instead!"
);
@@ -156,7 +156,7 @@ internal sealed class TarHeader
//ArchiveEncoding.UTF8.GetBytes("magic").CopyTo(buffer, 257);
var nameByteCount = ArchiveEncoding
.Default
.GetEncoding()
.GetByteCount(Name.NotNull("Name is null"));
if (nameByteCount > 100)
{
@@ -200,7 +200,7 @@ internal sealed class TarHeader
Name = ArchiveEncoding.Decode(
ArchiveEncoding.Encode(Name.NotNull("Name is null")),
0,
100 - ArchiveEncoding.Default.GetMaxByteCount(1)
100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1)
);
WriteGnuTarLongLink(output);
}

View File

@@ -41,8 +41,8 @@ internal class DirectoryEntryHeader : ZipFileEntry
if (Flags.HasFlag(HeaderFlags.Efs))
{
Name = ArchiveEncoding.UTF8.GetString(name);
Comment = ArchiveEncoding.UTF8.GetString(comment);
Name = ArchiveEncoding.DecodeUTF8(name);
Comment = ArchiveEncoding.DecodeUTF8(comment);
}
else
{

View File

@@ -33,7 +33,7 @@ internal class LocalEntryHeader : ZipFileEntry
if (Flags.HasFlag(HeaderFlags.Efs))
{
Name = ArchiveEncoding.UTF8.GetString(name);
Name = ArchiveEncoding.DecodeUTF8(name);
}
else
{

View File

@@ -23,7 +23,7 @@ public sealed class GZipWriter : AbstractWriter
destination,
CompressionMode.Compress,
(CompressionLevel)(options?.CompressionLevel ?? (int)CompressionLevel.Default),
WriterOptions.ArchiveEncoding.Default
WriterOptions.ArchiveEncoding.GetEncoding()
)
);
}

View File

@@ -72,7 +72,7 @@ internal class ZipCentralDirectoryEntry
version = 20;
}
var flags = Equals(archiveEncoding.Default, Encoding.UTF8)
var flags = Equals(archiveEncoding.GetEncoding(), Encoding.UTF8)
? HeaderFlags.Efs
: HeaderFlags.None;
if (!outputStream.CanSeek)

View File

@@ -244,7 +244,7 @@ public class ZipWriter : AbstractWriter
{
OutputStream.Write(stackalloc byte[] { 63, 0 }); //version says we used PPMd or LZMA
}
var flags = Equals(WriterOptions.ArchiveEncoding.Default, Encoding.UTF8)
var flags = Equals(WriterOptions.ArchiveEncoding.GetEncoding(), Encoding.UTF8)
? HeaderFlags.Efs
: 0;
if (!OutputStream.CanSeek)