diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index b86e154a..b9eac931 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -181,7 +181,7 @@ namespace SharpCompress.Archives.GZip protected override IEnumerable LoadEntries(IEnumerable volumes) { Stream stream = volumes.Single().Stream; - yield return new GZipArchiveEntry(this, new GZipFilePart(stream, ReaderOptions.ForceEncoding)); + yield return new GZipArchiveEntry(this, new GZipFilePart(stream, ReaderOptions.ArchiveEncoding)); } protected override IReader CreateReaderForSolidExtraction() diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 06cac787..f6ec3d50 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -106,7 +106,7 @@ namespace SharpCompress.Archives.SevenZip for (int i = 0; i < database.Files.Count; i++) { var file = database.Files[i]; - yield return new SevenZipArchiveEntry(this, new SevenZipFilePart(stream, database, i, file)); + yield return new SevenZipArchiveEntry(this, new SevenZipFilePart(stream, database, i, file, ReaderOptions.ArchiveEncoding)); } } diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 2705ffdf..35d7fd15 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -75,7 +75,7 @@ namespace SharpCompress.Archives.Tar { try { - TarHeader tar = new TarHeader(); + TarHeader tar = new TarHeader(new ArchiveEncoding()); tar.Read(new BinaryReader(stream)); return tar.Name.Length > 0 && Enum.IsDefined(typeof(EntryType), tar.EntryType); } @@ -127,7 +127,7 @@ namespace SharpCompress.Archives.Tar { Stream stream = volumes.Single().Stream; TarHeader previousHeader = null; - foreach (TarHeader header in TarHeaderFactory.ReadHeader(StreamingMode.Seekable, stream, ReaderOptions.ForceEncoding)) + foreach (TarHeader header in TarHeaderFactory.ReadHeader(StreamingMode.Seekable, stream, ReaderOptions.ArchiveEncoding)) { if (header != null) { @@ -152,7 +152,7 @@ namespace SharpCompress.Archives.Tar memoryStream.Position = 0; var bytes = memoryStream.ToArray(); - header.Name = (ReaderOptions.ForceEncoding ?? ArchiveEncoding.Default).GetString(bytes, 0, bytes.Length).TrimNulls(); + header.Name = ReaderOptions.ArchiveEncoding.Decode(bytes).TrimNulls(); } } diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 3de98abe..49cb69ec 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -81,7 +81,7 @@ namespace SharpCompress.Archives.Zip public static bool IsZipFile(Stream stream, string password = null) { - StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password); + StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password, new ArchiveEncoding()); try { ZipHeader header = @@ -112,7 +112,7 @@ namespace SharpCompress.Archives.Zip internal ZipArchive(FileInfo fileInfo, ReaderOptions readerOptions) : base(ArchiveType.Zip, fileInfo, readerOptions) { - headerFactory = new SeekableZipHeaderFactory(readerOptions.Password, readerOptions.ForceEncoding); + headerFactory = new SeekableZipHeaderFactory(readerOptions.Password, readerOptions.ArchiveEncoding); } protected override IEnumerable LoadVolumes(FileInfo file) @@ -134,7 +134,7 @@ namespace SharpCompress.Archives.Zip internal ZipArchive(Stream stream, ReaderOptions readerOptions) : base(ArchiveType.Zip, stream, readerOptions) { - headerFactory = new SeekableZipHeaderFactory(readerOptions.Password, readerOptions.ForceEncoding); + headerFactory = new SeekableZipHeaderFactory(readerOptions.Password, readerOptions.ArchiveEncoding); } protected override IEnumerable LoadVolumes(IEnumerable streams) @@ -163,7 +163,7 @@ namespace SharpCompress.Archives.Zip case ZipHeaderType.DirectoryEnd: { byte[] bytes = (h as DirectoryEndHeader).Comment; - volume.Comment = (ReaderOptions.ForceEncoding ?? ArchiveEncoding.Default).GetString(bytes, 0, bytes.Length); + volume.Comment = ReaderOptions.ArchiveEncoding.Decode(bytes); yield break; } } diff --git a/src/SharpCompress/Common/ArchiveEncoding.cs b/src/SharpCompress/Common/ArchiveEncoding.cs index c973c7cb..e37da084 100644 --- a/src/SharpCompress/Common/ArchiveEncoding.cs +++ b/src/SharpCompress/Common/ArchiveEncoding.cs @@ -1,23 +1,60 @@ -using System.Text; +using System; +using System.Text; namespace SharpCompress.Common { - public static class ArchiveEncoding + public class ArchiveEncoding { /// /// Default encoding to use when archive format doesn't specify one. /// - public static Encoding Default { get; set; } + public Encoding Default { get; set; } /// - /// Encoding used by encryption schemes which don't comply with RFC 2898. + /// ArchiveEncoding used by encryption schemes which don't comply with RFC 2898. /// - public static Encoding Password { get; set; } + public Encoding Password { get; set; } - static ArchiveEncoding() + /// + /// Set this encoding when you want to force it for all encoding operations. + /// + public Encoding Forced { get; set; } + + /// + /// Set this when you want to use a custom method for all decoding operations. + /// + /// string Func(bytes, index, length) + public Func CustomDecoder { get; set; } + + public ArchiveEncoding() { Default = Encoding.UTF8; Password = Encoding.UTF8; } + + public string Decode(byte[] bytes) + { + return Decode(bytes, 0, bytes.Length); + } + + public string Decode(byte[] bytes, int start, int length) + { + return GetDecoder().Invoke(bytes, start, length); + } + + public byte[] Encode(string str) + { + return GetEncoding().GetBytes(str); + } + + public Encoding GetEncoding() + { + return Forced ?? Default ?? Encoding.UTF8; + } + + public Func GetDecoder() + { + return CustomDecoder ?? ((bytes, index, count) => (Default ?? Encoding.UTF8).GetString(bytes, index, count)); + } } } \ No newline at end of file diff --git a/src/SharpCompress/Common/FilePart.cs b/src/SharpCompress/Common/FilePart.cs index b57ef613..8fd9e6e3 100644 --- a/src/SharpCompress/Common/FilePart.cs +++ b/src/SharpCompress/Common/FilePart.cs @@ -4,6 +4,13 @@ namespace SharpCompress.Common { public abstract class FilePart { + protected FilePart(ArchiveEncoding archiveEncoding) + { + ArchiveEncoding = archiveEncoding; + } + + internal ArchiveEncoding ArchiveEncoding { get; } + internal abstract string FilePartName { get; } internal abstract Stream GetCompressedStream(); diff --git a/src/SharpCompress/Common/GZip/GZipEntry.cs b/src/SharpCompress/Common/GZip/GZipEntry.cs index ad621394..6c80ddff 100644 --- a/src/SharpCompress/Common/GZip/GZipEntry.cs +++ b/src/SharpCompress/Common/GZip/GZipEntry.cs @@ -40,9 +40,9 @@ namespace SharpCompress.Common.GZip internal override IEnumerable Parts => filePart.AsEnumerable(); - internal static IEnumerable GetEntries(Stream stream, Encoding forceEncoding) + internal static IEnumerable GetEntries(Stream stream, OptionsBase options) { - yield return new GZipEntry(new GZipFilePart(stream, forceEncoding)); + yield return new GZipEntry(new GZipFilePart(stream, options.ArchiveEncoding)); } } } \ No newline at end of file diff --git a/src/SharpCompress/Common/GZip/GZipFilePart.cs b/src/SharpCompress/Common/GZip/GZipFilePart.cs index 7b7cda03..82d054be 100644 --- a/src/SharpCompress/Common/GZip/GZipFilePart.cs +++ b/src/SharpCompress/Common/GZip/GZipFilePart.cs @@ -11,32 +11,31 @@ namespace SharpCompress.Common.GZip { internal class GZipFilePart : FilePart { - private string name; - private readonly Stream stream; - private readonly Encoding forceEncoding; + private string _name; + private readonly Stream _stream; - internal GZipFilePart(Stream stream, Encoding forceEncoding) + internal GZipFilePart(Stream stream, ArchiveEncoding archiveEncoding) + : base(archiveEncoding) { ReadAndValidateGzipHeader(stream); EntryStartPosition = stream.Position; - this.stream = stream; - this.forceEncoding = forceEncoding; + this._stream = stream; } internal long EntryStartPosition { get; } internal DateTime? DateModified { get; private set; } - internal override string FilePartName => name; + internal override string FilePartName => _name; internal override Stream GetCompressedStream() { - return new DeflateStream(stream, CompressionMode.Decompress, CompressionLevel.Default, false); + return new DeflateStream(_stream, CompressionMode.Decompress, CompressionLevel.Default, false); } internal override Stream GetRawStream() { - return stream; + return _stream; } private void ReadAndValidateGzipHeader(Stream stream) @@ -78,11 +77,11 @@ namespace SharpCompress.Common.GZip } if ((header[3] & 0x08) == 0x08) { - name = ReadZeroTerminatedString(stream, forceEncoding); + _name = ReadZeroTerminatedString(stream); } if ((header[3] & 0x10) == 0x010) { - ReadZeroTerminatedString(stream, forceEncoding); + ReadZeroTerminatedString(stream); } if ((header[3] & 0x02) == 0x02) { @@ -90,7 +89,7 @@ namespace SharpCompress.Common.GZip } } - private static string ReadZeroTerminatedString(Stream stream, Encoding forceEncoding) + private string ReadZeroTerminatedString(Stream stream) { byte[] buf1 = new byte[1]; var list = new List(); @@ -114,7 +113,7 @@ namespace SharpCompress.Common.GZip } while (!done); byte[] buffer = list.ToArray(); - return (forceEncoding ?? ArchiveEncoding.Default).GetString(buffer, 0, buffer.Length); + return ArchiveEncoding.Decode(buffer); } } } \ No newline at end of file diff --git a/src/SharpCompress/Common/OptionsBase.cs b/src/SharpCompress/Common/OptionsBase.cs index 03fa70b5..b98f0a60 100644 --- a/src/SharpCompress/Common/OptionsBase.cs +++ b/src/SharpCompress/Common/OptionsBase.cs @@ -1,5 +1,4 @@ -using System.Text; - + namespace SharpCompress.Common { public class OptionsBase @@ -9,6 +8,6 @@ namespace SharpCompress.Common /// public bool LeaveStreamOpen { get; set; } = true; - public Encoding ForceEncoding { get; set; } + public ArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding(); } } \ No newline at end of file diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index d41fa76b..1b539eb7 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -68,12 +68,12 @@ namespace SharpCompress.Common.Rar.Headers } else { - FileName = DecodeString(fileNameBytes); + FileName = ArchiveEncoding.Decode(fileNameBytes); } } else { - FileName = DecodeString(fileNameBytes); + FileName = ArchiveEncoding.Decode(fileNameBytes); } FileName = ConvertPath(FileName, HostOS); } @@ -118,12 +118,6 @@ namespace SharpCompress.Common.Rar.Headers } } - //only the full .net framework will do other code pages than unicode/utf8 - private string DecodeString(byte[] bytes) - { - return (ForceEncoding ?? ArchiveEncoding.Default).GetString(bytes, 0, bytes.Length); - } - private long UInt32To64(uint x, uint y) { long l = x; diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs index f0a63a31..30753aee 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs @@ -18,14 +18,16 @@ namespace SharpCompress.Common.Rar.Headers HeaderSize = baseHeader.HeaderSize; AdditionalSize = baseHeader.AdditionalSize; ReadBytes = baseHeader.ReadBytes; + ArchiveEncoding = baseHeader.ArchiveEncoding; } - internal static RarHeader Create(RarCrcBinaryReader reader) + internal static RarHeader Create(RarCrcBinaryReader reader, ArchiveEncoding archiveEncoding) { try { RarHeader header = new RarHeader(); + header.ArchiveEncoding = archiveEncoding; reader.Mark(); header.ReadStartFromReader(reader); header.ReadBytes += reader.CurrentReadByteCount; @@ -109,7 +111,7 @@ namespace SharpCompress.Common.Rar.Headers protected short HeaderSize { get; private set; } - internal Encoding ForceEncoding { get; set; } + internal ArchiveEncoding ArchiveEncoding { get; private set; } /// /// This additional size of the header could be file data diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index cb713c0a..d05840ee 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -30,8 +30,6 @@ namespace SharpCompress.Common.Rar.Headers RarHeader header; while ((header = ReadNextHeader(stream)) != null) { - header.ForceEncoding = Options.ForceEncoding; - yield return header; if (header.HeaderType == HeaderType.EndArchiveHeader) { @@ -135,7 +133,7 @@ namespace SharpCompress.Common.Rar.Headers #endif - RarHeader header = RarHeader.Create(reader); + RarHeader header = RarHeader.Create(reader, Options.ArchiveEncoding); if (header == null) { return null; diff --git a/src/SharpCompress/Common/Rar/RarFilePart.cs b/src/SharpCompress/Common/Rar/RarFilePart.cs index d52fedea..5c05cc80 100644 --- a/src/SharpCompress/Common/Rar/RarFilePart.cs +++ b/src/SharpCompress/Common/Rar/RarFilePart.cs @@ -9,6 +9,7 @@ namespace SharpCompress.Common.Rar internal abstract class RarFilePart : FilePart { internal RarFilePart(MarkHeader mh, FileHeader fh) + : base(fh.ArchiveEncoding) { MarkHeader = mh; FileHeader = fh; diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index 13ac91b6..9dec4aa0 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs @@ -7,14 +7,15 @@ namespace SharpCompress.Common.SevenZip { internal class SevenZipFilePart : FilePart { - private CompressionType? type; - private readonly Stream stream; - private readonly ArchiveDatabase database; + private CompressionType? _type; + private readonly Stream _stream; + private readonly ArchiveDatabase _database; - internal SevenZipFilePart(Stream stream, ArchiveDatabase database, int index, CFileItem fileEntry) + internal SevenZipFilePart(Stream stream, ArchiveDatabase database, int index, CFileItem fileEntry, ArchiveEncoding archiveEncoding) + : base(archiveEncoding) { - this.stream = stream; - this.database = database; + this._stream = stream; + this._database = database; Index = index; Header = fileEntry; if (Header.HasStream) @@ -41,14 +42,14 @@ namespace SharpCompress.Common.SevenZip { return null; } - var folderStream = database.GetFolderStream(stream, Folder, null); + var folderStream = _database.GetFolderStream(_stream, Folder, null); - int firstFileIndex = database.FolderStartFileIndex[database.Folders.IndexOf(Folder)]; + int firstFileIndex = _database.FolderStartFileIndex[_database.Folders.IndexOf(Folder)]; int skipCount = Index - firstFileIndex; long skipSize = 0; for (int i = 0; i < skipCount; i++) { - skipSize += database.Files[firstFileIndex + i].Size; + skipSize += _database.Files[firstFileIndex + i].Size; } if (skipSize > 0) { @@ -61,11 +62,11 @@ namespace SharpCompress.Common.SevenZip { get { - if (type == null) + if (_type == null) { - type = GetCompression(); + _type = GetCompression(); } - return type.Value; + return _type.Value; } } @@ -84,7 +85,7 @@ namespace SharpCompress.Common.SevenZip { var coder = Folder.Coders.First(); switch (coder.MethodId.Id) - { + { case k_LZMA: case k_LZMA2: { diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 79528835..a03495f0 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -9,6 +9,11 @@ namespace SharpCompress.Common.Tar.Headers { internal static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + public TarHeader(ArchiveEncoding archiveEncoding) + { + ArchiveEncoding = archiveEncoding; + } + internal string Name { get; set; } //internal int Mode { get; set; } @@ -20,7 +25,7 @@ namespace SharpCompress.Common.Tar.Headers internal DateTime LastModifiedTime { get; set; } internal EntryType EntryType { get; set; } internal Stream PackedStream { get; set; } - internal Encoding ForceEncoding { get; set; } + internal ArchiveEncoding ArchiveEncoding { get; } internal const int BlockSize = 512; @@ -32,7 +37,7 @@ namespace SharpCompress.Common.Tar.Headers WriteOctalBytes(0, buffer, 108, 8); // owner ID WriteOctalBytes(0, buffer, 116, 8); // group ID - //Encoding.UTF8.GetBytes("magic").CopyTo(buffer, 257); + //ArchiveEncoding.UTF8.GetBytes("magic").CopyTo(buffer, 257); if (Name.Length > 100) { // Set mock filename and filetype to indicate the next block is the actual name of the file @@ -73,7 +78,7 @@ namespace SharpCompress.Common.Tar.Headers private void WriteLongFilenameHeader(Stream output) { - byte[] nameBytes = (ForceEncoding ?? ArchiveEncoding.Default).GetBytes(Name); + byte[] nameBytes = ArchiveEncoding.Encode(Name); output.Write(nameBytes, 0, nameBytes.Length); // pad to multiple of BlockSize bytes, and make sure a terminating null is added @@ -100,7 +105,7 @@ namespace SharpCompress.Common.Tar.Headers } else { - Name = (ForceEncoding ?? ArchiveEncoding.Default).GetString(buffer, 0, 100).TrimNulls(); + Name = ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); } EntryType = ReadEntryType(buffer); @@ -112,12 +117,12 @@ namespace SharpCompress.Common.Tar.Headers long unixTimeStamp = ReadASCIIInt64Base8(buffer, 136, 11); LastModifiedTime = Epoch.AddSeconds(unixTimeStamp).ToLocalTime(); - Magic = (ForceEncoding ?? ArchiveEncoding.Default).GetString(buffer, 257, 6).TrimNulls(); + Magic = ArchiveEncoding.Decode(buffer, 257, 6).TrimNulls(); if (!string.IsNullOrEmpty(Magic) && "ustar".Equals(Magic)) { - string namePrefix = (ForceEncoding ?? ArchiveEncoding.Default).GetString(buffer, 345, 157); + string namePrefix = ArchiveEncoding.Decode(buffer, 345, 157); namePrefix = namePrefix.TrimNulls(); if (!string.IsNullOrEmpty(namePrefix)) { @@ -144,7 +149,7 @@ namespace SharpCompress.Common.Tar.Headers { reader.ReadBytes(remainingBytesToRead); } - return (ForceEncoding ?? ArchiveEncoding.Default).GetString(nameBytes, 0, nameBytes.Length).TrimNulls(); + return ArchiveEncoding.Decode(nameBytes, 0, nameBytes.Length).TrimNulls(); } private static EntryType ReadEntryType(byte[] buffer) diff --git a/src/SharpCompress/Common/Tar/TarEntry.cs b/src/SharpCompress/Common/Tar/TarEntry.cs index f4d0d019..5208bce1 100644 --- a/src/SharpCompress/Common/Tar/TarEntry.cs +++ b/src/SharpCompress/Common/Tar/TarEntry.cs @@ -44,9 +44,9 @@ namespace SharpCompress.Common.Tar internal override IEnumerable Parts => filePart.AsEnumerable(); internal static IEnumerable GetEntries(StreamingMode mode, Stream stream, - CompressionType compressionType, Encoding forceEncoding) + CompressionType compressionType, ArchiveEncoding archiveEncoding) { - foreach (TarHeader h in TarHeaderFactory.ReadHeader(mode, stream, forceEncoding)) + foreach (TarHeader h in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding)) { if (h != null) { diff --git a/src/SharpCompress/Common/Tar/TarFilePart.cs b/src/SharpCompress/Common/Tar/TarFilePart.cs index d3569df1..2aec15f4 100644 --- a/src/SharpCompress/Common/Tar/TarFilePart.cs +++ b/src/SharpCompress/Common/Tar/TarFilePart.cs @@ -6,11 +6,12 @@ namespace SharpCompress.Common.Tar { internal class TarFilePart : FilePart { - private readonly Stream seekableStream; + private readonly Stream _seekableStream; internal TarFilePart(TarHeader header, Stream seekableStream) + : base(header.ArchiveEncoding) { - this.seekableStream = seekableStream; + this._seekableStream = seekableStream; Header = header; } @@ -20,10 +21,10 @@ namespace SharpCompress.Common.Tar internal override Stream GetCompressedStream() { - if (seekableStream != null) + if (_seekableStream != null) { - seekableStream.Position = Header.DataStartPosition.Value; - return new ReadOnlySubStream(seekableStream, Header.Size); + _seekableStream.Position = Header.DataStartPosition.Value; + return new ReadOnlySubStream(_seekableStream, Header.Size); } return Header.PackedStream; } diff --git a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs index e9ca829c..4671f094 100644 --- a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs +++ b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs @@ -8,7 +8,7 @@ namespace SharpCompress.Common.Tar { internal static class TarHeaderFactory { - internal static IEnumerable ReadHeader(StreamingMode mode, Stream stream, Encoding forceEncoding) + internal static IEnumerable ReadHeader(StreamingMode mode, Stream stream, ArchiveEncoding archiveEncoding) { while (true) { @@ -16,10 +16,7 @@ namespace SharpCompress.Common.Tar try { BinaryReader reader = new BinaryReader(stream); - header = new TarHeader() - { - ForceEncoding = forceEncoding - }; + header = new TarHeader(archiveEncoding); if (!header.Read(reader)) { diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index 7282d640..e7502d26 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -6,8 +6,8 @@ namespace SharpCompress.Common.Zip.Headers { internal class DirectoryEntryHeader : ZipFileEntry { - public DirectoryEntryHeader() - : base(ZipHeaderType.DirectoryEntry) + public DirectoryEntryHeader(ArchiveEncoding archiveEncoding) + : base(ZipHeaderType.DirectoryEntry, archiveEncoding) { } @@ -31,10 +31,10 @@ namespace SharpCompress.Common.Zip.Headers RelativeOffsetOfEntryHeader = reader.ReadUInt32(); byte[] name = reader.ReadBytes(nameLength); - Name = DecodeString(name); + Name = ArchiveEncoding.Decode(name); byte[] extra = reader.ReadBytes(extraLength); byte[] comment = reader.ReadBytes(commentLength); - Comment = DecodeString(comment); + Comment = ArchiveEncoding.Decode(comment); LoadExtra(extra); var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField); diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index d63c4f83..2b89385b 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -6,8 +6,8 @@ namespace SharpCompress.Common.Zip.Headers { internal class LocalEntryHeader : ZipFileEntry { - public LocalEntryHeader() - : base(ZipHeaderType.LocalEntry) + public LocalEntryHeader(ArchiveEncoding archiveEncoding) + : base(ZipHeaderType.LocalEntry, archiveEncoding) { } @@ -25,7 +25,7 @@ namespace SharpCompress.Common.Zip.Headers ushort extraLength = reader.ReadUInt16(); byte[] name = reader.ReadBytes(nameLength); byte[] extra = reader.ReadBytes(extraLength); - Name = DecodeString(name); + Name = ArchiveEncoding.Decode(name); LoadExtra(extra); var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField); diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index 0266b0c1..594d89a0 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -8,10 +8,11 @@ namespace SharpCompress.Common.Zip.Headers { internal abstract class ZipFileEntry : ZipHeader { - protected ZipFileEntry(ZipHeaderType type) + protected ZipFileEntry(ZipHeaderType type, ArchiveEncoding archiveEncoding) : base(type) { Extra = new List(); + ArchiveEncoding = archiveEncoding; } internal bool IsDirectory @@ -29,40 +30,10 @@ namespace SharpCompress.Common.Zip.Headers && Name.EndsWith("\\"); } } - - protected string DecodeString(byte[] str) - { - if (ForceEncoding != null) - { - return ForceEncoding.GetString(str, 0, str.Length); - } - - if (FlagUtility.HasFlag(Flags, HeaderFlags.UTF8)) - { - return Encoding.UTF8.GetString(str, 0, str.Length); - } - - return ArchiveEncoding.Default.GetString(str, 0, str.Length); - } - - protected byte[] EncodeString(string str) - { - if (ForceEncoding != null) - { - return ForceEncoding.GetBytes(str); - } - - if (FlagUtility.HasFlag(Flags, HeaderFlags.UTF8)) - { - return Encoding.UTF8.GetBytes(str); - } - - return ArchiveEncoding.Default.GetBytes(str); - } - + internal Stream PackedStream { get; set; } - internal Encoding ForceEncoding { get; set; } + internal ArchiveEncoding ArchiveEncoding { get; } internal string Name { get; set; } diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index 5d77a086..b0e5be75 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs @@ -9,9 +9,11 @@ namespace SharpCompress.Common.Zip { private static readonly CRC32 crc32 = new CRC32(); private readonly UInt32[] _Keys = {0x12345678, 0x23456789, 0x34567890}; + private readonly ArchiveEncoding _archiveEncoding; - private PkwareTraditionalEncryptionData(string password) + private PkwareTraditionalEncryptionData(string password, ArchiveEncoding archiveEncoding) { + _archiveEncoding = archiveEncoding; Initialize(password); } @@ -27,7 +29,7 @@ namespace SharpCompress.Common.Zip public static PkwareTraditionalEncryptionData ForRead(string password, ZipFileEntry header, byte[] encryptionHeader) { - var encryptor = new PkwareTraditionalEncryptionData(password); + var encryptor = new PkwareTraditionalEncryptionData(password, header.ArchiveEncoding); byte[] plainTextHeader = encryptor.Decrypt(encryptionHeader, encryptionHeader.Length); if (plainTextHeader[11] != (byte)((header.Crc >> 24) & 0xff)) { @@ -93,17 +95,12 @@ namespace SharpCompress.Common.Zip } } - internal static byte[] StringToByteArray(string value, Encoding encoding) + internal byte[] StringToByteArray(string value) { - byte[] a = encoding.GetBytes(value); + byte[] a = _archiveEncoding.Password.GetBytes(value); return a; } - internal static byte[] StringToByteArray(string value) - { - return StringToByteArray(value, ArchiveEncoding.Password); - } - private void UpdateKeys(byte byteValue) { _Keys[0] = (UInt32)crc32.ComputeCrc32((int)_Keys[0], byteValue); diff --git a/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs b/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs index 73600aa1..2364eb27 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs @@ -5,21 +5,21 @@ namespace SharpCompress.Common.Zip { internal class SeekableZipFilePart : ZipFilePart { - private bool isLocalHeaderLoaded; - private readonly SeekableZipHeaderFactory headerFactory; + private bool _isLocalHeaderLoaded; + private readonly SeekableZipHeaderFactory _headerFactory; internal SeekableZipFilePart(SeekableZipHeaderFactory headerFactory, DirectoryEntryHeader header, Stream stream) : base(header, stream) { - this.headerFactory = headerFactory; + this._headerFactory = headerFactory; } internal override Stream GetCompressedStream() { - if (!isLocalHeaderLoaded) + if (!_isLocalHeaderLoaded) { LoadLocalHeader(); - isLocalHeaderLoaded = true; + _isLocalHeaderLoaded = true; } return base.GetCompressedStream(); } @@ -29,7 +29,7 @@ namespace SharpCompress.Common.Zip private void LoadLocalHeader() { bool hasData = Header.HasData; - Header = headerFactory.GetLocalHeader(BaseStream, Header as DirectoryEntryHeader); + Header = _headerFactory.GetLocalHeader(BaseStream, Header as DirectoryEntryHeader); Header.HasData = hasData; } diff --git a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs index 03d97966..897b5a0a 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs @@ -10,10 +10,10 @@ namespace SharpCompress.Common.Zip internal class SeekableZipHeaderFactory : ZipHeaderFactory { private const int MAX_ITERATIONS_FOR_DIRECTORY_HEADER = 4096; - private bool zip64; + private bool _zip64; - internal SeekableZipHeaderFactory(string password, Encoding forceEncoding) - : base(StreamingMode.Seekable, password, forceEncoding) + internal SeekableZipHeaderFactory(string password, ArchiveEncoding archiveEncoding) + : base(StreamingMode.Seekable, password, archiveEncoding) { } @@ -27,7 +27,7 @@ namespace SharpCompress.Common.Zip if (entry.IsZip64) { - zip64 = true; + _zip64 = true; SeekBackToHeader(stream, reader, ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR); var zip64Locator = new Zip64DirectoryEndLocatorHeader(); zip64Locator.Read(reader); @@ -51,7 +51,7 @@ namespace SharpCompress.Common.Zip { stream.Position = position; uint signature = reader.ReadUInt32(); - var directoryEntryHeader = ReadHeader(signature, reader, zip64) as DirectoryEntryHeader; + var directoryEntryHeader = ReadHeader(signature, reader, _zip64) as DirectoryEntryHeader; position = stream.Position; if (directoryEntryHeader == null) { @@ -92,7 +92,7 @@ namespace SharpCompress.Common.Zip stream.Seek(directoryEntryHeader.RelativeOffsetOfEntryHeader, SeekOrigin.Begin); BinaryReader reader = new BinaryReader(stream); uint signature = reader.ReadUInt32(); - var localEntryHeader = ReadHeader(signature, reader, zip64) as LocalEntryHeader; + var localEntryHeader = ReadHeader(signature, reader, _zip64) as LocalEntryHeader; if (localEntryHeader == null) { throw new InvalidOperationException(); diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 92ae351a..1f4df93a 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -8,8 +8,8 @@ namespace SharpCompress.Common.Zip { internal class StreamingZipHeaderFactory : ZipHeaderFactory { - internal StreamingZipHeaderFactory(string password, Encoding forceEncoding = null) - : base(StreamingMode.Streaming, password, forceEncoding) + internal StreamingZipHeaderFactory(string password, ArchiveEncoding archiveEncoding) + : base(StreamingMode.Streaming, password, archiveEncoding) { } diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index 8e09461e..adf1340a 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -15,6 +15,7 @@ namespace SharpCompress.Common.Zip internal abstract class ZipFilePart : FilePart { internal ZipFilePart(ZipFileEntry header, Stream stream) + : base(header.ArchiveEncoding) { Header = header; header.Part = this; diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 56c05fed..9fcf9348 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -24,13 +24,13 @@ namespace SharpCompress.Common.Zip protected LocalEntryHeader lastEntryHeader; private readonly string password; private readonly StreamingMode mode; - private readonly Encoding forceEncoding; + private readonly ArchiveEncoding archiveEncoding; - protected ZipHeaderFactory(StreamingMode mode, string password, Encoding forceEncoding) + protected ZipHeaderFactory(StreamingMode mode, string password, ArchiveEncoding archiveEncoding) { this.mode = mode; this.password = password; - this.forceEncoding = forceEncoding; + this.archiveEncoding = archiveEncoding; } protected ZipHeader ReadHeader(uint headerBytes, BinaryReader reader, bool zip64 = false) @@ -38,26 +38,20 @@ namespace SharpCompress.Common.Zip switch (headerBytes) { case ENTRY_HEADER_BYTES: - { - var entryHeader = new LocalEntryHeader() - { - ForceEncoding = forceEncoding - }; - entryHeader.Read(reader); - LoadHeader(entryHeader, reader.BaseStream); + { + var entryHeader = new LocalEntryHeader(archiveEncoding); + entryHeader.Read(reader); + LoadHeader(entryHeader, reader.BaseStream); - lastEntryHeader = entryHeader; - return entryHeader; - } + lastEntryHeader = entryHeader; + return entryHeader; + } case DIRECTORY_START_HEADER_BYTES: - { - var entry = new DirectoryEntryHeader() - { - ForceEncoding = forceEncoding - }; - entry.Read(reader); - return entry; - } + { + var entry = new DirectoryEntryHeader(archiveEncoding); + entry.Read(reader); + return entry; + } case POST_DATA_DESCRIPTOR: { if (FlagUtility.HasFlag(lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)) diff --git a/src/SharpCompress/Compressors/Deflate/GZipStream.cs b/src/SharpCompress/Compressors/Deflate/GZipStream.cs index 80be7cdc..6784b6d4 100644 --- a/src/SharpCompress/Compressors/Deflate/GZipStream.cs +++ b/src/SharpCompress/Compressors/Deflate/GZipStream.cs @@ -36,39 +36,39 @@ namespace SharpCompress.Compressors.Deflate { public class GZipStream : Stream { - internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + internal static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public DateTime? LastModified { get; set; } - private string comment; - private string fileName; + private string _comment; + private string _fileName; internal ZlibBaseStream BaseStream; - private bool disposed; - private bool firstReadDone; - private int headerByteCount; + private bool _disposed; + private bool _firstReadDone; + private int _headerByteCount; - private readonly Encoding forceEncoding; + private readonly Encoding _encoding; public GZipStream(Stream stream, CompressionMode mode) - : this(stream, mode, CompressionLevel.Default, false) + : this(stream, mode, CompressionLevel.Default, false, Encoding.UTF8) { } public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level) - : this(stream, mode, level, false) + : this(stream, mode, level, false, Encoding.UTF8) { } public GZipStream(Stream stream, CompressionMode mode, bool leaveOpen) - : this(stream, mode, CompressionLevel.Default, leaveOpen) + : this(stream, mode, CompressionLevel.Default, leaveOpen, Encoding.UTF8) { } - public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen, Encoding forceEncoding = null) + public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen, Encoding encoding) { - BaseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.GZIP, leaveOpen, forceEncoding); - this.forceEncoding = forceEncoding; + BaseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.GZIP, leaveOpen, encoding); + _encoding = encoding; } #region Zlib properties @@ -78,7 +78,7 @@ namespace SharpCompress.Compressors.Deflate get => (BaseStream._flushMode); set { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -91,7 +91,7 @@ namespace SharpCompress.Compressors.Deflate get => BaseStream._bufferSize; set { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -127,7 +127,7 @@ namespace SharpCompress.Compressors.Deflate { get { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -153,7 +153,7 @@ namespace SharpCompress.Compressors.Deflate { get { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -183,7 +183,7 @@ namespace SharpCompress.Compressors.Deflate { if (BaseStream._streamMode == ZlibBaseStream.StreamMode.Writer) { - return BaseStream._z.TotalBytesOut + headerByteCount; + return BaseStream._z.TotalBytesOut + _headerByteCount; } if (BaseStream._streamMode == ZlibBaseStream.StreamMode.Reader) { @@ -206,14 +206,14 @@ namespace SharpCompress.Compressors.Deflate { try { - if (!disposed) + if (!_disposed) { if (disposing && (BaseStream != null)) { BaseStream.Dispose(); Crc32 = BaseStream.Crc32; } - disposed = true; + _disposed = true; } } finally @@ -227,7 +227,7 @@ namespace SharpCompress.Compressors.Deflate /// public override void Flush() { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -267,7 +267,7 @@ namespace SharpCompress.Compressors.Deflate /// the number of bytes actually read public override int Read(byte[] buffer, int offset, int count) { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -276,9 +276,9 @@ namespace SharpCompress.Compressors.Deflate // Console.WriteLine("GZipStream::Read(buffer, off({0}), c({1}) = {2}", offset, count, n); // Console.WriteLine( Util.FormatByteArray(buffer, offset, n) ); - if (!firstReadDone) + if (!_firstReadDone) { - firstReadDone = true; + _firstReadDone = true; FileName = BaseStream._GzipFileName; Comment = BaseStream._GzipComment; } @@ -329,7 +329,7 @@ namespace SharpCompress.Compressors.Deflate /// the number of bytes to write. public override void Write(byte[] buffer, int offset, int count) { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } @@ -339,7 +339,7 @@ namespace SharpCompress.Compressors.Deflate if (BaseStream._wantCompress) { // first write in compression, therefore, emit the GZIP header - headerByteCount = EmitHeader(); + _headerByteCount = EmitHeader(); } else { @@ -354,52 +354,52 @@ namespace SharpCompress.Compressors.Deflate public String Comment { - get => comment; + get => _comment; set { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } - comment = value; + _comment = value; } } public string FileName { - get => fileName; + get => _fileName; set { - if (disposed) + if (_disposed) { throw new ObjectDisposedException("GZipStream"); } - fileName = value; - if (fileName == null) + _fileName = value; + if (_fileName == null) { return; } - if (fileName.IndexOf("/") != -1) + if (_fileName.IndexOf("/") != -1) { - fileName = fileName.Replace("/", "\\"); + _fileName = _fileName.Replace("/", "\\"); } - if (fileName.EndsWith("\\")) + if (_fileName.EndsWith("\\")) { throw new InvalidOperationException("Illegal filename"); } - var index = fileName.IndexOf("\\"); + var index = _fileName.IndexOf("\\"); if (index != -1) { // trim any leading path - int length = fileName.Length; + int length = _fileName.Length; int num = length; while (--num >= 0) { - char c = fileName[num]; + char c = _fileName[num]; if (c == '\\') { - fileName = fileName.Substring(num + 1, length - num - 1); + _fileName = _fileName.Substring(num + 1, length - num - 1); } } } @@ -411,9 +411,9 @@ namespace SharpCompress.Compressors.Deflate private int EmitHeader() { byte[] commentBytes = (Comment == null) ? null - : (forceEncoding ?? ArchiveEncoding.Default).GetBytes(Comment); + : _encoding.GetBytes(Comment); byte[] filenameBytes = (FileName == null) ? null - : (forceEncoding ?? ArchiveEncoding.Default).GetBytes(FileName); + : _encoding.GetBytes(FileName); int cbLength = (Comment == null) ? 0 : commentBytes.Length + 1; int fnLength = (FileName == null) ? 0 : filenameBytes.Length + 1; @@ -446,7 +446,7 @@ namespace SharpCompress.Compressors.Deflate { LastModified = DateTime.Now; } - TimeSpan delta = LastModified.Value - UnixEpoch; + TimeSpan delta = LastModified.Value - UNIX_EPOCH; var timet = (Int32)delta.TotalSeconds; DataConverter.LittleEndian.PutBytes(header, i, timet); i += 4; diff --git a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs index a993b1cb..64938b7e 100644 --- a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs +++ b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs @@ -65,7 +65,7 @@ namespace SharpCompress.Compressors.Deflate protected internal DateTime _GzipMtime; protected internal int _gzipHeaderByteCount; - private readonly Encoding forceEncoding; + private readonly Encoding _encoding; internal int Crc32 { @@ -84,7 +84,7 @@ namespace SharpCompress.Compressors.Deflate CompressionLevel level, ZlibStreamFlavor flavor, bool leaveOpen, - Encoding forceEncoding) + Encoding encoding) { _flushMode = FlushType.None; @@ -95,7 +95,7 @@ namespace SharpCompress.Compressors.Deflate _flavor = flavor; _level = level; - this.forceEncoding = forceEncoding; + _encoding = encoding; // workitem 7159 if (flavor == ZlibStreamFlavor.GZIP) @@ -425,7 +425,7 @@ namespace SharpCompress.Compressors.Deflate } while (!done); byte[] buffer = list.ToArray(); - return (forceEncoding ?? ArchiveEncoding.Default).GetString(buffer, 0, buffer.Length); + return _encoding.GetString(buffer, 0, buffer.Length); } private int _ReadAndValidateGzipHeader() diff --git a/src/SharpCompress/Compressors/Deflate/ZlibStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibStream.cs index 38558925..b94ceea8 100644 --- a/src/SharpCompress/Compressors/Deflate/ZlibStream.cs +++ b/src/SharpCompress/Compressors/Deflate/ZlibStream.cs @@ -37,23 +37,23 @@ namespace SharpCompress.Compressors.Deflate private bool _disposed; public ZlibStream(Stream stream, CompressionMode mode) - : this(stream, mode, CompressionLevel.Default, false) + : this(stream, mode, CompressionLevel.Default, false, Encoding.UTF8) { } public ZlibStream(Stream stream, CompressionMode mode, CompressionLevel level) - : this(stream, mode, level, false) + : this(stream, mode, level, false, Encoding.UTF8) { } public ZlibStream(Stream stream, CompressionMode mode, bool leaveOpen) - : this(stream, mode, CompressionLevel.Default, leaveOpen) + : this(stream, mode, CompressionLevel.Default, leaveOpen, Encoding.UTF8) { } - public ZlibStream(Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen, Encoding forceEncoding = null) + public ZlibStream(Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen, Encoding encoding) { - _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.ZLIB, leaveOpen, forceEncoding); + _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.ZLIB, leaveOpen, encoding); } #region Zlib properties diff --git a/src/SharpCompress/Readers/GZip/GZipReader.cs b/src/SharpCompress/Readers/GZip/GZipReader.cs index f5a2fd49..b8265409 100644 --- a/src/SharpCompress/Readers/GZip/GZipReader.cs +++ b/src/SharpCompress/Readers/GZip/GZipReader.cs @@ -33,7 +33,7 @@ namespace SharpCompress.Readers.GZip internal override IEnumerable GetEntries(Stream stream) { - return GZipEntry.GetEntries(stream, Options.ForceEncoding); + return GZipEntry.GetEntries(stream, Options); } } } \ No newline at end of file diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index 805445f2..809ea3b5 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -118,7 +118,7 @@ namespace SharpCompress.Readers.Tar internal override IEnumerable GetEntries(Stream stream) { - return TarEntry.GetEntries(StreamingMode.Streaming, stream, compressionType, Options.ForceEncoding); + return TarEntry.GetEntries(StreamingMode.Streaming, stream, compressionType, Options.ArchiveEncoding); } } } \ No newline at end of file diff --git a/src/SharpCompress/Readers/Zip/ZipReader.cs b/src/SharpCompress/Readers/Zip/ZipReader.cs index 78df2dee..6dfbefb6 100644 --- a/src/SharpCompress/Readers/Zip/ZipReader.cs +++ b/src/SharpCompress/Readers/Zip/ZipReader.cs @@ -8,13 +8,13 @@ namespace SharpCompress.Readers.Zip { public class ZipReader : AbstractReader { - private readonly StreamingZipHeaderFactory headerFactory; + private readonly StreamingZipHeaderFactory _headerFactory; internal ZipReader(Stream stream, ReaderOptions options) : base(options, ArchiveType.Zip) { Volume = new ZipVolume(stream, options); - headerFactory = new StreamingZipHeaderFactory(options.Password, options.ForceEncoding); + _headerFactory = new StreamingZipHeaderFactory(options.Password, options.ArchiveEncoding); } public override ZipVolume Volume { get; } @@ -37,7 +37,7 @@ namespace SharpCompress.Readers.Zip internal override IEnumerable GetEntries(Stream stream) { - foreach (ZipHeader h in headerFactory.ReadStreamHeader(stream)) + foreach (ZipHeader h in _headerFactory.ReadStreamHeader(stream)) { if (h != null) { diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index 24db4234..2251b028 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -8,12 +8,15 @@ namespace SharpCompress.Writers.GZip { public class GZipWriter : AbstractWriter { - private bool wroteToStream; + private bool _wroteToStream; - public GZipWriter(Stream destination, bool leaveOpen = false) - : base(ArchiveType.GZip, new WriterOptions(CompressionType.GZip)) + public GZipWriter(Stream destination, GZipWriterOptions options = null) + : base(ArchiveType.GZip, options ?? new GZipWriterOptions()) { - InitalizeStream(new GZipStream(destination, CompressionMode.Compress, leaveOpen), !leaveOpen); + InitalizeStream(new GZipStream(destination, CompressionMode.Compress, + options?.CompressionLevel ?? CompressionLevel.Default, + WriterOptions.LeaveStreamOpen, + WriterOptions.ArchiveEncoding.GetEncoding()), !WriterOptions.LeaveStreamOpen); } protected override void Dispose(bool isDisposing) @@ -28,7 +31,7 @@ namespace SharpCompress.Writers.GZip public override void Write(string filename, Stream source, DateTime? modificationTime) { - if (wroteToStream) + if (_wroteToStream) { throw new ArgumentException("Can only write a single stream to a GZip file."); } @@ -36,7 +39,7 @@ namespace SharpCompress.Writers.GZip stream.FileName = filename; stream.LastModified = modificationTime; source.TransferTo(stream); - wroteToStream = true; + _wroteToStream = true; } } } \ No newline at end of file diff --git a/src/SharpCompress/Writers/GZip/GZipWriterOptions.cs b/src/SharpCompress/Writers/GZip/GZipWriterOptions.cs new file mode 100644 index 00000000..38c3a723 --- /dev/null +++ b/src/SharpCompress/Writers/GZip/GZipWriterOptions.cs @@ -0,0 +1,28 @@ +using SharpCompress.Common; +using SharpCompress.Compressors.Deflate; + +namespace SharpCompress.Writers.GZip +{ + public class GZipWriterOptions : WriterOptions + { + public GZipWriterOptions() + : base(CompressionType.GZip) + { + } + + internal GZipWriterOptions(WriterOptions options) + : base(options.CompressionType) + { + LeaveStreamOpen = options.LeaveStreamOpen; + ArchiveEncoding = options.ArchiveEncoding; + + var writerOptions = options as GZipWriterOptions; + if (writerOptions != null) + { + CompressionLevel = writerOptions.CompressionLevel; + } + } + + public CompressionLevel CompressionLevel { get; set; } = CompressionLevel.Default; + } +} \ No newline at end of file diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 28457b6a..c4b7b460 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -72,10 +72,7 @@ namespace SharpCompress.Writers.Tar long realSize = size ?? source.Length; - TarHeader header = new TarHeader() - { - ForceEncoding = WriterOptions.ForceEncoding - }; + TarHeader header = new TarHeader(WriterOptions.ArchiveEncoding); header.LastModifiedTime = modificationTime ?? TarHeader.Epoch; header.Name = NormalizeFilename(filename); diff --git a/src/SharpCompress/Writers/WriterFactory.cs b/src/SharpCompress/Writers/WriterFactory.cs index d989d589..b623ee63 100644 --- a/src/SharpCompress/Writers/WriterFactory.cs +++ b/src/SharpCompress/Writers/WriterFactory.cs @@ -19,7 +19,7 @@ namespace SharpCompress.Writers { throw new InvalidFormatException("GZip archives only support GZip compression type."); } - return new GZipWriter(stream, writerOptions.LeaveStreamOpen); + return new GZipWriter(stream, new GZipWriterOptions(writerOptions)); } case ArchiveType.Zip: { diff --git a/src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs b/src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs index eb04ceaa..f4237e91 100644 --- a/src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs +++ b/src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using SharpCompress.Common; using SharpCompress.Common.Zip; using SharpCompress.Common.Zip.Headers; using SharpCompress.Converters; @@ -11,14 +12,14 @@ namespace SharpCompress.Writers.Zip { private readonly ZipCompressionMethod compression; private readonly string fileName; - private readonly Encoding forceEncoding; + private readonly ArchiveEncoding archiveEncoding; - public ZipCentralDirectoryEntry(ZipCompressionMethod compression, string fileName, ulong headerOffset, Encoding forceEncoding) + public ZipCentralDirectoryEntry(ZipCompressionMethod compression, string fileName, ulong headerOffset, ArchiveEncoding archiveEncoding) { this.compression = compression; this.fileName = fileName; HeaderOffset = headerOffset; - this.forceEncoding = forceEncoding; + this.archiveEncoding = archiveEncoding; } internal DateTime? ModificationTime { get; set; } @@ -31,8 +32,8 @@ namespace SharpCompress.Writers.Zip internal uint Write(Stream outputStream) { - byte[] encodedFilename = (forceEncoding ?? Encoding.UTF8).GetBytes(fileName); - byte[] encodedComment = (forceEncoding ?? Encoding.UTF8).GetBytes(Comment); + byte[] encodedFilename = archiveEncoding.Encode(fileName); + byte[] encodedComment = archiveEncoding.Encode(Comment); var zip64_stream = Compressed >= uint.MaxValue || Decompressed >= uint.MaxValue; var zip64 = zip64_stream || HeaderOffset >= uint.MaxValue || Zip64HeaderOffset != 0; @@ -43,7 +44,7 @@ namespace SharpCompress.Writers.Zip var extralength = zip64 ? (2 + 2 + 8 + 8 + 8 + 4) : 0; var version = (byte)(zip64 ? 45 : 20); // Version 20 required for deflate/encryption - HeaderFlags flags = (forceEncoding ?? Encoding.UTF8) == Encoding.UTF8 ? HeaderFlags.UTF8 : HeaderFlags.None; + HeaderFlags flags = Equals(archiveEncoding.GetEncoding(), Encoding.UTF8) ? HeaderFlags.UTF8 : HeaderFlags.None; if (!outputStream.CanSeek) { // Cannot use data descriptors with zip64: diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index defeb854..2c34c52f 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -118,7 +118,7 @@ namespace SharpCompress.Writers.Zip entryPath = NormalizeFilename(entryPath); options.ModificationDateTime = options.ModificationDateTime ?? DateTime.Now; options.EntryComment = options.EntryComment ?? string.Empty; - var entry = new ZipCentralDirectoryEntry(compression, entryPath, (ulong)streamPosition, WriterOptions.ForceEncoding) + var entry = new ZipCentralDirectoryEntry(compression, entryPath, (ulong)streamPosition, WriterOptions.ArchiveEncoding) { Comment = options.EntryComment, ModificationTime = options.ModificationDateTime @@ -155,7 +155,7 @@ namespace SharpCompress.Writers.Zip throw new NotSupportedException("Zip64 extensions are not supported on non-seekable streams"); var explicitZipCompressionInfo = ToZipCompressionMethod(zipWriterEntryOptions.CompressionType ?? compressionType); - byte[] encodedFilename = (WriterOptions.ForceEncoding ?? ArchiveEncoding.Default).GetBytes(filename); + byte[] encodedFilename = WriterOptions.ArchiveEncoding.Encode(filename); OutputStream.Write(DataConverter.LittleEndian.GetBytes(ZipHeaderFactory.ENTRY_HEADER_BYTES), 0, 4); if (explicitZipCompressionInfo == ZipCompressionMethod.Deflate) @@ -169,7 +169,7 @@ namespace SharpCompress.Writers.Zip { OutputStream.Write(new byte[] { 63, 0 }, 0, 2); //version says we used PPMd or LZMA } - HeaderFlags flags = (WriterOptions.ForceEncoding ?? ArchiveEncoding.Default) == Encoding.UTF8 ? HeaderFlags.UTF8 : 0; + HeaderFlags flags = Equals(WriterOptions.ArchiveEncoding.GetEncoding(), Encoding.UTF8) ? HeaderFlags.UTF8 : 0; if (!OutputStream.CanSeek) { flags |= HeaderFlags.UsePostDataDescriptor; @@ -214,7 +214,7 @@ namespace SharpCompress.Writers.Zip private void WriteEndRecord(ulong size) { - byte[] encodedComment = (WriterOptions.ForceEncoding ?? ArchiveEncoding.Default).GetBytes(zipComment); + byte[] encodedComment = WriterOptions.ArchiveEncoding.Encode(zipComment); var zip64 = isZip64 || entries.Count > ushort.MaxValue || streamPosition >= uint.MaxValue || size >= uint.MaxValue; var sizevalue = size >= uint.MaxValue ? uint.MaxValue : (uint)size; diff --git a/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs b/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs index 81c2afbe..660e567a 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriterOptions.cs @@ -15,8 +15,15 @@ namespace SharpCompress.Writers.Zip : base(options.CompressionType) { LeaveStreamOpen = options.LeaveStreamOpen; - if (options is ZipWriterOptions) - UseZip64 = ((ZipWriterOptions)options).UseZip64; + ArchiveEncoding = options.ArchiveEncoding; + + var writerOptions = options as ZipWriterOptions; + if (writerOptions != null) + { + UseZip64 = writerOptions.UseZip64; + DeflateCompressionLevel = writerOptions.DeflateCompressionLevel; + ArchiveComment = writerOptions.ArchiveComment; + } } /// /// When CompressionType.Deflate is used, this property is referenced. Defaults to CompressionLevel.Default.