cleanup and run csharpier

This commit is contained in:
Adam Hathcock
2022-12-20 13:45:47 +00:00
parent 2dae2b7984
commit 970e31a1b1
356 changed files with 17199 additions and 5194 deletions

View File

@@ -82,7 +82,7 @@ namespace SharpCompress.Algorithms
public static int EvenReduceSum(Vector256<int> accumulator)
{
Vector128<int> vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); // add upper lane to lower lane
vsum = Sse2.Add(vsum, Sse2.Shuffle(vsum, 0b_11_10_11_10)); // add high to low
vsum = Sse2.Add(vsum, Sse2.Shuffle(vsum, 0b_11_10_11_10)); // add high to low
// Vector128<int>.ToScalar() isn't optimized pre-net5.0 https://github.com/dotnet/runtime/pull/37882
return Sse2.ConvertToInt32(vsum);
@@ -107,11 +107,42 @@ namespace SharpCompress.Algorithms
private const int BlockSize = 1 << 5;
// The C# compiler emits this as a compile-time constant embedded in the PE file.
private static ReadOnlySpan<byte> Tap1Tap2 => new byte[]
{
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, // tap1
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 // tap2
};
private static ReadOnlySpan<byte> Tap1Tap2 =>
new byte[]
{
32,
31,
30,
29,
28,
27,
26,
25,
24,
23,
22,
21,
20,
19,
18,
17, // tap1
16,
15,
14,
13,
12,
11,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1 // tap2
};
#endif
/// <summary>
@@ -120,8 +151,7 @@ namespace SharpCompress.Algorithms
/// <param name="buffer">The readonly span of bytes.</param>
/// <returns>The <see cref="uint"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint Calculate(ReadOnlySpan<byte> buffer)
=> Calculate(SeedValue, buffer);
public static uint Calculate(ReadOnlySpan<byte> buffer) => Calculate(SeedValue, buffer);
/// <summary>
/// Calculates the Adler32 checksum with the bytes taken from the span and seed.
@@ -181,7 +211,7 @@ namespace SharpCompress.Algorithms
while (blocks > 0)
{
uint n = NMAX / BlockSize; /* The NMAX constraint. */
uint n = NMAX / BlockSize; /* The NMAX constraint. */
if (n > blocks)
{
n = blocks;
@@ -206,23 +236,28 @@ namespace SharpCompress.Algorithms
// Horizontally add the bytes for s1, multiply-adds the
// bytes by [ 32, 31, 30, ... ] for s2.
v_s1 = Sse2.Add(v_s1, Sse2.SumAbsoluteDifferences(bytes1, zero).AsUInt32());
v_s1 = Sse2.Add(
v_s1,
Sse2.SumAbsoluteDifferences(bytes1, zero).AsUInt32()
);
Vector128<short> mad1 = Ssse3.MultiplyAddAdjacent(bytes1, tap1);
v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad1, ones).AsUInt32());
v_s1 = Sse2.Add(v_s1, Sse2.SumAbsoluteDifferences(bytes2, zero).AsUInt32());
v_s1 = Sse2.Add(
v_s1,
Sse2.SumAbsoluteDifferences(bytes2, zero).AsUInt32()
);
Vector128<short> mad2 = Ssse3.MultiplyAddAdjacent(bytes2, tap2);
v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad2, ones).AsUInt32());
localBufferPtr += BlockSize;
}
while (--n > 0);
} while (--n > 0);
v_s2 = Sse2.Add(v_s2, Sse2.ShiftLeftLogical(v_ps, 5));
// Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
const byte S2301 = 0b1011_0001; // A B C D -> B A D C
const byte S1032 = 0b0100_1110; // A B C D -> C D A B
const byte S2301 = 0b1011_0001; // A B C D -> B A D C
const byte S1032 = 0b0100_1110; // A B C D -> C D A B
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S1032));
@@ -262,7 +297,40 @@ namespace SharpCompress.Algorithms
Vector256<byte> zero = Vector256<byte>.Zero;
var dot3v = Vector256.Create((short)1);
var dot2v = Vector256.Create(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
var dot2v = Vector256.Create(
32,
31,
30,
29,
28,
27,
26,
25,
24,
23,
22,
21,
20,
19,
18,
17,
16,
15,
14,
13,
12,
11,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1
);
// Process n blocks of data. At most NMAX data bytes can be
// processed before s2 must be reduced modulo BASE.
@@ -325,7 +393,12 @@ namespace SharpCompress.Algorithms
}
}
private static unsafe void HandleLeftOver(byte* localBufferPtr, uint length, ref uint s1, ref uint s2)
private static unsafe void HandleLeftOver(
byte* localBufferPtr,
uint length,
ref uint s1,
ref uint s2
)
{
if (length >= 16)
{

View File

@@ -42,13 +42,17 @@ namespace SharpCompress.Archives
lazyVolumes = new LazyReadOnlyCollection<TVolume>(Enumerable.Empty<TVolume>());
lazyEntries = new LazyReadOnlyCollection<TEntry>(Enumerable.Empty<TEntry>());
}
#nullable enable
public ArchiveType Type { get; }
void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry)
{
EntryExtractionBegin?.Invoke(this, new ArchiveExtractionEventArgs<IArchiveEntry>(entry));
EntryExtractionBegin?.Invoke(
this,
new ArchiveExtractionEventArgs<IArchiveEntry>(entry)
);
}
void IArchiveExtractionListener.FireEntryExtractionEnd(IArchiveEntry entry)
@@ -78,12 +82,14 @@ namespace SharpCompress.Archives
/// <summary>
/// The total size of the files compressed in the archive.
/// </summary>
public virtual long TotalSize => Entries.Aggregate(0L, (total, cf) => total + cf.CompressedSize);
public virtual long TotalSize =>
Entries.Aggregate(0L, (total, cf) => total + cf.CompressedSize);
/// <summary>
/// The total size of the files as uncompressed in the archive.
/// </summary>
public virtual long TotalUncompressSize => Entries.Aggregate(0L, (total, cf) => total + cf.Size);
public virtual long TotalUncompressSize =>
Entries.Aggregate(0L, (total, cf) => total + cf.Size);
protected abstract IEnumerable<TVolume> LoadVolumes(SourceStream srcStream);
protected abstract IEnumerable<TEntry> LoadEntries(IEnumerable<TVolume> volumes);
@@ -110,21 +116,34 @@ namespace SharpCompress.Archives
lazyVolumes.EnsureFullyLoaded();
}
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
void IExtractionListener.FireCompressedBytesRead(
long currentPartCompressedBytes,
long compressedReadBytes
)
{
CompressedBytesRead?.Invoke(this, new CompressedBytesReadEventArgs(
currentFilePartCompressedBytesRead: currentPartCompressedBytes,
compressedBytesRead: compressedReadBytes
));
CompressedBytesRead?.Invoke(
this,
new CompressedBytesReadEventArgs(
currentFilePartCompressedBytesRead: currentPartCompressedBytes,
compressedBytesRead: compressedReadBytes
)
);
}
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
void IExtractionListener.FireFilePartExtractionBegin(
string name,
long size,
long compressedSize
)
{
FilePartExtractionBegin?.Invoke(this, new FilePartExtractionBeginEventArgs(
compressedSize: compressedSize,
size: size,
name: name
));
FilePartExtractionBegin?.Invoke(
this,
new FilePartExtractionBeginEventArgs(
compressedSize: compressedSize,
size: size,
name: name
)
);
}
/// <summary>

View File

@@ -9,7 +9,9 @@ using SharpCompress.Writers;
namespace SharpCompress.Archives
{
public abstract class AbstractWritableArchive<TEntry, TVolume> : AbstractArchive<TEntry, TVolume>, IWritableArchive
public abstract class AbstractWritableArchive<TEntry, TVolume>
: AbstractArchive<TEntry, TVolume>,
IWritableArchive
where TEntry : IArchiveEntry
where TVolume : IVolume
{
@@ -29,6 +31,7 @@ namespace SharpCompress.Archives
archive.RebuildModifiedCollection();
}
}
private readonly List<TEntry> newEntries = new List<TEntry>();
private readonly List<TEntry> removedEntries = new List<TEntry>();
@@ -36,15 +39,10 @@ namespace SharpCompress.Archives
private bool hasModifications;
private bool pauseRebuilding;
internal AbstractWritableArchive(ArchiveType type)
: base(type)
{
}
internal AbstractWritableArchive(ArchiveType type) : base(type) { }
internal AbstractWritableArchive(ArchiveType type, SourceStream srcStream)
: base(type, srcStream)
{
}
: base(type, srcStream) { }
public override ICollection<TEntry> Entries
{
@@ -75,7 +73,10 @@ namespace SharpCompress.Archives
modifiedEntries.AddRange(OldEntries.Concat(newEntries));
}
private IEnumerable<TEntry> OldEntries { get { return base.Entries.Where(x => !removedEntries.Contains(x)); } }
private IEnumerable<TEntry> OldEntries
{
get { return base.Entries.Where(x => !removedEntries.Contains(x)); }
}
public void RemoveEntry(TEntry entry)
{
@@ -91,19 +92,29 @@ namespace SharpCompress.Archives
RemoveEntry((TEntry)entry);
}
public TEntry AddEntry(string key, Stream source,
long size = 0, DateTime? modified = null)
public TEntry AddEntry(string key, Stream source, long size = 0, DateTime? modified = null)
{
return AddEntry(key, source, false, size, modified);
}
IArchiveEntry IWritableArchive.AddEntry(string key, Stream source, bool closeStream, long size, DateTime? modified)
IArchiveEntry IWritableArchive.AddEntry(
string key,
Stream source,
bool closeStream,
long size,
DateTime? modified
)
{
return AddEntry(key, source, closeStream, size, modified);
}
public TEntry AddEntry(string key, Stream source, bool closeStream,
long size = 0, DateTime? modified = null)
public TEntry AddEntry(
string key,
Stream source,
bool closeStream,
long size = 0,
DateTime? modified = null
)
{
if (key.Length > 0 && key[0] is '/' or '\\')
{
@@ -136,24 +147,43 @@ namespace SharpCompress.Archives
public void SaveTo(Stream stream, WriterOptions options)
{
//reset streams of new entries
newEntries.Cast<IWritableArchiveEntry>().ForEach(x => x.Stream.Seek(0, SeekOrigin.Begin));
newEntries
.Cast<IWritableArchiveEntry>()
.ForEach(x => x.Stream.Seek(0, SeekOrigin.Begin));
SaveTo(stream, options, OldEntries, newEntries);
}
protected TEntry CreateEntry(string key, Stream source, long size, DateTime? modified,
bool closeStream)
protected TEntry CreateEntry(
string key,
Stream source,
long size,
DateTime? modified,
bool closeStream
)
{
if (!source.CanRead || !source.CanSeek)
{
throw new ArgumentException("Streams must be readable and seekable to use the Writing Archive API");
throw new ArgumentException(
"Streams must be readable and seekable to use the Writing Archive API"
);
}
return CreateEntryInternal(key, source, size, modified, closeStream);
}
protected abstract TEntry CreateEntryInternal(string key, Stream source, long size, DateTime? modified,
bool closeStream);
protected abstract TEntry CreateEntryInternal(
string key,
Stream source,
long size,
DateTime? modified,
bool closeStream
);
protected abstract void SaveTo(Stream stream, WriterOptions options, IEnumerable<TEntry> oldEntries, IEnumerable<TEntry> newEntries);
protected abstract void SaveTo(
Stream stream,
WriterOptions options,
IEnumerable<TEntry> oldEntries,
IEnumerable<TEntry> newEntries
);
public override void Dispose()
{

View File

@@ -31,14 +31,13 @@ namespace SharpCompress.Archives
public static IWritableArchive Create(ArchiveType type)
{
var factory = Factories.Factory
.Factories
var factory = Factories.Factory.Factories
.OfType<IWriteableArchiveFactory>()
.Where(item => item.KnownArchiveType == type)
.FirstOrDefault();
if (factory != null)
return factory.CreateWriteableArchive();
return factory.CreateWriteableArchive();
throw new NotSupportedException("Cannot create Archives of type: " + type);
}
@@ -60,7 +59,7 @@ namespace SharpCompress.Archives
/// <param name="fileInfo"></param>
/// <param name="options"></param>
public static IArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
{
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return FindFactory<IArchiveFactory>(fileInfo).Open(fileInfo, options);
@@ -105,14 +104,17 @@ namespace SharpCompress.Archives
firstStream.CheckNotNull(nameof(firstStream));
options ??= new ReaderOptions();
return FindFactory<IMultiArchiveFactory>(firstStream).Open(streamsArray, options);
}
return FindFactory<IMultiArchiveFactory>(firstStream).Open(streamsArray, options);
}
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteToDirectory(string sourceArchive, string destinationDirectory,
ExtractionOptions? options = null)
public static void WriteToDirectory(
string sourceArchive,
string destinationDirectory,
ExtractionOptions? options = null
)
{
using IArchive archive = Open(sourceArchive);
foreach (IArchiveEntry entry in archive.Entries)
@@ -121,8 +123,7 @@ namespace SharpCompress.Archives
}
}
private static T FindFactory<T>(FileInfo finfo)
where T : IFactory
private static T FindFactory<T>(FileInfo finfo) where T : IFactory
{
finfo.CheckNotNull(nameof(finfo));
using (Stream stream = finfo.OpenRead())
@@ -131,8 +132,7 @@ namespace SharpCompress.Archives
}
}
private static T FindFactory<T>(Stream stream)
where T: IFactory
private static T FindFactory<T>(Stream stream) where T : IFactory
{
stream.CheckNotNull(nameof(stream));
if (!stream.CanRead || !stream.CanSeek)
@@ -158,7 +158,9 @@ namespace SharpCompress.Archives
var extensions = string.Join(", ", factories.Select(item => item.Name));
throw new InvalidOperationException($"Cannot determine compressed stream type. Supported Archive Formats: {extensions}");
throw new InvalidOperationException(
$"Cannot determine compressed stream type. Supported Archive Formats: {extensions}"
);
}
public static bool IsArchive(string filePath, out ArchiveType? type)
@@ -180,7 +182,7 @@ namespace SharpCompress.Archives
var startPosition = stream.Position;
foreach(var factory in Factories.Factory.Factories)
foreach (var factory in Factories.Factory.Factories)
{
stream.Position = startPosition;
@@ -213,9 +215,9 @@ namespace SharpCompress.Archives
public static IEnumerable<FileInfo> GetFileParts(FileInfo part1)
{
part1.CheckNotNull(nameof(part1));
yield return part1;
yield return part1;
foreach(var factory in Factory.Factories.OfType<IFactory>())
foreach (var factory in Factory.Factories.OfType<IFactory>())
{
int i = 1;
FileInfo? part = factory.GetFilePart(i++, part1);

View File

@@ -18,12 +18,19 @@ namespace SharpCompress.Archives
//split 001, 002 ...
Match m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase);
if (m.Success)
item = new FileInfo(Path.Combine(part1.DirectoryName!, String.Concat(m.Groups[1].Value, (index + 1).ToString().PadLeft(m.Groups[2].Value.Length, '0'))));
item = new FileInfo(
Path.Combine(
part1.DirectoryName!,
String.Concat(
m.Groups[1].Value,
(index + 1).ToString().PadLeft(m.Groups[2].Value.Length, '0')
)
)
);
if (item != null && item.Exists)
return item;
return null;
}
}
}

View File

@@ -33,7 +33,13 @@ namespace SharpCompress.Archives.GZip
public static GZipArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.CheckNotNull(nameof(fileInfo));
return new GZipArchive(new SourceStream(fileInfo, i => ArchiveVolumeFactory.GetFilePart(i, fileInfo), readerOptions ?? new ReaderOptions()));
return new GZipArchive(
new SourceStream(
fileInfo,
i => ArchiveVolumeFactory.GetFilePart(i, fileInfo),
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -41,11 +47,20 @@ namespace SharpCompress.Archives.GZip
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
public static GZipArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
public static GZipArchive Open(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
{
fileInfos.CheckNotNull(nameof(fileInfos));
FileInfo[] files = fileInfos.ToArray();
return new GZipArchive(new SourceStream(files[0], i => i < files.Length ? files[i] : null, readerOptions ?? new ReaderOptions()));
return new GZipArchive(
new SourceStream(
files[0],
i => i < files.Length ? files[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -53,11 +68,20 @@ namespace SharpCompress.Archives.GZip
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
public static GZipArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static GZipArchive Open(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.CheckNotNull(nameof(streams));
Stream[] strms = streams.ToArray();
return new GZipArchive(new SourceStream(strms[0], i => i < strms.Length ? strms[i] : null, readerOptions ?? new ReaderOptions()));
return new GZipArchive(
new SourceStream(
strms[0],
i => i < strms.Length ? strms[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -68,7 +92,9 @@ namespace SharpCompress.Archives.GZip
public static GZipArchive Open(Stream stream, ReaderOptions? readerOptions = null)
{
stream.CheckNotNull(nameof(stream));
return new GZipArchive(new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()));
return new GZipArchive(
new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions())
);
}
public static GZipArchive Create()
@@ -81,10 +107,7 @@ namespace SharpCompress.Archives.GZip
/// </summary>
/// <param name="srcStream"></param>
/// <param name="options"></param>
internal GZipArchive(SourceStream srcStream)
: base(ArchiveType.Tar, srcStream)
{
}
internal GZipArchive(SourceStream srcStream) : base(ArchiveType.Tar, srcStream) { }
protected override IEnumerable<GZipVolume> LoadVolumes(SourceStream srcStream)
{
@@ -92,6 +115,7 @@ namespace SharpCompress.Archives.GZip
int idx = 0;
return srcStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, idx++));
}
public static bool IsGZipFile(string filePath)
{
return IsGZipFile(new FileInfo(filePath));
@@ -140,24 +164,36 @@ namespace SharpCompress.Archives.GZip
return true;
}
internal GZipArchive()
: base(ArchiveType.GZip)
{
}
internal GZipArchive() : base(ArchiveType.GZip) { }
protected override GZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
bool closeStream)
protected override GZipArchiveEntry CreateEntryInternal(
string filePath,
Stream source,
long size,
DateTime? modified,
bool closeStream
)
{
if (Entries.Any())
{
throw new InvalidOperationException("Only one entry is allowed in a GZip Archive");
}
return new GZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream);
return new GZipWritableArchiveEntry(
this,
source,
filePath,
size,
modified,
closeStream
);
}
protected override void SaveTo(Stream stream, WriterOptions options,
IEnumerable<GZipArchiveEntry> oldEntries,
IEnumerable<GZipArchiveEntry> newEntries)
protected override void SaveTo(
Stream stream,
WriterOptions options,
IEnumerable<GZipArchiveEntry> oldEntries,
IEnumerable<GZipArchiveEntry> newEntries
)
{
if (Entries.Count > 1)
{
@@ -165,8 +201,7 @@ namespace SharpCompress.Archives.GZip
}
using (var writer = new GZipWriter(stream, new GZipWriterOptions(options)))
{
foreach (var entry in oldEntries.Concat(newEntries)
.Where(x => !x.IsDirectory))
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using (var entryStream = entry.OpenEntryStream())
{
@@ -176,10 +211,15 @@ namespace SharpCompress.Archives.GZip
}
}
protected override IEnumerable<GZipArchiveEntry> LoadEntries(IEnumerable<GZipVolume> volumes)
protected override IEnumerable<GZipArchiveEntry> LoadEntries(
IEnumerable<GZipVolume> volumes
)
{
Stream stream = volumes.Single().Stream;
yield return new GZipArchiveEntry(this, new GZipFilePart(stream, ReaderOptions.ArchiveEncoding));
yield return new GZipArchiveEntry(
this,
new GZipFilePart(stream, ReaderOptions.ArchiveEncoding)
);
}
protected override IReader CreateReaderForSolidExtraction()

View File

@@ -6,8 +6,7 @@ namespace SharpCompress.Archives.GZip
{
public class GZipArchiveEntry : GZipEntry, IArchiveEntry
{
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part)
: base(part)
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part) : base(part)
{
Archive = archive;
}
@@ -31,4 +30,4 @@ namespace SharpCompress.Archives.GZip
#endregion
}
}
}

View File

@@ -13,9 +13,14 @@ namespace SharpCompress.Archives.GZip
private readonly bool closeStream;
private readonly Stream stream;
internal GZipWritableArchiveEntry(GZipArchive archive, Stream stream,
string path, long size, DateTime? lastModified, bool closeStream)
: base(archive, null)
internal GZipWritableArchiveEntry(
GZipArchive archive,
Stream stream,
string path,
long size,
DateTime? lastModified,
bool closeStream
) : base(archive, null)
{
this.stream = stream;
Key = path;

View File

@@ -20,7 +20,7 @@ namespace SharpCompress.Archives
/// <summary>
/// Use this method to extract all entries in an archive in order.
/// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be
/// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be
/// extracted sequentially for the best performance.
/// </summary>
IReader ExtractAllEntries();
@@ -46,4 +46,4 @@ namespace SharpCompress.Archives
/// </summary>
long TotalUncompressSize { get; }
}
}
}

View File

@@ -21,4 +21,4 @@ namespace SharpCompress.Archives
/// </summary>
IArchive Archive { get; }
}
}
}

View File

@@ -16,7 +16,11 @@ namespace SharpCompress.Archives
var streamListener = (IArchiveExtractionListener)archiveEntry.Archive;
streamListener.EnsureEntriesLoaded();
streamListener.FireEntryExtractionBegin(archiveEntry);
streamListener.FireFilePartExtractionBegin(archiveEntry.Key, archiveEntry.Size, archiveEntry.CompressedSize);
streamListener.FireFilePartExtractionBegin(
archiveEntry.Key,
archiveEntry.Size,
archiveEntry.CompressedSize
);
var entryStream = archiveEntry.OpenEntryStream();
if (entryStream is null)
{
@@ -35,29 +39,41 @@ namespace SharpCompress.Archives
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory,
ExtractionOptions? options = null)
public static void WriteToDirectory(
this IArchiveEntry entry,
string destinationDirectory,
ExtractionOptions? options = null
)
{
ExtractionMethods.WriteEntryToDirectory(entry, destinationDirectory, options,
entry.WriteToFile);
ExtractionMethods.WriteEntryToDirectory(
entry,
destinationDirectory,
options,
entry.WriteToFile
);
}
/// <summary>
/// Extract to specific file
/// </summary>
public static void WriteToFile(this IArchiveEntry entry,
string destinationFileName,
ExtractionOptions? options = null)
public static void WriteToFile(
this IArchiveEntry entry,
string destinationFileName,
ExtractionOptions? options = null
)
{
ExtractionMethods.WriteEntryToFile(entry, destinationFileName, options,
(x, fm) =>
{
using (FileStream fs = File.Open(destinationFileName, fm))
{
entry.WriteTo(fs);
}
});
ExtractionMethods.WriteEntryToFile(
entry,
destinationFileName,
options,
(x, fm) =>
{
using (FileStream fs = File.Open(destinationFileName, fm))
{
entry.WriteTo(fs);
}
}
);
}
}
}
}

View File

@@ -8,8 +8,11 @@ namespace SharpCompress.Archives
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteToDirectory(this IArchive archive, string destinationDirectory,
ExtractionOptions? options = null)
public static void WriteToDirectory(
this IArchive archive,
string destinationDirectory,
ExtractionOptions? options = null
)
{
foreach (IArchiveEntry entry in archive.Entries.Where(x => !x.IsDirectory))
{
@@ -17,4 +20,4 @@ namespace SharpCompress.Archives
}
}
}
}
}

View File

@@ -8,4 +8,4 @@ namespace SharpCompress.Archives
void FireEntryExtractionBegin(IArchiveEntry entry);
void FireEntryExtractionEnd(IArchiveEntry entry);
}
}
}

View File

@@ -16,8 +16,8 @@ namespace SharpCompress.Archives
/// <list type="table">
/// <item><see cref="Factories.TarFactory"/></item>
/// <item><see cref="Factories.RarFactory"/></item>
/// <item><see cref="Factories.ZipFactory"/></item>
/// <item><see cref="Factories.GZipFactory"/></item>
/// <item><see cref="Factories.ZipFactory"/></item>
/// <item><see cref="Factories.GZipFactory"/></item>
/// <item><see cref="Factories.SevenZipFactory"/></item>
/// </list>
/// </remarks>

View File

@@ -16,8 +16,8 @@ namespace SharpCompress.Archives
/// <list type="table">
/// <item><see cref="Factories.TarFactory"/></item>
/// <item><see cref="Factories.RarFactory"/></item>
/// <item><see cref="Factories.ZipFactory"/></item>
/// <item><see cref="Factories.GZipFactory"/></item>
/// <item><see cref="Factories.ZipFactory"/></item>
/// <item><see cref="Factories.GZipFactory"/></item>
/// <item><see cref="Factories.SevenZipFactory"/></item>
/// </list>
/// </remarks>
@@ -35,6 +35,9 @@ namespace SharpCompress.Archives
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IReadOnlyList<System.IO.FileInfo> fileInfos, ReaderOptions? readerOptions = null);
IArchive Open(
IReadOnlyList<System.IO.FileInfo> fileInfos,
ReaderOptions? readerOptions = null
);
}
}

View File

@@ -8,7 +8,13 @@ namespace SharpCompress.Archives
{
void RemoveEntry(IArchiveEntry entry);
IArchiveEntry AddEntry(string key, Stream source, bool closeStream, long size = 0, DateTime? modified = null);
IArchiveEntry AddEntry(
string key,
Stream source,
bool closeStream,
long size = 0,
DateTime? modified = null
);
void SaveTo(Stream stream, WriterOptions options);
@@ -18,4 +24,4 @@ namespace SharpCompress.Archives
/// <returns>IDisposeable to resume entry rebuilding</returns>
IDisposable PauseEntryRebuilding();
}
}
}

View File

@@ -6,4 +6,4 @@ namespace SharpCompress.Archives
{
Stream Stream { get; }
}
}
}

View File

@@ -6,24 +6,40 @@ namespace SharpCompress.Archives
{
public static class IWritableArchiveExtensions
{
public static void AddEntry(this IWritableArchive writableArchive,
string entryPath, string filePath)
public static void AddEntry(
this IWritableArchive writableArchive,
string entryPath,
string filePath
)
{
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
{
throw new FileNotFoundException("Could not AddEntry: " + filePath);
}
writableArchive.AddEntry(entryPath, new FileInfo(filePath).OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
writableArchive.AddEntry(
entryPath,
new FileInfo(filePath).OpenRead(),
true,
fileInfo.Length,
fileInfo.LastWriteTime
);
}
public static void SaveTo(this IWritableArchive writableArchive, string filePath, WriterOptions options)
public static void SaveTo(
this IWritableArchive writableArchive,
string filePath,
WriterOptions options
)
{
writableArchive.SaveTo(new FileInfo(filePath), options);
}
public static void SaveTo(this IWritableArchive writableArchive, FileInfo fileInfo, WriterOptions options)
public static void SaveTo(
this IWritableArchive writableArchive,
FileInfo fileInfo,
WriterOptions options
)
{
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
{
@@ -33,25 +49,46 @@ namespace SharpCompress.Archives
public static void AddAllFromDirectory(
this IWritableArchive writableArchive,
string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
string filePath,
string searchPattern = "*.*",
SearchOption searchOption = SearchOption.AllDirectories
)
{
using (writableArchive.PauseEntryRebuilding())
{
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
foreach (
var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption)
)
{
var fileInfo = new FileInfo(path);
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
writableArchive.AddEntry(
path.Substring(filePath.Length),
fileInfo.OpenRead(),
true,
fileInfo.Length,
fileInfo.LastWriteTime
);
}
}
}
public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)
public static IArchiveEntry AddEntry(
this IWritableArchive writableArchive,
string key,
FileInfo fileInfo
)
{
if (!fileInfo.Exists)
{
throw new ArgumentException("FileInfo does not exist.");
}
return writableArchive.AddEntry(key, fileInfo.OpenRead(), true, fileInfo.Length, fileInfo.LastWriteTime);
return writableArchive.AddEntry(
key,
fileInfo.OpenRead(),
true,
fileInfo.Length,
fileInfo.LastWriteTime
);
}
}
}
}

View File

@@ -33,7 +33,13 @@ namespace SharpCompress.Archives.Rar
internal override RarFilePart CreateFilePart(MarkHeader markHeader, FileHeader fileHeader)
{
return new FileInfoRarFilePart(this, ReaderOptions.Password, markHeader, fileHeader, FileInfo);
return new FileInfoRarFilePart(
this,
ReaderOptions.Password,
markHeader,
fileHeader,
FileInfo
);
}
internal override IEnumerable<RarFilePart> ReadFileParts()

View File

@@ -5,8 +5,13 @@ namespace SharpCompress.Archives.Rar
{
internal sealed class FileInfoRarFilePart : SeekableFilePart
{
internal FileInfoRarFilePart(FileInfoRarArchiveVolume volume, string? password, MarkHeader mh, FileHeader fh, FileInfo fi)
: base(mh, fh, volume.Index, volume.Stream, password)
internal FileInfoRarFilePart(
FileInfoRarArchiveVolume volume,
string? password,
MarkHeader mh,
FileHeader fh,
FileInfo fi
) : base(mh, fh, volume.Index, volume.Stream, password)
{
FileInfo = fi;
}
@@ -15,11 +20,7 @@ namespace SharpCompress.Archives.Rar
internal override string FilePartName
{
get
{
return "Rar File: " + FileInfo.FullName
+ " File Entry: " + FileHeader.FileName;
}
get { return "Rar File: " + FileInfo.FullName + " File Entry: " + FileHeader.FileName; }
}
}
}

View File

@@ -20,4 +20,4 @@ namespace SharpCompress.Archives.Rar
return archive.Volumes.First().IsMultiVolume;
}
}
}
}

View File

@@ -11,22 +11,19 @@ using SharpCompress.Readers.Rar;
namespace SharpCompress.Archives.Rar
{
public class
RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
{
internal Lazy<IRarUnpack> UnpackV2017 { get; } = new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV2017.Unpack());
internal Lazy<IRarUnpack> UnpackV1 { get; } = new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV1.Unpack());
internal Lazy<IRarUnpack> UnpackV2017 { get; } =
new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV2017.Unpack());
internal Lazy<IRarUnpack> UnpackV1 { get; } =
new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV1.Unpack());
/// <summary>
/// Constructor with a SourceStream able to handle FileInfo and Streams.
/// </summary>
/// <param name="srcStream"></param>
/// <param name="options"></param>
internal RarArchive(SourceStream srcStream)
: base(ArchiveType.Rar, srcStream)
{
}
internal RarArchive(SourceStream srcStream) : base(ArchiveType.Rar, srcStream) { }
protected override IEnumerable<RarArchiveEntry> LoadEntries(IEnumerable<RarVolume> volumes)
{
@@ -44,7 +41,9 @@ namespace SharpCompress.Archives.Rar
streams[1].Position = 0;
base.SrcStream.Position = 0;
return srcStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions, idx++));
return srcStream.Streams.Select(
a => new StreamRarArchiveVolume(a, ReaderOptions, idx++)
);
}
else //split mode or single file
return new StreamRarArchiveVolume(base.SrcStream, ReaderOptions, idx++).AsEnumerable();
@@ -72,7 +71,13 @@ namespace SharpCompress.Archives.Rar
{
filePath.CheckNotNullOrEmpty(nameof(filePath));
FileInfo fileInfo = new FileInfo(filePath);
return new RarArchive(new SourceStream(fileInfo, i => RarArchiveVolumeFactory.GetFilePart(i, fileInfo), options ?? new ReaderOptions()));
return new RarArchive(
new SourceStream(
fileInfo,
i => RarArchiveVolumeFactory.GetFilePart(i, fileInfo),
options ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -83,7 +88,13 @@ namespace SharpCompress.Archives.Rar
public static RarArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
{
fileInfo.CheckNotNull(nameof(fileInfo));
return new RarArchive(new SourceStream(fileInfo, i => RarArchiveVolumeFactory.GetFilePart(i, fileInfo), options ?? new ReaderOptions()));
return new RarArchive(
new SourceStream(
fileInfo,
i => RarArchiveVolumeFactory.GetFilePart(i, fileInfo),
options ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -94,7 +105,9 @@ namespace SharpCompress.Archives.Rar
public static RarArchive Open(Stream stream, ReaderOptions? options = null)
{
stream.CheckNotNull(nameof(stream));
return new RarArchive(new SourceStream(stream, i => null, options ?? new ReaderOptions()));
return new RarArchive(
new SourceStream(stream, i => null, options ?? new ReaderOptions())
);
}
/// <summary>
@@ -102,11 +115,20 @@ namespace SharpCompress.Archives.Rar
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
public static RarArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
public static RarArchive Open(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
{
fileInfos.CheckNotNull(nameof(fileInfos));
FileInfo[] files = fileInfos.ToArray();
return new RarArchive(new SourceStream(files[0], i => i < files.Length ? files[i] : null, readerOptions ?? new ReaderOptions()));
return new RarArchive(
new SourceStream(
files[0],
i => i < files.Length ? files[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -114,14 +136,22 @@ namespace SharpCompress.Archives.Rar
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
public static RarArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static RarArchive Open(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.CheckNotNull(nameof(streams));
Stream[] strms = streams.ToArray();
return new RarArchive(new SourceStream(strms[0], i => i < strms.Length ? strms[i] : null, readerOptions ?? new ReaderOptions()));
return new RarArchive(
new SourceStream(
strms[0],
i => i < strms.Length ? strms[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
public static bool IsRarFile(string filePath)
{
return IsRarFile(new FileInfo(filePath));

View File

@@ -16,7 +16,11 @@ namespace SharpCompress.Archives.Rar
private readonly RarArchive archive;
private readonly ReaderOptions readerOptions;
internal RarArchiveEntry(RarArchive archive, IEnumerable<RarFilePart> parts, ReaderOptions readerOptions)
internal RarArchiveEntry(
RarArchive archive,
IEnumerable<RarFilePart> parts,
ReaderOptions readerOptions
)
{
this.parts = parts.ToList();
this.archive = archive;
@@ -63,10 +67,18 @@ namespace SharpCompress.Archives.Rar
{
if (IsRarV3)
{
return new RarStream(archive.UnpackV1.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
return new RarStream(
archive.UnpackV1.Value,
FileHeader,
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive)
);
}
return new RarStream(archive.UnpackV2017.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
return new RarStream(
archive.UnpackV2017.Value,
FileHeader,
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive)
);
}
public bool IsComplete
@@ -82,7 +94,9 @@ namespace SharpCompress.Archives.Rar
{
if (!readerOptions.DisableCheckIncomplete && !IsComplete)
{
throw new IncompleteArchiveException("ArchiveEntry is incomplete and cannot perform this operation.");
throw new IncompleteArchiveException(
"ArchiveEntry is incomplete and cannot perform this operation."
);
}
}
}

View File

@@ -17,7 +17,9 @@ namespace SharpCompress.Archives.Rar
}
}
private static IEnumerable<IEnumerable<RarFilePart>> GetMatchedFileParts(IEnumerable<RarVolume> parts)
private static IEnumerable<IEnumerable<RarFilePart>> GetMatchedFileParts(
IEnumerable<RarVolume> parts
)
{
var groupedParts = new List<RarFilePart>();
foreach (RarFilePart fp in GetFileParts(parts))
@@ -36,9 +38,11 @@ namespace SharpCompress.Archives.Rar
}
}
internal static IEnumerable<RarArchiveEntry> GetEntries(RarArchive archive,
IEnumerable<RarVolume> rarParts,
ReaderOptions readerOptions)
internal static IEnumerable<RarArchiveEntry> GetEntries(
RarArchive archive,
IEnumerable<RarVolume> rarParts,
ReaderOptions readerOptions
)
{
foreach (var groupedParts in GetMatchedFileParts(rarParts))
{
@@ -46,4 +50,4 @@ namespace SharpCompress.Archives.Rar
}
}
}
}
}

View File

@@ -17,15 +17,38 @@ namespace SharpCompress.Archives.Rar
FileInfo? item = null;
//new style rar - ..part1 | /part01 | part001 ....
Match m = Regex.Match(part1.Name, @"^(.*\.part)([0-9]+)(\.rar)$", RegexOptions.IgnoreCase);
Match m = Regex.Match(
part1.Name,
@"^(.*\.part)([0-9]+)(\.rar)$",
RegexOptions.IgnoreCase
);
if (m.Success)
item = new FileInfo(Path.Combine(part1.DirectoryName!, String.Concat(m.Groups[1].Value, (index + 1).ToString().PadLeft(m.Groups[2].Value.Length, '0'), m.Groups[3].Value)));
item = new FileInfo(
Path.Combine(
part1.DirectoryName!,
String.Concat(
m.Groups[1].Value,
(index + 1).ToString().PadLeft(m.Groups[2].Value.Length, '0'),
m.Groups[3].Value
)
)
);
else
{
//old style - ...rar, .r00, .r01 ...
m = Regex.Match(part1.Name, @"^(.*\.r)(ar|[0-9]+)$", RegexOptions.IgnoreCase);
if (m.Success)
item = new FileInfo(Path.Combine(part1.DirectoryName!, String.Concat(m.Groups[1].Value, index == 0 ? "ar" : (index - 1).ToString().PadLeft(m.Groups[2].Value.Length, '0'))));
item = new FileInfo(
Path.Combine(
part1.DirectoryName!,
String.Concat(
m.Groups[1].Value,
index == 0
? "ar"
: (index - 1).ToString().PadLeft(m.Groups[2].Value.Length, '0')
)
)
);
else //split .001, .002 ....
return ArchiveVolumeFactory.GetFilePart(index, part1);
}
@@ -35,6 +58,5 @@ namespace SharpCompress.Archives.Rar
return null; //no more items
}
}
}

View File

@@ -9,8 +9,13 @@ namespace SharpCompress.Archives.Rar
private readonly Stream stream;
private readonly string? password;
internal SeekableFilePart(MarkHeader mh, FileHeader fh, int index, Stream stream, string? password)
: base(mh, fh, index)
internal SeekableFilePart(
MarkHeader mh,
FileHeader fh,
int index,
Stream stream,
string? password
) : base(mh, fh, index)
{
this.stream = stream;
this.password = password;
@@ -26,6 +31,7 @@ namespace SharpCompress.Archives.Rar
return stream;
}
internal override string FilePartName => "Unknown Stream - File Entry: " + FileHeader.FileName;
internal override string FilePartName =>
"Unknown Stream - File Entry: " + FileHeader.FileName;
}
}

View File

@@ -10,9 +10,7 @@ namespace SharpCompress.Archives.Rar
internal class StreamRarArchiveVolume : RarVolume
{
internal StreamRarArchiveVolume(Stream stream, ReaderOptions options, int index = 0)
: base(StreamingMode.Seekable, stream, options, index)
{
}
: base(StreamingMode.Seekable, stream, options, index) { }
internal override IEnumerable<RarFilePart> ReadFileParts()
{
@@ -21,7 +19,13 @@ namespace SharpCompress.Archives.Rar
internal override RarFilePart CreateFilePart(MarkHeader markHeader, FileHeader fileHeader)
{
return new SeekableFilePart(markHeader, fileHeader, this.Index, Stream, ReaderOptions.Password);
return new SeekableFilePart(
markHeader,
fileHeader,
this.Index,
Stream,
ReaderOptions.Password
);
}
}
}

View File

@@ -15,6 +15,7 @@ namespace SharpCompress.Archives.SevenZip
public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVolume>
{
private ArchiveDatabase database;
/// <summary>
/// Constructor expects a filepath to an existing file.
/// </summary>
@@ -34,7 +35,13 @@ namespace SharpCompress.Archives.SevenZip
public static SevenZipArchive Open(FileInfo fileInfo, ReaderOptions readerOptions = null)
{
fileInfo.CheckNotNull("fileInfo");
return new SevenZipArchive(new SourceStream(fileInfo, i => ArchiveVolumeFactory.GetFilePart(i, fileInfo), readerOptions ?? new ReaderOptions()));
return new SevenZipArchive(
new SourceStream(
fileInfo,
i => ArchiveVolumeFactory.GetFilePart(i, fileInfo),
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -42,11 +49,20 @@ namespace SharpCompress.Archives.SevenZip
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
public static SevenZipArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions readerOptions = null)
public static SevenZipArchive Open(
IEnumerable<FileInfo> fileInfos,
ReaderOptions readerOptions = null
)
{
fileInfos.CheckNotNull(nameof(fileInfos));
FileInfo[] files = fileInfos.ToArray();
return new SevenZipArchive(new SourceStream(files[0], i => i < files.Length ? files[i] : null, readerOptions ?? new ReaderOptions()));
return new SevenZipArchive(
new SourceStream(
files[0],
i => i < files.Length ? files[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -54,11 +70,20 @@ namespace SharpCompress.Archives.SevenZip
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
public static SevenZipArchive Open(IEnumerable<Stream> streams, ReaderOptions readerOptions = null)
public static SevenZipArchive Open(
IEnumerable<Stream> streams,
ReaderOptions readerOptions = null
)
{
streams.CheckNotNull(nameof(streams));
Stream[] strms = streams.ToArray();
return new SevenZipArchive(new SourceStream(strms[0], i => i < strms.Length ? strms[i] : null, readerOptions ?? new ReaderOptions()));
return new SevenZipArchive(
new SourceStream(
strms[0],
i => i < strms.Length ? strms[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -69,7 +94,9 @@ namespace SharpCompress.Archives.SevenZip
public static SevenZipArchive Open(Stream stream, ReaderOptions readerOptions = null)
{
stream.CheckNotNull("stream");
return new SevenZipArchive(new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()));
return new SevenZipArchive(
new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions())
);
}
/// <summary>
@@ -77,10 +104,7 @@ namespace SharpCompress.Archives.SevenZip
/// </summary>
/// <param name="srcStream"></param>
/// <param name="options"></param>
internal SevenZipArchive(SourceStream srcStream)
: base(ArchiveType.SevenZip, srcStream)
{
}
internal SevenZipArchive(SourceStream srcStream) : base(ArchiveType.SevenZip, srcStream) { }
protected override IEnumerable<SevenZipVolume> LoadVolumes(SourceStream srcStream)
{
@@ -106,12 +130,11 @@ namespace SharpCompress.Archives.SevenZip
}
}
internal SevenZipArchive()
: base(ArchiveType.SevenZip)
{
}
internal SevenZipArchive() : base(ArchiveType.SevenZip) { }
protected override IEnumerable<SevenZipArchiveEntry> LoadEntries(IEnumerable<SevenZipVolume> volumes)
protected override IEnumerable<SevenZipArchiveEntry> LoadEntries(
IEnumerable<SevenZipVolume> volumes
)
{
var stream = volumes.Single().Stream;
LoadFactory(stream);
@@ -119,9 +142,14 @@ namespace SharpCompress.Archives.SevenZip
for (int i = 0; i < database._files.Count; i++)
{
var file = database._files[i];
entries[i] = new SevenZipArchiveEntry(this, new SevenZipFilePart(stream, database, i, file, ReaderOptions.ArchiveEncoding));
entries[i] = new SevenZipArchiveEntry(
this,
new SevenZipFilePart(stream, database, i, file, ReaderOptions.ArchiveEncoding)
);
}
foreach (var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder))
foreach (
var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder)
)
{
var isSolid = false;
foreach (var entry in group)
@@ -157,7 +185,8 @@ namespace SharpCompress.Archives.SevenZip
}
}
private static ReadOnlySpan<byte> SIGNATURE => new byte[] { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
private static ReadOnlySpan<byte> SIGNATURE =>
new byte[] { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
private static bool SignatureMatch(Stream stream)
{
@@ -171,7 +200,14 @@ namespace SharpCompress.Archives.SevenZip
return new SevenZipReader(ReaderOptions, this);
}
public override bool IsSolid { get { return Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; } }
public override bool IsSolid
{
get
{
return Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count()
> 1;
}
}
public override long TotalSize
{
@@ -205,7 +241,9 @@ namespace SharpCompress.Archives.SevenZip
{
yield return dir;
}
foreach (var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder))
foreach (
var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder)
)
{
currentFolder = group.Key;
if (group.Key is null)
@@ -214,7 +252,11 @@ namespace SharpCompress.Archives.SevenZip
}
else
{
currentStream = archive.database.GetFolderStream(stream, currentFolder, new PasswordProvider(Options.Password));
currentStream = archive.database.GetFolderStream(
stream,
currentFolder,
new PasswordProvider(Options.Password)
);
}
foreach (var entry in group)
{

View File

@@ -5,8 +5,7 @@ namespace SharpCompress.Archives.SevenZip
{
public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry
{
internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part)
: base(part)
internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part) : base(part)
{
Archive = archive;
}
@@ -25,4 +24,4 @@ namespace SharpCompress.Archives.SevenZip
/// </summary>
public bool IsAnti => FilePart.Header.IsAnti;
}
}
}

View File

@@ -34,7 +34,13 @@ namespace SharpCompress.Archives.Tar
public static TarArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.CheckNotNull(nameof(fileInfo));
return new TarArchive(new SourceStream(fileInfo, i => ArchiveVolumeFactory.GetFilePart(i, fileInfo), readerOptions ?? new ReaderOptions()));
return new TarArchive(
new SourceStream(
fileInfo,
i => ArchiveVolumeFactory.GetFilePart(i, fileInfo),
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -42,11 +48,20 @@ namespace SharpCompress.Archives.Tar
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
public static TarArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
public static TarArchive Open(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
{
fileInfos.CheckNotNull(nameof(fileInfos));
FileInfo[] files = fileInfos.ToArray();
return new TarArchive(new SourceStream(files[0], i => i < files.Length ? files[i] : null, readerOptions ?? new ReaderOptions()));
return new TarArchive(
new SourceStream(
files[0],
i => i < files.Length ? files[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -54,11 +69,20 @@ namespace SharpCompress.Archives.Tar
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
public static TarArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static TarArchive Open(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.CheckNotNull(nameof(streams));
Stream[] strms = streams.ToArray();
return new TarArchive(new SourceStream(strms[0], i => i < strms.Length ? strms[i] : null, readerOptions ?? new ReaderOptions()));
return new TarArchive(
new SourceStream(
strms[0],
i => i < strms.Length ? strms[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -69,7 +93,9 @@ namespace SharpCompress.Archives.Tar
public static TarArchive Open(Stream stream, ReaderOptions? readerOptions = null)
{
stream.CheckNotNull(nameof(stream));
return new TarArchive(new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()));
return new TarArchive(
new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions())
);
}
public static bool IsTarFile(string filePath)
@@ -95,12 +121,13 @@ namespace SharpCompress.Archives.Tar
{
TarHeader tarHeader = new TarHeader(new ArchiveEncoding());
bool readSucceeded = tarHeader.Read(new BinaryReader(stream));
bool isEmptyArchive = tarHeader.Name.Length == 0 && tarHeader.Size == 0 && Enum.IsDefined(typeof(EntryType), tarHeader.EntryType);
bool isEmptyArchive =
tarHeader.Name.Length == 0
&& tarHeader.Size == 0
&& Enum.IsDefined(typeof(EntryType), tarHeader.EntryType);
return readSucceeded || isEmptyArchive;
}
catch
{
}
catch { }
return false;
}
@@ -116,21 +143,21 @@ namespace SharpCompress.Archives.Tar
/// </summary>
/// <param name="srcStream"></param>
/// <param name="options"></param>
internal TarArchive(SourceStream srcStream)
: base(ArchiveType.Tar, srcStream)
{
}
internal TarArchive(SourceStream srcStream) : base(ArchiveType.Tar, srcStream) { }
internal TarArchive()
: base(ArchiveType.Tar)
{
}
internal TarArchive() : base(ArchiveType.Tar) { }
protected override IEnumerable<TarArchiveEntry> LoadEntries(IEnumerable<TarVolume> volumes)
{
Stream stream = volumes.Single().Stream;
TarHeader? previousHeader = null;
foreach (TarHeader? header in TarHeaderFactory.ReadHeader(StreamingMode.Seekable, stream, ReaderOptions.ArchiveEncoding))
foreach (
TarHeader? header in TarHeaderFactory.ReadHeader(
StreamingMode.Seekable,
stream,
ReaderOptions.ArchiveEncoding
)
)
{
if (header != null)
{
@@ -142,8 +169,11 @@ namespace SharpCompress.Archives.Tar
{
if (previousHeader != null)
{
var entry = new TarArchiveEntry(this, new TarFilePart(previousHeader, stream),
CompressionType.None);
var entry = new TarArchiveEntry(
this,
new TarFilePart(previousHeader, stream),
CompressionType.None
);
var oldStreamPos = stream.Position;
@@ -155,7 +185,9 @@ namespace SharpCompress.Archives.Tar
memoryStream.Position = 0;
var bytes = memoryStream.ToArray();
header.Name = ReaderOptions.ArchiveEncoding.Decode(bytes).TrimNulls();
header.Name = ReaderOptions.ArchiveEncoding
.Decode(bytes)
.TrimNulls();
}
}
@@ -163,7 +195,11 @@ namespace SharpCompress.Archives.Tar
previousHeader = null;
}
yield return new TarArchiveEntry(this, new TarFilePart(header, stream), CompressionType.None);
yield return new TarArchiveEntry(
this,
new TarFilePart(header, stream),
CompressionType.None
);
}
}
}
@@ -174,21 +210,35 @@ namespace SharpCompress.Archives.Tar
return new TarArchive();
}
protected override TarArchiveEntry CreateEntryInternal(string filePath, Stream source,
long size, DateTime? modified, bool closeStream)
protected override TarArchiveEntry CreateEntryInternal(
string filePath,
Stream source,
long size,
DateTime? modified,
bool closeStream
)
{
return new TarWritableArchiveEntry(this, source, CompressionType.Unknown, filePath, size, modified,
closeStream);
return new TarWritableArchiveEntry(
this,
source,
CompressionType.Unknown,
filePath,
size,
modified,
closeStream
);
}
protected override void SaveTo(Stream stream, WriterOptions options,
IEnumerable<TarArchiveEntry> oldEntries,
IEnumerable<TarArchiveEntry> newEntries)
protected override void SaveTo(
Stream stream,
WriterOptions options,
IEnumerable<TarArchiveEntry> oldEntries,
IEnumerable<TarArchiveEntry> newEntries
)
{
using (var writer = new TarWriter(stream, new TarWriterOptions(options)))
{
foreach (var entry in oldEntries.Concat(newEntries)
.Where(x => !x.IsDirectory))
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using (var entryStream = entry.OpenEntryStream())
{

View File

@@ -7,8 +7,11 @@ namespace SharpCompress.Archives.Tar
{
public class TarArchiveEntry : TarEntry, IArchiveEntry
{
internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType)
: base(part, compressionType)
internal TarArchiveEntry(
TarArchive archive,
TarFilePart part,
CompressionType compressionType
) : base(part, compressionType)
{
Archive = archive;
}
@@ -26,4 +29,4 @@ namespace SharpCompress.Archives.Tar
#endregion
}
}
}

View File

@@ -13,9 +13,15 @@ namespace SharpCompress.Archives.Tar
private readonly bool closeStream;
private readonly Stream stream;
internal TarWritableArchiveEntry(TarArchive archive, Stream stream, CompressionType compressionType,
string path, long size, DateTime? lastModified, bool closeStream)
: base(archive, null, compressionType)
internal TarWritableArchiveEntry(
TarArchive archive,
Stream stream,
CompressionType compressionType,
string path,
long size,
DateTime? lastModified,
bool closeStream
) : base(archive, null, compressionType)
{
this.stream = stream;
Key = path;

View File

@@ -18,6 +18,7 @@ namespace SharpCompress.Archives.Zip
{
#nullable disable
private readonly SeekableZipHeaderFactory headerFactory;
#nullable enable
/// <summary>
@@ -31,10 +32,12 @@ namespace SharpCompress.Archives.Zip
/// </summary>
/// <param name="srcStream"></param>
/// <param name="options"></param>
internal ZipArchive(SourceStream srcStream)
: base(ArchiveType.Zip, srcStream)
internal ZipArchive(SourceStream srcStream) : base(ArchiveType.Zip, srcStream)
{
headerFactory = new SeekableZipHeaderFactory(srcStream.ReaderOptions.Password, srcStream.ReaderOptions.ArchiveEncoding);
headerFactory = new SeekableZipHeaderFactory(
srcStream.ReaderOptions.Password,
srcStream.ReaderOptions.ArchiveEncoding
);
}
/// <summary>
@@ -56,7 +59,13 @@ namespace SharpCompress.Archives.Zip
public static ZipArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.CheckNotNull(nameof(fileInfo));
return new ZipArchive(new SourceStream(fileInfo, i => ZipArchiveVolumeFactory.GetFilePart(i, fileInfo), readerOptions ?? new ReaderOptions()));
return new ZipArchive(
new SourceStream(
fileInfo,
i => ZipArchiveVolumeFactory.GetFilePart(i, fileInfo),
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -64,11 +73,20 @@ namespace SharpCompress.Archives.Zip
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
public static ZipArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? readerOptions = null)
public static ZipArchive Open(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
{
fileInfos.CheckNotNull(nameof(fileInfos));
FileInfo[] files = fileInfos.ToArray();
return new ZipArchive(new SourceStream(files[0], i => i < files.Length ? files[i] : null, readerOptions ?? new ReaderOptions()));
return new ZipArchive(
new SourceStream(
files[0],
i => i < files.Length ? files[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -76,11 +94,20 @@ namespace SharpCompress.Archives.Zip
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
public static ZipArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static ZipArchive Open(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.CheckNotNull(nameof(streams));
Stream[] strms = streams.ToArray();
return new ZipArchive(new SourceStream(strms[0], i => i < strms.Length ? strms[i] : null, readerOptions ?? new ReaderOptions()));
return new ZipArchive(
new SourceStream(
strms[0],
i => i < strms.Length ? strms[i] : null,
readerOptions ?? new ReaderOptions()
)
);
}
/// <summary>
@@ -91,7 +118,9 @@ namespace SharpCompress.Archives.Zip
public static ZipArchive Open(Stream stream, ReaderOptions? readerOptions = null)
{
stream.CheckNotNull(nameof(stream));
return new ZipArchive(new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()));
return new ZipArchive(
new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions())
);
}
public static bool IsZipFile(string filePath, string? password = null)
@@ -113,10 +142,15 @@ namespace SharpCompress.Archives.Zip
public static bool IsZipFile(Stream stream, string? password = null)
{
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password, new ArchiveEncoding());
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(
password,
new ArchiveEncoding()
);
try
{
ZipHeader? header = headerFactory.ReadStreamHeader(stream).FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
ZipHeader? header = headerFactory
.ReadStreamHeader(stream)
.FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
if (header is null)
{
return false;
@@ -135,15 +169,23 @@ namespace SharpCompress.Archives.Zip
public static bool IsZipMulti(Stream stream, string? password = null)
{
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password, new ArchiveEncoding());
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(
password,
new ArchiveEncoding()
);
try
{
ZipHeader? header = headerFactory.ReadStreamHeader(stream).FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
ZipHeader? header = headerFactory
.ReadStreamHeader(stream)
.FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
if (header is null)
{
if (stream.CanSeek) //could be multipart. Test for central directory - might not be z64 safe
{
SeekableZipHeaderFactory z = new SeekableZipHeaderFactory(password, new ArchiveEncoding());
SeekableZipHeaderFactory z = new SeekableZipHeaderFactory(
password,
new ArchiveEncoding()
);
var x = z.ReadSeekableHeader(stream).FirstOrDefault();
return x?.ZipHeaderType == ZipHeaderType.DirectoryEntry;
}
@@ -191,10 +233,7 @@ namespace SharpCompress.Archives.Zip
return new ZipVolume(base.SrcStream, ReaderOptions, idx++).AsEnumerable();
}
internal ZipArchive()
: base(ArchiveType.Zip)
{
}
internal ZipArchive() : base(ArchiveType.Zip) { }
protected override IEnumerable<ZipArchiveEntry> LoadEntries(IEnumerable<ZipVolume> volumes)
{
@@ -206,19 +245,30 @@ namespace SharpCompress.Archives.Zip
switch (h.ZipHeaderType)
{
case ZipHeaderType.DirectoryEntry:
{
DirectoryEntryHeader deh = (DirectoryEntryHeader)h;
Stream s;
if (deh.RelativeOffsetOfEntryHeader + deh.CompressedSize > vols[deh.DiskNumberStart].Stream.Length)
{
var v = vols.Skip(deh.DiskNumberStart).ToArray();
s = new SourceStream(v[0].Stream, i => i < v.Length ? v[i].Stream : null, new ReaderOptions() { LeaveStreamOpen = true });
DirectoryEntryHeader deh = (DirectoryEntryHeader)h;
Stream s;
if (
deh.RelativeOffsetOfEntryHeader + deh.CompressedSize
> vols[deh.DiskNumberStart].Stream.Length
)
{
var v = vols.Skip(deh.DiskNumberStart).ToArray();
s = new SourceStream(
v[0].Stream,
i => i < v.Length ? v[i].Stream : null,
new ReaderOptions() { LeaveStreamOpen = true }
);
}
else
s = vols[deh.DiskNumberStart].Stream;
yield return new ZipArchiveEntry(
this,
new SeekableZipFilePart(headerFactory, deh, s)
);
}
else
s = vols[deh.DiskNumberStart].Stream;
yield return new ZipArchiveEntry(this, new SeekableZipFilePart(headerFactory, deh, s));
}
break;
break;
case ZipHeaderType.DirectoryEnd:
{
byte[] bytes = ((DirectoryEndHeader)h).Comment ?? Array.Empty<byte>();
@@ -235,14 +285,16 @@ namespace SharpCompress.Archives.Zip
SaveTo(stream, new WriterOptions(CompressionType.Deflate));
}
protected override void SaveTo(Stream stream, WriterOptions options,
IEnumerable<ZipArchiveEntry> oldEntries,
IEnumerable<ZipArchiveEntry> newEntries)
protected override void SaveTo(
Stream stream,
WriterOptions options,
IEnumerable<ZipArchiveEntry> oldEntries,
IEnumerable<ZipArchiveEntry> newEntries
)
{
using (var writer = new ZipWriter(stream, new ZipWriterOptions(options)))
{
foreach (var entry in oldEntries.Concat(newEntries)
.Where(x => !x.IsDirectory))
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using (var entryStream = entry.OpenEntryStream())
{
@@ -252,8 +304,13 @@ namespace SharpCompress.Archives.Zip
}
}
protected override ZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
bool closeStream)
protected override ZipArchiveEntry CreateEntryInternal(
string filePath,
Stream source,
long size,
DateTime? modified,
bool closeStream
)
{
return new ZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream);
}

View File

@@ -6,8 +6,7 @@ namespace SharpCompress.Archives.Zip
{
public class ZipArchiveEntry : ZipEntry, IArchiveEntry
{
internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart? part)
: base(part)
internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart? part) : base(part)
{
Archive = archive;
}
@@ -27,4 +26,4 @@ namespace SharpCompress.Archives.Zip
public string? Comment => ((SeekableZipFilePart)Parts.Single()).Comment;
}
}
}

View File

@@ -18,9 +18,22 @@ namespace SharpCompress.Archives.Zip
//load files with zip/zipx first. Swapped to end once loaded in ZipArchive
//new style .zip, z01.. | .zipx, zx01 - if the numbers go beyond 99 then they use 100 ...1000 etc
Match m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase);
Match m = Regex.Match(
part1.Name,
@"^(.*\.)(zipx?|zx?[0-9]+)$",
RegexOptions.IgnoreCase
);
if (m.Success)
item = new FileInfo(Path.Combine(part1.DirectoryName!, String.Concat(m.Groups[1].Value, Regex.Replace(m.Groups[2].Value, @"[^xz]", ""), index.ToString().PadLeft(2, '0'))));
item = new FileInfo(
Path.Combine(
part1.DirectoryName!,
String.Concat(
m.Groups[1].Value,
Regex.Replace(m.Groups[2].Value, @"[^xz]", ""),
index.ToString().PadLeft(2, '0')
)
)
);
else //split - 001, 002 ...
return ArchiveVolumeFactory.GetFilePart(index, part1);
@@ -29,6 +42,5 @@ namespace SharpCompress.Archives.Zip
return null; //no more items
}
}
}

View File

@@ -12,9 +12,14 @@ namespace SharpCompress.Archives.Zip
private readonly Stream stream;
private bool isDisposed;
internal ZipWritableArchiveEntry(ZipArchive archive, Stream stream, string path, long size,
DateTime? lastModified, bool closeStream)
: base(archive, null)
internal ZipWritableArchiveEntry(
ZipArchive archive,
Stream stream,
string path,
long size,
DateTime? lastModified,
bool closeStream
) : base(archive, null)
{
this.stream = stream;
Key = path;

View File

@@ -26,10 +26,8 @@ namespace SharpCompress.Common
/// <returns>string Func(bytes, index, length)</returns>
public Func<byte[], int, int, string>? CustomDecoder { get; set; }
public ArchiveEncoding()
: this(Encoding.Default, Encoding.Default)
{
}
public ArchiveEncoding() : this(Encoding.Default, Encoding.Default) { }
public ArchiveEncoding(Encoding def, Encoding password)
{
Default = def;
@@ -70,7 +68,8 @@ namespace SharpCompress.Common
public Func<byte[], int, int, string> GetDecoder()
{
return CustomDecoder ?? ((bytes, index, count) => GetEncoding().GetString(bytes, index, count));
return CustomDecoder
?? ((bytes, index, count) => GetEncoding().GetString(bytes, index, count));
}
}
}

View File

@@ -4,9 +4,6 @@ namespace SharpCompress.Common
{
public class ArchiveException : Exception
{
public ArchiveException(string message)
: base(message)
{
}
public ArchiveException(string message) : base(message) { }
}
}
}

View File

@@ -11,4 +11,4 @@ namespace SharpCompress.Common
public T Item { get; }
}
}
}

View File

@@ -8,4 +8,4 @@
SevenZip,
GZip
}
}
}

View File

@@ -4,7 +4,10 @@ namespace SharpCompress.Common
{
public sealed class CompressedBytesReadEventArgs : EventArgs
{
public CompressedBytesReadEventArgs(long compressedBytesRead, long currentFilePartCompressedBytesRead)
public CompressedBytesReadEventArgs(
long compressedBytesRead,
long currentFilePartCompressedBytesRead
)
{
CompressedBytesRead = compressedBytesRead;
CurrentFilePartCompressedBytesRead = currentFilePartCompressedBytesRead;
@@ -20,4 +23,4 @@ namespace SharpCompress.Common
/// </summary>
public long CurrentFilePartCompressedBytesRead { get; }
}
}
}

View File

@@ -16,4 +16,4 @@
Unknown,
Deflate64
}
}
}

View File

@@ -4,9 +4,6 @@ namespace SharpCompress.Common
{
public class CryptographicException : Exception
{
public CryptographicException(string message)
: base(message)
{
}
public CryptographicException(string message) : base(message) { }
}
}
}

View File

@@ -73,6 +73,7 @@ namespace SharpCompress.Common
public int VolumeIndexFirst => this.Parts?.FirstOrDefault()?.Index ?? 0;
public int VolumeIndexLast => this.Parts?.LastOrDefault()?.Index ?? 0;
/// <inheritdoc/>
public override string ToString() => Key;
@@ -80,9 +81,7 @@ namespace SharpCompress.Common
public bool IsSolid { get; set; }
internal virtual void Close()
{
}
internal virtual void Close() { }
/// <summary>
/// Entry file attribute.

View File

@@ -47,13 +47,15 @@ namespace SharpCompress.Common
public override bool CanWrite => false;
public override void Flush()
{
}
public override void Flush() { }
public override long Length => _stream.Length;
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
@@ -90,4 +92,4 @@ namespace SharpCompress.Common
throw new NotSupportedException();
}
}
}
}

View File

@@ -4,14 +4,8 @@ namespace SharpCompress.Common
{
public class ExtractionException : Exception
{
public ExtractionException(string message)
: base(message)
{
}
public ExtractionException(string message) : base(message) { }
public ExtractionException(string message, Exception inner)
: base(message, inner)
{
}
public ExtractionException(string message, Exception inner) : base(message, inner) { }
}
}
}

View File

@@ -8,41 +8,49 @@ namespace SharpCompress.Common
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteEntryToDirectory(IEntry entry,
string destinationDirectory,
ExtractionOptions? options,
Action<string, ExtractionOptions?> write)
public static void WriteEntryToDirectory(
IEntry entry,
string destinationDirectory,
ExtractionOptions? options,
Action<string, ExtractionOptions?> write
)
{
string destinationFileName;
string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
//check for trailing slash.
if (fullDestinationDirectoryPath[fullDestinationDirectoryPath.Length - 1] != Path.DirectorySeparatorChar)
if (
fullDestinationDirectoryPath[fullDestinationDirectoryPath.Length - 1]
!= Path.DirectorySeparatorChar
)
{
fullDestinationDirectoryPath += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(fullDestinationDirectoryPath))
{
throw new ExtractionException($"Directory does not exist to extract to: {fullDestinationDirectoryPath}");
throw new ExtractionException(
$"Directory does not exist to extract to: {fullDestinationDirectoryPath}"
);
}
options ??= new ExtractionOptions()
{
Overwrite = true
};
options ??= new ExtractionOptions() { Overwrite = true };
string file = Path.GetFileName(entry.Key);
if (options.ExtractFullPath)
{
string folder = Path.GetDirectoryName(entry.Key)!;
string destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder));
string destdir = Path.GetFullPath(
Path.Combine(fullDestinationDirectoryPath, folder)
);
if (!Directory.Exists(destdir))
{
if (!destdir.StartsWith(fullDestinationDirectoryPath, StringComparison.Ordinal))
{
throw new ExtractionException("Entry is trying to create a directory outside of the destination directory.");
throw new ExtractionException(
"Entry is trying to create a directory outside of the destination directory."
);
}
Directory.CreateDirectory(destdir);
@@ -52,16 +60,22 @@ namespace SharpCompress.Common
else
{
destinationFileName = Path.Combine(fullDestinationDirectoryPath, file);
}
if (!entry.IsDirectory)
{
destinationFileName = Path.GetFullPath(destinationFileName);
if (!destinationFileName.StartsWith(fullDestinationDirectoryPath, StringComparison.Ordinal))
if (
!destinationFileName.StartsWith(
fullDestinationDirectoryPath,
StringComparison.Ordinal
)
)
{
throw new ExtractionException("Entry is trying to write a file outside of the destination directory.");
throw new ExtractionException(
"Entry is trying to write a file outside of the destination directory."
);
}
write(destinationFileName, options);
}
@@ -71,25 +85,27 @@ namespace SharpCompress.Common
}
}
public static void WriteEntryToFile(IEntry entry, string destinationFileName,
ExtractionOptions? options,
Action<string, FileMode> openAndWrite)
public static void WriteEntryToFile(
IEntry entry,
string destinationFileName,
ExtractionOptions? options,
Action<string, FileMode> openAndWrite
)
{
if (entry.LinkTarget != null)
{
if (options?.WriteSymbolicLink is null)
{
throw new ExtractionException("Entry is a symbolic link but ExtractionOptions.WriteSymbolicLink delegate is null");
throw new ExtractionException(
"Entry is a symbolic link but ExtractionOptions.WriteSymbolicLink delegate is null"
);
}
options.WriteSymbolicLink(destinationFileName, entry.LinkTarget);
}
else
{
FileMode fm = FileMode.Create;
options ??= new ExtractionOptions()
{
Overwrite = true
};
options ??= new ExtractionOptions() { Overwrite = true };
if (!options.Overwrite)
{
@@ -101,4 +117,4 @@ namespace SharpCompress.Common
}
}
}
}
}

View File

@@ -31,10 +31,11 @@ namespace SharpCompress.Common
/// </summary>
public delegate void SymbolicLinkWriterDelegate(string sourcePath, string targetPath);
public SymbolicLinkWriterDelegate WriteSymbolicLink =
(sourcePath, targetPath) =>
{
Console.WriteLine($"Could not write symlink {sourcePath} -> {targetPath}, for more information please see https://github.com/dotnet/runtime/issues/24271");
};
public SymbolicLinkWriterDelegate WriteSymbolicLink = (sourcePath, targetPath) =>
{
Console.WriteLine(
$"Could not write symlink {sourcePath} -> {targetPath}, for more information please see https://github.com/dotnet/runtime/issues/24271"
);
};
}
}
}

View File

@@ -26,4 +26,4 @@ namespace SharpCompress.Common
/// </summary>
public long CompressedSize { get; }
}
}
}

View File

@@ -6,35 +6,33 @@ namespace SharpCompress.Common
{
/// <summary>
/// Returns true if the flag is set on the specified bit field.
/// Currently only works with 32-bit bitfields.
/// Currently only works with 32-bit bitfields.
/// </summary>
/// <typeparam name="T">Enumeration with Flags attribute</typeparam>
/// <param name="bitField">Flagged variable</param>
/// <param name="flag">Flag to test</param>
/// <returns></returns>
public static bool HasFlag<T>(long bitField, T flag)
where T : struct
public static bool HasFlag<T>(long bitField, T flag) where T : struct
{
return HasFlag(bitField, flag);
}
/// <summary>
/// Returns true if the flag is set on the specified bit field.
/// Currently only works with 32-bit bitfields.
/// Currently only works with 32-bit bitfields.
/// </summary>
/// <typeparam name="T">Enumeration with Flags attribute</typeparam>
/// <param name="bitField">Flagged variable</param>
/// <param name="flag">Flag to test</param>
/// <returns></returns>
public static bool HasFlag<T>(ulong bitField, T flag)
where T : struct
public static bool HasFlag<T>(ulong bitField, T flag) where T : struct
{
return HasFlag(bitField, flag);
}
/// <summary>
/// Returns true if the flag is set on the specified bit field.
/// Currently only works with 32-bit bitfields.
/// Currently only works with 32-bit bitfields.
/// </summary>
/// <param name="bitField">Flagged variable</param>
/// <param name="flag">Flag to test</param>
@@ -51,21 +49,20 @@ namespace SharpCompress.Common
/// <summary>
/// Returns true if the flag is set on the specified bit field.
/// Currently only works with 32-bit bitfields.
/// Currently only works with 32-bit bitfields.
/// </summary>
/// <typeparam name="T">Enumeration with Flags attribute</typeparam>
/// <param name="bitField">Flagged variable</param>
/// <param name="flag">Flag to test</param>
/// <returns></returns>
public static bool HasFlag<T>(T bitField, T flag)
where T : struct
public static bool HasFlag<T>(T bitField, T flag) where T : struct
{
return HasFlag(Convert.ToInt64(bitField), Convert.ToInt64(flag));
}
/// <summary>
/// Returns true if the flag is set on the specified bit field.
/// Currently only works with 32-bit bitfields.
/// Currently only works with 32-bit bitfields.
/// </summary>
/// <param name="bitField">Flagged variable</param>
/// <param name="flag">Flag to test</param>
@@ -99,10 +96,9 @@ namespace SharpCompress.Common
/// <param name="flag">Flag to change</param>
/// <param name="on">bool</param>
/// <returns>The flagged variable with the flag changed</returns>
public static long SetFlag<T>(T bitField, T flag, bool on)
where T : struct
public static long SetFlag<T>(T bitField, T flag, bool on) where T : struct
{
return SetFlag(Convert.ToInt64(bitField), Convert.ToInt64(flag), on);
}
}
}
}

View File

@@ -46,4 +46,4 @@ namespace SharpCompress.Common.GZip
yield return new GZipEntry(new GZipFilePart(stream, options.ArchiveEncoding));
}
}
}
}

View File

@@ -129,8 +129,7 @@ namespace SharpCompress.Common.GZip
{
list.Add(buf1[0]);
}
}
while (!done);
} while (!done);
byte[] buffer = list.ToArray();
return ArchiveEncoding.Decode(buffer);
}

View File

@@ -6,9 +6,7 @@ namespace SharpCompress.Common.GZip
public class GZipVolume : Volume
{
public GZipVolume(Stream stream, ReaderOptions options, int index = 0)
: base(stream, options, index)
{
}
: base(stream, options, index) { }
public GZipVolume(FileInfo fileInfo, ReaderOptions options)
: base(fileInfo.OpenRead(), options)

View File

@@ -4,8 +4,11 @@ namespace SharpCompress.Common
{
internal static class EntryExtensions
{
internal static void PreserveExtractionOptions(this IEntry entry, string destinationFileName,
ExtractionOptions options)
internal static void PreserveExtractionOptions(
this IEntry entry,
string destinationFileName,
ExtractionOptions options
)
{
if (options.PreserveFileTime || options.PreserveAttributes)
{
@@ -38,7 +41,8 @@ namespace SharpCompress.Common
{
if (entry.Attrib.HasValue)
{
nf.Attributes = (FileAttributes)System.Enum.ToObject(typeof(FileAttributes), entry.Attrib.Value);
nf.Attributes = (FileAttributes)
System.Enum.ToObject(typeof(FileAttributes), entry.Attrib.Value);
}
}
}

View File

@@ -2,9 +2,6 @@
{
public class IncompleteArchiveException : ArchiveException
{
public IncompleteArchiveException(string message)
: base(message)
{
}
public IncompleteArchiveException(string message) : base(message) { }
}
}
}

View File

@@ -4,14 +4,8 @@ namespace SharpCompress.Common
{
public class InvalidFormatException : ExtractionException
{
public InvalidFormatException(string message)
: base(message)
{
}
public InvalidFormatException(string message) : base(message) { }
public InvalidFormatException(string message, Exception inner)
: base(message, inner)
{
}
public InvalidFormatException(string message, Exception inner) : base(message, inner) { }
}
}
}

View File

@@ -4,14 +4,9 @@ namespace SharpCompress.Common
{
public class MultiVolumeExtractionException : ExtractionException
{
public MultiVolumeExtractionException(string message)
: base(message)
{
}
public MultiVolumeExtractionException(string message) : base(message) { }
public MultiVolumeExtractionException(string message, Exception inner)
: base(message, inner)
{
}
: base(message, inner) { }
}
}
}

View File

@@ -2,9 +2,6 @@
{
public class MultipartStreamRequiredException : ExtractionException
{
public MultipartStreamRequiredException(string message)
: base(message)
{
}
public MultipartStreamRequiredException(string message) : base(message) { }
}
}
}

View File

@@ -1,5 +1,4 @@
namespace SharpCompress.Common
namespace SharpCompress.Common
{
public class OptionsBase
{
@@ -10,4 +9,4 @@ namespace SharpCompress.Common
public ArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
}
}
}

View File

@@ -4,14 +4,9 @@ namespace SharpCompress.Common
{
public class PasswordProtectedException : ExtractionException
{
public PasswordProtectedException(string message)
: base(message)
{
}
public PasswordProtectedException(string message) : base(message) { }
public PasswordProtectedException(string message, Exception inner)
: base(message, inner)
{
}
public PasswordProtectedException(string message, Exception inner) : base(message, inner)
{ }
}
}
}

View File

@@ -29,4 +29,4 @@ namespace SharpCompress.Common.Rar.Headers
internal byte AvVersion { get; private set; }
}
}
}

View File

@@ -6,7 +6,6 @@ namespace SharpCompress.Common.Rar.Headers
{
internal class ArchiveCryptHeader : RarHeader
{
private const int CRYPT_VERSION = 0; // Supported encryption version.
private const int SIZE_SALT50 = 16;
private const int SIZE_SALT30 = 8;
@@ -16,7 +15,6 @@ namespace SharpCompress.Common.Rar.Headers
private const int CRYPT5_KDF_LG2_COUNT = 15; // LOG2 of PDKDF2 iteration count.
private const int CRYPT5_KDF_LG2_COUNT_MAX = 24; // LOG2 of maximum accepted iteration count.
private bool _usePswCheck;
private uint _lg2Count; // Log2 of PBKDF2 repetition count.
private byte[] _salt;
@@ -24,9 +22,7 @@ namespace SharpCompress.Common.Rar.Headers
private byte[] _pswCheckCsm;
public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader)
: base(header, reader, HeaderType.Crypt)
{
}
: base(header, reader, HeaderType.Crypt) { }
protected override void ReadFinish(MarkingBinaryReader reader)
{
@@ -37,10 +33,12 @@ namespace SharpCompress.Common.Rar.Headers
return;
}
var encryptionFlags = reader.ReadRarVIntUInt32();
_usePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
_usePswCheck = FlagUtility.HasFlag(
encryptionFlags,
EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK
);
_lg2Count = reader.ReadRarVIntByte(1);
//UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
if (_lg2Count > CRYPT5_KDF_LG2_COUNT_MAX)
{
@@ -56,4 +54,4 @@ namespace SharpCompress.Common.Rar.Headers
}
}
}
}
}

View File

@@ -5,9 +5,7 @@ namespace SharpCompress.Common.Rar.Headers
internal sealed class ArchiveHeader : RarHeader
{
public ArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
: base(header, reader, HeaderType.Archive)
{
}
: base(header, reader, HeaderType.Archive) { }
protected override void ReadFinish(MarkingBinaryReader reader)
{
@@ -81,8 +79,9 @@ namespace SharpCompress.Common.Rar.Headers
public bool IsVolume => HasFlag(IsRar5 ? ArchiveFlagsV5.VOLUME : ArchiveFlagsV4.VOLUME);
// RAR5: Volume number field is present. True for all volumes except first.
public bool IsFirstVolume => IsRar5 ? VolumeNumber is null : HasFlag(ArchiveFlagsV4.FIRST_VOLUME);
public bool IsFirstVolume =>
IsRar5 ? VolumeNumber is null : HasFlag(ArchiveFlagsV4.FIRST_VOLUME);
public bool IsSolid => HasFlag(IsRar5 ? ArchiveFlagsV5.SOLID : ArchiveFlagsV4.SOLID);
}
}
}

View File

@@ -28,4 +28,4 @@ namespace SharpCompress.Common.Rar.Headers
internal byte UnpMethod { get; private set; }
internal short CommCrc { get; private set; }
}
}
}

View File

@@ -5,9 +5,7 @@ namespace SharpCompress.Common.Rar.Headers
internal class EndArchiveHeader : RarHeader
{
public EndArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
: base(header, reader, HeaderType.EndArchive)
{
}
: base(header, reader, HeaderType.EndArchive) { }
protected override void ReadFinish(MarkingBinaryReader reader)
{
@@ -40,4 +38,4 @@ namespace SharpCompress.Common.Rar.Headers
internal short? VolumeNumber { get; private set; }
}
}
}

View File

@@ -22,9 +22,7 @@ namespace SharpCompress.Common.Rar.Headers
private uint _fileCrc;
public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType)
: base(header, reader, headerType)
{
}
: base(header, reader, headerType) { }
protected override void ReadFinish(MarkingBinaryReader reader)
{
@@ -68,7 +66,7 @@ namespace SharpCompress.Common.Rar.Headers
// them.
CompressionAlgorithm = (byte)((compressionInfo & 0x3f) + 50);
// 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files.
// 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files.
// It can be set only for file headers and is never set for service headers.
IsSolid = (compressionInfo & 0x40) == 0x40;
@@ -89,7 +87,7 @@ namespace SharpCompress.Common.Rar.Headers
// TODO: not sure if anything needs to be done to handle the following:
// If Unix file name contains any high ASCII characters which cannot be correctly converted to Unicode and UTF-8
// we map such characters to to 0xE080 - 0xE0FF private use Unicode area and insert 0xFFFE Unicode non-character
// to resulting string to indicate that it contains mapped characters, which need to be converted back when extracting.
// to resulting string to indicate that it contains mapped characters, which need to be converted back when extracting.
// Concrete position of 0xFFFE is not defined, we need to search the entire string for it. Such mapped names are not
// portable and can be correctly unpacked only on the same system where they were created.
//
@@ -119,6 +117,7 @@ namespace SharpCompress.Common.Rar.Headers
{
//TODO
case 1: // file encryption
{
isEncryptedRar5 = true;
@@ -132,6 +131,7 @@ namespace SharpCompress.Common.Rar.Headers
// }
// break;
case 3: // file time
{
ushort flags = reader.ReadRarVIntUInt16();
var isWindowsTime = (flags & 1) == 0;
@@ -190,7 +190,6 @@ namespace SharpCompress.Common.Rar.Headers
}
}
private static DateTime ReadExtendedTimeV5(MarkingBinaryReader reader, bool isWindowsTime)
{
if (isWindowsTime)
@@ -213,12 +212,13 @@ namespace SharpCompress.Common.Rar.Headers
return path;
}
private void ReadFromReaderV4(MarkingBinaryReader reader)
{
Flags = HeaderFlags;
IsSolid = HasFlag(FileFlagsV4.SOLID);
WindowSize = IsDirectory ? 0U : ((size_t)0x10000) << ((Flags & FileFlagsV4.WINDOW_MASK) >> 5);
WindowSize = IsDirectory
? 0U
: ((size_t)0x10000) << ((Flags & FileFlagsV4.WINDOW_MASK) >> 5);
uint lowUncompressedSize = reader.ReadUInt32();
@@ -263,12 +263,12 @@ namespace SharpCompress.Common.Rar.Headers
switch (HeaderCode)
{
case HeaderCodeV.RAR4_FILE_HEADER:
{
if (HasFlag(FileFlagsV4.UNICODE))
{
int length = 0;
while (length < fileNameBytes.Length
&& fileNameBytes[length] != 0)
while (length < fileNameBytes.Length && fileNameBytes[length] != 0)
{
length++;
}
@@ -290,6 +290,7 @@ namespace SharpCompress.Common.Rar.Headers
}
break;
case HeaderCodeV.RAR4_NEW_SUB_HEADER:
{
int datasize = HeaderSize - newLhdSize - nameSize;
if (HasFlag(FileFlagsV4.SALT))
@@ -303,8 +304,11 @@ namespace SharpCompress.Common.Rar.Headers
if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
{
RecoverySectors = SubData[8] + (SubData[9] << 8)
+ (SubData[10] << 16) + (SubData[11] << 24);
RecoverySectors =
SubData[8]
+ (SubData[9] << 8)
+ (SubData[10] << 16)
+ (SubData[11] << 24);
}
}
break;
@@ -321,7 +325,12 @@ namespace SharpCompress.Common.Rar.Headers
if (RemainingHeaderBytes(reader) >= 2)
{
ushort extendedFlags = reader.ReadUInt16();
FileLastModifiedTime = ProcessExtendedTimeV4(extendedFlags, FileLastModifiedTime, reader, 0);
FileLastModifiedTime = ProcessExtendedTimeV4(
extendedFlags,
FileLastModifiedTime,
reader,
0
);
FileCreatedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 1);
FileLastAccessedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 2);
FileArchivedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 3);
@@ -336,7 +345,12 @@ namespace SharpCompress.Common.Rar.Headers
return l + y;
}
private static DateTime? ProcessExtendedTimeV4(ushort extendedFlags, DateTime? time, MarkingBinaryReader reader, int i)
private static DateTime? ProcessExtendedTimeV4(
ushort extendedFlags,
DateTime? time,
MarkingBinaryReader reader,
int i
)
{
uint rmode = (uint)extendedFlags >> (3 - i) * 4;
if ((rmode & 8) == 0)
@@ -395,7 +409,7 @@ namespace SharpCompress.Common.Rar.Headers
{
if (IsRar5 && !HasFlag(FileFlagsV5.HAS_CRC32))
{
//!!! rar5:
//!!! rar5:
throw new InvalidOperationException("TODO rar5");
}
return _fileCrc;
@@ -437,8 +451,10 @@ namespace SharpCompress.Common.Rar.Headers
internal long DataStartPosition { get; set; }
public Stream PackedStream { get; set; }
public bool IsSplitBefore => IsRar5 ? HasHeaderFlag(HeaderFlagsV5.SPLIT_BEFORE) : HasFlag(FileFlagsV4.SPLIT_BEFORE);
public bool IsSplitAfter => IsRar5 ? HasHeaderFlag(HeaderFlagsV5.SPLIT_AFTER) : HasFlag(FileFlagsV4.SPLIT_AFTER);
public bool IsSplitBefore =>
IsRar5 ? HasHeaderFlag(HeaderFlagsV5.SPLIT_BEFORE) : HasFlag(FileFlagsV4.SPLIT_BEFORE);
public bool IsSplitAfter =>
IsRar5 ? HasHeaderFlag(HeaderFlagsV5.SPLIT_AFTER) : HasFlag(FileFlagsV4.SPLIT_AFTER);
public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY);
@@ -453,4 +469,4 @@ namespace SharpCompress.Common.Rar.Headers
internal DateTime? FileArchivedTime { get; private set; }
}
}
}

View File

@@ -54,7 +54,11 @@ namespace SharpCompress.Common.Rar.Headers
if ((length & 0x80) != 0)
{
int correction = GetChar(name, encPos++);
for (length = (length & 0x7f) + 2; length > 0 && decPos < name.Length; length--, decPos++)
for (
length = (length & 0x7f) + 2;
length > 0 && decPos < name.Length;
length--, decPos++
)
{
low = (GetChar(name, decPos) + correction) & 0xff;
buf.Append((char)((highByte << 8) + low));
@@ -62,7 +66,11 @@ namespace SharpCompress.Common.Rar.Headers
}
else
{
for (length += 2; length > 0 && decPos < name.Length; length--, decPos++)
for (
length += 2;
length > 0 && decPos < name.Length;
length--, decPos++
)
{
buf.Append((char)(GetChar(name, decPos)));
}
@@ -75,4 +83,4 @@ namespace SharpCompress.Common.Rar.Headers
return buf.ToString();
}
}
}
}

View File

@@ -54,7 +54,7 @@ namespace SharpCompress.Common.Rar.Headers
{
public const ushort HAS_EXTRA = 0x0001;
public const ushort HAS_DATA = 0x0002;
public const ushort KEEP = 0x0004; // block must be kept during an update
public const ushort KEEP = 0x0004; // block must be kept during an update
public const ushort SPLIT_BEFORE = 0x0008;
public const ushort SPLIT_AFTER = 0x0010;
public const ushort CHILD = 0x0020; // ??? Block depends on preceding file block.

View File

@@ -34,7 +34,8 @@ namespace SharpCompress.Common.Rar.Headers
try
{
int start = -1;
var b = GetByte(stream); start++;
var b = GetByte(stream);
start++;
while (start <= maxScanIndex)
{
// Rar old signature: 52 45 7E 5E
@@ -42,37 +43,44 @@ namespace SharpCompress.Common.Rar.Headers
// Rar5 signature: 52 61 72 21 1A 07 01 00
if (b == 0x52)
{
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b == 0x61)
{
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x72)
{
continue;
}
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x21)
{
continue;
}
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x1a)
{
continue;
}
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x07)
{
continue;
}
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b == 1)
{
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0)
{
continue;
@@ -87,24 +95,29 @@ namespace SharpCompress.Common.Rar.Headers
}
else if (b == 0x45)
{
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x7e)
{
continue;
}
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
if (b != 0x5e)
{
continue;
}
throw new InvalidFormatException("Rar format version pre-4 is unsupported.");
throw new InvalidFormatException(
"Rar format version pre-4 is unsupported."
);
}
}
else
{
b = GetByte(stream); start++;
b = GetByte(stream);
start++;
}
}
}

View File

@@ -46,4 +46,4 @@ namespace SharpCompress.Common.Rar.Headers
return other is not null && Equals(other._bytes);
}
}
}
}

View File

@@ -28,4 +28,4 @@ namespace SharpCompress.Common.Rar.Headers
internal uint TotalBlocks { get; private set; }
internal byte[]? Mark { get; private set; }
}
}
}

View File

@@ -11,7 +11,11 @@ namespace SharpCompress.Common.Rar.Headers
private readonly HeaderType _headerType;
private readonly bool _isRar5;
internal static RarHeader? TryReadBase(RarCrcBinaryReader reader, bool isRar5, ArchiveEncoding archiveEncoding)
internal static RarHeader? TryReadBase(
RarCrcBinaryReader reader,
bool isRar5,
ArchiveEncoding archiveEncoding
)
{
try
{
@@ -131,4 +135,4 @@ namespace SharpCompress.Common.Rar.Headers
/// </summary>
protected long AdditionalDataSize { get; }
}
}
}

View File

@@ -21,7 +21,11 @@ namespace SharpCompress.Common.Rar.Headers
public IEnumerable<IRarHeader> ReadHeaders(Stream stream)
{
var markHeader = MarkHeader.Read(stream, Options.LeaveStreamOpen, Options.LookForHeader);
var markHeader = MarkHeader.Read(
stream,
Options.LeaveStreamOpen,
Options.LookForHeader
);
_isRar5 = markHeader.IsRar5;
yield return markHeader;
@@ -49,7 +53,9 @@ namespace SharpCompress.Common.Rar.Headers
{
if (Options.Password is null)
{
throw new CryptographicException("Encrypted Rar archive has no password specified.");
throw new CryptographicException(
"Encrypted Rar archive has no password specified."
);
}
reader = new RarCryptoBinaryReader(stream, Options.Password);
}
@@ -63,102 +69,113 @@ namespace SharpCompress.Common.Rar.Headers
{
case HeaderCodeV.RAR5_ARCHIVE_HEADER:
case HeaderCodeV.RAR4_ARCHIVE_HEADER:
{
var ah = new ArchiveHeader(header, reader);
if (ah.IsEncrypted == true)
{
var ah = new ArchiveHeader(header, reader);
if (ah.IsEncrypted == true)
{
//!!! rar5 we don't know yet
IsEncrypted = true;
}
return ah;
//!!! rar5 we don't know yet
IsEncrypted = true;
}
return ah;
}
case HeaderCodeV.RAR4_PROTECT_HEADER:
{
var ph = new ProtectHeader(header, reader);
// skip the recovery record data, we do not use it.
switch (StreamingMode)
{
var ph = new ProtectHeader(header, reader);
// skip the recovery record data, we do not use it.
switch (StreamingMode)
{
case StreamingMode.Seekable:
{
reader.BaseStream.Position += ph.DataSize;
}
break;
case StreamingMode.Streaming:
{
reader.BaseStream.Skip(ph.DataSize);
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
}
case StreamingMode.Seekable:
return ph;
{
reader.BaseStream.Position += ph.DataSize;
}
break;
case StreamingMode.Streaming:
{
reader.BaseStream.Skip(ph.DataSize);
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
}
return ph;
}
case HeaderCodeV.RAR5_SERVICE_HEADER:
{
var fh = new FileHeader(header, reader, HeaderType.Service);
SkipData(fh, reader);
return fh;
}
{
var fh = new FileHeader(header, reader, HeaderType.Service);
SkipData(fh, reader);
return fh;
}
case HeaderCodeV.RAR4_NEW_SUB_HEADER:
{
var fh = new FileHeader(header, reader, HeaderType.NewSub);
SkipData(fh, reader);
return fh;
}
{
var fh = new FileHeader(header, reader, HeaderType.NewSub);
SkipData(fh, reader);
return fh;
}
case HeaderCodeV.RAR5_FILE_HEADER:
case HeaderCodeV.RAR4_FILE_HEADER:
{
var fh = new FileHeader(header, reader, HeaderType.File);
switch (StreamingMode)
{
var fh = new FileHeader(header, reader, HeaderType.File);
switch (StreamingMode)
case StreamingMode.Seekable:
{
fh.DataStartPosition = reader.BaseStream.Position;
reader.BaseStream.Position += fh.CompressedSize;
}
break;
case StreamingMode.Streaming:
{
var ms = new ReadOnlySubStream(
reader.BaseStream,
fh.CompressedSize
);
if (fh.R4Salt is null)
{
fh.PackedStream = ms;
}
else
{
fh.PackedStream = new RarCryptoWrapper(
ms,
Options.Password!,
fh.R4Salt
);
}
}
break;
default:
{
case StreamingMode.Seekable:
{
fh.DataStartPosition = reader.BaseStream.Position;
reader.BaseStream.Position += fh.CompressedSize;
}
break;
case StreamingMode.Streaming:
{
var ms = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize);
if (fh.R4Salt is null)
{
fh.PackedStream = ms;
}
else
{
fh.PackedStream = new RarCryptoWrapper(ms, Options.Password!, fh.R4Salt);
}
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
throw new InvalidFormatException("Invalid StreamingMode");
}
return fh;
}
return fh;
}
case HeaderCodeV.RAR5_END_ARCHIVE_HEADER:
case HeaderCodeV.RAR4_END_ARCHIVE_HEADER:
{
return new EndArchiveHeader(header, reader);
}
{
return new EndArchiveHeader(header, reader);
}
case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER:
{
var ch = new ArchiveCryptHeader(header, reader);
IsEncrypted = true;
return ch;
}
{
var ch = new ArchiveCryptHeader(header, reader);
IsEncrypted = true;
return ch;
}
default:
{
throw new InvalidFormatException("Unknown Rar Header: " + header.HeaderCode);
}
{
throw new InvalidFormatException("Unknown Rar Header: " + header.HeaderCode);
}
}
}
@@ -167,21 +184,23 @@ namespace SharpCompress.Common.Rar.Headers
switch (StreamingMode)
{
case StreamingMode.Seekable:
{
fh.DataStartPosition = reader.BaseStream.Position;
reader.BaseStream.Position += fh.CompressedSize;
}
break;
case StreamingMode.Streaming:
{
//skip the data because it's useless?
reader.BaseStream.Skip(fh.CompressedSize);
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
{
throw new InvalidFormatException("Invalid StreamingMode");
}
}
}
}

View File

@@ -26,4 +26,4 @@ namespace SharpCompress.Common.Rar.Headers
internal short UserNameSize { get; private set; }
}
}
}

View File

@@ -8,10 +8,7 @@ namespace SharpCompress.Common.Rar
{
private uint _currentCrc;
public RarCrcBinaryReader(Stream stream)
: base(stream)
{
}
public RarCrcBinaryReader(Stream stream) : base(stream) { }
public uint GetCrc32()
{
@@ -47,4 +44,4 @@ namespace SharpCompress.Common.Rar
return result;
}
}
}
}

View File

@@ -11,8 +11,7 @@ namespace SharpCompress.Common.Rar
private readonly Queue<byte> _data = new Queue<byte>();
private long _readCount;
public RarCryptoBinaryReader(Stream stream, string password)
: base(stream)
public RarCryptoBinaryReader(Stream stream, string password) : base(stream)
{
_password = password;
@@ -108,4 +107,4 @@ namespace SharpCompress.Common.Rar
ClearQueue();
}
}
}
}

View File

@@ -10,7 +10,11 @@ namespace SharpCompress.Common.Rar
/// <summary>
/// As the V2017 port isn't complete, add this check to use the legacy Rar code.
/// </summary>
internal bool IsRarV3 => FileHeader.CompressionAlgorithm == 20 || FileHeader.CompressionAlgorithm == 26 || FileHeader.CompressionAlgorithm == 29 || FileHeader.CompressionAlgorithm == 36; //Nanook - Added 20+26 as Test arc from WinRar2.8 (algo 20) was failing with 2017 code
internal bool IsRarV3 =>
FileHeader.CompressionAlgorithm == 20
|| FileHeader.CompressionAlgorithm == 26
|| FileHeader.CompressionAlgorithm == 29
|| FileHeader.CompressionAlgorithm == 36; //Nanook - Added 20+26 as Test arc from WinRar2.8 (algo 20) was failing with 2017 code
/// <summary>
/// The File's 32 bit CRC Hash
@@ -58,8 +62,13 @@ namespace SharpCompress.Common.Rar
public override string ToString()
{
return string.Format("Entry Path: {0} Compressed Size: {1} Uncompressed Size: {2} CRC: {3}",
Key, CompressedSize, Size, Crc);
return string.Format(
"Entry Path: {0} Compressed Size: {1} Uncompressed Size: {2} CRC: {3}",
Key,
CompressedSize,
Size,
Crc
);
}
}
}
}

View File

@@ -8,8 +8,7 @@ namespace SharpCompress.Common.Rar
/// </summary>
internal abstract class RarFilePart : FilePart
{
internal RarFilePart(MarkHeader mh, FileHeader fh, int index)
: base(fh.ArchiveEncoding)
internal RarFilePart(MarkHeader mh, FileHeader fh, int index) : base(fh.ArchiveEncoding)
{
MarkHeader = mh;
FileHeader = fh;

View File

@@ -24,7 +24,6 @@ namespace SharpCompress.Common.Rar
private void Initialize()
{
_rijndael = new RijndaelEngine();
_aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE];
int rawLength = 2 * _password.Length;
@@ -52,11 +51,14 @@ namespace SharpCompress.Common.Rar
data[i * (rawPassword.Length + iblock) + rawPassword.Length + 0] = (byte)i;
data[i * (rawPassword.Length + iblock) + rawPassword.Length + 1] = (byte)(i >> 8);
data[i * (rawPassword.Length + iblock) + rawPassword.Length + 2] = (byte)(i >> CRYPTO_BLOCK_SIZE);
data[i * (rawPassword.Length + iblock) + rawPassword.Length + 2] = (byte)(
i >> CRYPTO_BLOCK_SIZE
);
if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0)
{
digest = SHA1.Create().ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
digest = SHA1.Create()
.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
_aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19];
}
}
@@ -68,16 +70,18 @@ namespace SharpCompress.Common.Rar
{
for (int j = 0; j < 4; j++)
{
aesKey[i * 4 + j] = (byte)
(((digest[i * 4] * 0x1000000) & 0xff000000 |
(uint)((digest[i * 4 + 1] * 0x10000) & 0xff0000) |
(uint)((digest[i * 4 + 2] * 0x100) & 0xff00) |
(uint)(digest[i * 4 + 3] & 0xff)) >> (j * 8));
aesKey[i * 4 + j] = (byte)(
(
(digest[i * 4] * 0x1000000) & 0xff000000
| (uint)((digest[i * 4 + 1] * 0x10000) & 0xff0000)
| (uint)((digest[i * 4 + 2] * 0x100) & 0xff00)
| (uint)(digest[i * 4 + 3] & 0xff)
) >> (j * 8)
);
}
}
_rijndael.Init(false, new KeyParameter(aesKey));
}
public static RarRijndael InitializeFrom(string password, byte[] salt)
@@ -106,8 +110,6 @@ namespace SharpCompress.Common.Rar
return decryptedBytes;
}
public void Dispose()
{
}
public void Dispose() { }
}
}

View File

@@ -24,6 +24,7 @@ namespace SharpCompress.Common.Rar
#nullable disable
internal ArchiveHeader ArchiveHeader { get; private set; }
#nullable enable
internal StreamingMode Mode => _headerFactory.StreamingMode;
@@ -40,16 +41,19 @@ namespace SharpCompress.Common.Rar
switch (header.HeaderType)
{
case HeaderType.Mark:
{
lastMarkHeader = (MarkHeader)header;
}
break;
case HeaderType.Archive:
{
ArchiveHeader = (ArchiveHeader)header;
}
break;
case HeaderType.File:
{
var fh = (FileHeader)header;
if (_maxCompressionAlgorithm < fh.CompressionAlgorithm)
@@ -58,17 +62,22 @@ namespace SharpCompress.Common.Rar
}
break;
case HeaderType.Service:
{
var fh = (FileHeader)header;
if (fh.FileName == "CMT")
{
var part = CreateFilePart(lastMarkHeader!, fh);
var buffer = new byte[fh.CompressedSize];
part.GetCompressedStream().Read(buffer, 0, buffer.Length);
Comment = System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1);
}
}
break;
{
var fh = (FileHeader)header;
if (fh.FileName == "CMT")
{
var part = CreateFilePart(lastMarkHeader!, fh);
var buffer = new byte[fh.CompressedSize];
part.GetCompressedStream().Read(buffer, 0, buffer.Length);
Comment = System.Text.Encoding.UTF8.GetString(
buffer,
0,
buffer.Length - 1
);
}
}
break;
}
}
}
@@ -79,7 +88,9 @@ namespace SharpCompress.Common.Rar
{
if (Mode == StreamingMode.Streaming)
{
throw new InvalidOperationException("ArchiveHeader should never been null in a streaming read.");
throw new InvalidOperationException(
"ArchiveHeader should never been null in a streaming read."
);
}
// we only want to load the archive header to avoid overhead but have to do the nasty thing and reset the stream
@@ -157,7 +168,7 @@ namespace SharpCompress.Common.Rar
return 1;
}
}
public string? Comment { get; internal set; }
}
}

View File

@@ -15,4 +15,4 @@ namespace SharpCompress.Common
public ReaderProgress? ReaderProgress { get; }
}
}
}

View File

@@ -48,10 +48,10 @@ namespace SharpCompress.Common.SevenZip
internal bool IsEmpty()
{
return _packSizes.Count == 0
&& _packCrCs.Count == 0
&& _folders.Count == 0
&& _numUnpackStreamsVector.Count == 0
&& _files.Count == 0;
&& _packCrCs.Count == 0
&& _folders.Count == 0
&& _numUnpackStreamsVector.Count == 0
&& _files.Count == 0;
}
private void FillStartPos()
@@ -161,7 +161,13 @@ namespace SharpCompress.Common.SevenZip
packSizes[j] = _packSizes[packStreamIndex + j];
}
return DecoderStreamHelper.CreateDecoderStream(stream, folderStartPackPos, packSizes, folder, pw);
return DecoderStreamHelper.CreateDecoderStream(
stream,
folderStartPackPos,
packSizes,
folder,
pw
);
}
private long GetFolderPackStreamSize(int folderIndex, int streamIndex)

View File

@@ -154,7 +154,11 @@ namespace SharpCompress.Common.SevenZip
return ReadBitVector(length);
}
private void ReadNumberVector(List<byte[]> dataVector, int numFiles, Action<int, long?> action)
private void ReadNumberVector(
List<byte[]> dataVector,
int numFiles,
Action<int, long?> action
)
{
var defined = ReadOptionalBitVector(numFiles);
@@ -191,12 +195,24 @@ namespace SharpCompress.Common.SevenZip
return null;
}
private void ReadDateTimeVector(List<byte[]> dataVector, int numFiles, Action<int, DateTime?> action)
private void ReadDateTimeVector(
List<byte[]> dataVector,
int numFiles,
Action<int, DateTime?> action
)
{
ReadNumberVector(dataVector, numFiles, (index, value) => action(index, TranslateTime(value)));
ReadNumberVector(
dataVector,
numFiles,
(index, value) => action(index, TranslateTime(value))
);
}
private void ReadAttributeVector(List<byte[]> dataVector, int numFiles, Action<int, uint?> action)
private void ReadAttributeVector(
List<byte[]> dataVector,
int numFiles,
Action<int, uint?> action
)
{
BitVector boolVector = ReadOptionalBitVector(numFiles);
using (var streamSwitch = new CStreamSwitch())
@@ -251,7 +267,16 @@ namespace SharpCompress.Common.SevenZip
byte[] longId = new byte[idSize];
ReadBytes(longId, 0, idSize);
#if DEBUG
Log.WriteLine("MethodId: " + String.Join("", Enumerable.Range(0, idSize).Select(x => longId[x].ToString("x2")).ToArray()));
Log.WriteLine(
"MethodId: "
+ String.Join(
"",
Enumerable
.Range(0, idSize)
.Select(x => longId[x].ToString("x2"))
.ToArray()
)
);
#endif
if (idSize > 8)
{
@@ -269,7 +294,13 @@ namespace SharpCompress.Common.SevenZip
coder._numInStreams = ReadNum();
coder._numOutStreams = ReadNum();
#if DEBUG
Log.WriteLine("Complex Stream (In: " + coder._numInStreams + " - Out: " + coder._numOutStreams + ")");
Log.WriteLine(
"Complex Stream (In: "
+ coder._numInStreams
+ " - Out: "
+ coder._numOutStreams
+ ")"
);
#endif
}
else
@@ -287,7 +318,13 @@ namespace SharpCompress.Common.SevenZip
coder._props = new byte[propsSize];
ReadBytes(coder._props, 0, propsSize);
#if DEBUG
Log.WriteLine("Settings: " + String.Join("", coder._props.Select(bt => bt.ToString("x2")).ToArray()));
Log.WriteLine(
"Settings: "
+ String.Join(
"",
coder._props.Select(bt => bt.ToString("x2")).ToArray()
)
);
#endif
}
@@ -414,7 +451,11 @@ namespace SharpCompress.Common.SevenZip
return digests;
}
private void ReadPackInfo(out long dataOffset, out List<long> packSizes, out List<uint?> packCrCs)
private void ReadPackInfo(
out long dataOffset,
out List<long> packSizes,
out List<uint?> packCrCs
)
{
#if DEBUG
Log.WriteLine("-- ReadPackInfo --");
@@ -568,8 +609,12 @@ namespace SharpCompress.Common.SevenZip
}
}
private void ReadSubStreamsInfo(List<CFolder> folders, out List<int> numUnpackStreamsInFolders,
out List<long> unpackSizes, out List<uint?> digests)
private void ReadSubStreamsInfo(
List<CFolder> folders,
out List<int> numUnpackStreamsInFolders,
out List<long> unpackSizes,
out List<uint?> digests
)
{
#if DEBUG
Log.WriteLine("-- ReadSubStreamsInfo --");
@@ -739,7 +784,8 @@ namespace SharpCompress.Common.SevenZip
out List<CFolder> folders,
out List<int> numUnpackStreamsInFolders,
out List<long> unpackSizes,
out List<uint?> digests)
out List<uint?> digests
)
{
#if DEBUG
Log.WriteLine("-- ReadStreamsInfo --");
@@ -768,7 +814,12 @@ namespace SharpCompress.Common.SevenZip
ReadUnpackInfo(dataVector, out folders);
break;
case BlockType.SubStreamsInfo:
ReadSubStreamsInfo(folders, out numUnpackStreamsInFolders, out unpackSizes, out digests);
ReadSubStreamsInfo(
folders,
out numUnpackStreamsInFolders,
out unpackSizes,
out digests
);
break;
default:
throw new InvalidOperationException();
@@ -791,14 +842,16 @@ namespace SharpCompress.Common.SevenZip
#endif
try
{
ReadStreamsInfo(null,
out long dataStartPos,
out List<long> packSizes,
out List<uint?> packCrCs,
out List<CFolder> folders,
out List<int> numUnpackStreamsInFolders,
out List<long> unpackSizes,
out List<uint?> digests);
ReadStreamsInfo(
null,
out long dataStartPos,
out List<long> packSizes,
out List<uint?> packCrCs,
out List<CFolder> folders,
out List<int> numUnpackStreamsInFolders,
out List<long> unpackSizes,
out List<uint?> digests
);
dataStartPos += baseOffset;
@@ -815,23 +868,35 @@ namespace SharpCompress.Common.SevenZip
dataStartPos += packSize;
}
var outStream = DecoderStreamHelper.CreateDecoderStream(_stream, oldDataStartPos, myPackSizes,
folder, pass);
var outStream = DecoderStreamHelper.CreateDecoderStream(
_stream,
oldDataStartPos,
myPackSizes,
folder,
pass
);
int unpackSize = checked((int)folder.GetUnpackSize());
byte[] data = new byte[unpackSize];
outStream.ReadExact(data, 0, data.Length);
if (outStream.ReadByte() >= 0)
{
throw new InvalidOperationException("Decoded stream is longer than expected.");
throw new InvalidOperationException(
"Decoded stream is longer than expected."
);
}
dataVector.Add(data);
if (folder.UnpackCrcDefined)
{
if (Crc.Finish(Crc.Update(Crc.INIT_CRC, data, 0, unpackSize)) != folder._unpackCrc)
if (
Crc.Finish(Crc.Update(Crc.INIT_CRC, data, 0, unpackSize))
!= folder._unpackCrc
)
{
throw new InvalidOperationException("Decoded stream does not match expected CRC.");
throw new InvalidOperationException(
"Decoded stream does not match expected CRC."
);
}
}
}
@@ -864,7 +929,10 @@ namespace SharpCompress.Common.SevenZip
List<byte[]> dataVector = null;
if (type == BlockType.AdditionalStreamsInfo)
{
dataVector = ReadAndDecodePackedStreams(db._startPositionAfterHeader, getTextPassword);
dataVector = ReadAndDecodePackedStreams(
db._startPositionAfterHeader,
getTextPassword
);
type = ReadId();
}
@@ -873,14 +941,16 @@ namespace SharpCompress.Common.SevenZip
if (type == BlockType.MainStreamsInfo)
{
ReadStreamsInfo(dataVector,
out db._dataStartPosition,
out db._packSizes,
out db._packCrCs,
out db._folders,
out db._numUnpackStreamsVector,
out unpackSizes,
out digests);
ReadStreamsInfo(
dataVector,
out db._dataStartPosition,
out db._packSizes,
out db._packCrCs,
out db._folders,
out db._numUnpackStreamsVector,
out unpackSizes,
out digests
);
db._dataStartPosition += db._startPositionAfterHeader;
type = ReadId();
@@ -961,35 +1031,41 @@ namespace SharpCompress.Common.SevenZip
#if DEBUG
Log.Write("WinAttributes:");
#endif
ReadAttributeVector(dataVector, numFiles, delegate (int i, uint? attr)
{
// Some third party implementations established an unofficial extension
// of the 7z archive format by placing posix file attributes in the high
// bits of the windows file attributes. This makes use of the fact that
// the official implementation does not perform checks on this value.
//
// Newer versions of the official 7z GUI client will try to parse this
// extension, thus acknowledging the unofficial use of these bits.
//
// For us it is safe to just discard the upper bits if they are set and
// keep the windows attributes from the lower bits (which should be set
// properly even if posix file attributes are present, in order to be
// compatible with older 7z archive readers)
//
// Note that the 15th bit is used by some implementations to indicate
// presence of the extension, but not all implementations do that so
// we can't trust that bit and must ignore it.
//
if (attr.HasValue && (attr.Value >> 16) != 0)
{
attr = attr.Value & 0x7FFFu;
}
ReadAttributeVector(
dataVector,
numFiles,
delegate(int i, uint? attr)
{
// Some third party implementations established an unofficial extension
// of the 7z archive format by placing posix file attributes in the high
// bits of the windows file attributes. This makes use of the fact that
// the official implementation does not perform checks on this value.
//
// Newer versions of the official 7z GUI client will try to parse this
// extension, thus acknowledging the unofficial use of these bits.
//
// For us it is safe to just discard the upper bits if they are set and
// keep the windows attributes from the lower bits (which should be set
// properly even if posix file attributes are present, in order to be
// compatible with older 7z archive readers)
//
// Note that the 15th bit is used by some implementations to indicate
// presence of the extension, but not all implementations do that so
// we can't trust that bit and must ignore it.
//
if (attr.HasValue && (attr.Value >> 16) != 0)
{
attr = attr.Value & 0x7FFFu;
}
db._files[i].Attrib = attr;
db._files[i].Attrib = attr;
#if DEBUG
Log.Write(" " + (attr.HasValue ? attr.Value.ToString("x8") : "n/a"));
Log.Write(
" " + (attr.HasValue ? attr.Value.ToString("x8") : "n/a")
);
#endif
});
}
);
#if DEBUG
Log.WriteLine();
#endif
@@ -1049,13 +1125,24 @@ namespace SharpCompress.Common.SevenZip
#if DEBUG
Log.Write("StartPos:");
#endif
ReadNumberVector(dataVector, numFiles, delegate (int i, long? startPos)
{
db._files[i].StartPos = startPos;
ReadNumberVector(
dataVector,
numFiles,
delegate(int i, long? startPos)
{
db._files[i].StartPos = startPos;
#if DEBUG
Log.Write(" " + (startPos.HasValue ? startPos.Value.ToString() : "n/a"));
Log.Write(
" "
+ (
startPos.HasValue
? startPos.Value.ToString()
: "n/a"
)
);
#endif
});
}
);
#if DEBUG
Log.WriteLine();
#endif
@@ -1064,13 +1151,19 @@ namespace SharpCompress.Common.SevenZip
#if DEBUG
Log.Write("CTime:");
#endif
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
{
db._files[i].CTime = time;
ReadDateTimeVector(
dataVector,
numFiles,
delegate(int i, DateTime? time)
{
db._files[i].CTime = time;
#if DEBUG
Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a"));
Log.Write(
" " + (time.HasValue ? time.Value.ToString() : "n/a")
);
#endif
});
}
);
#if DEBUG
Log.WriteLine();
#endif
@@ -1079,13 +1172,19 @@ namespace SharpCompress.Common.SevenZip
#if DEBUG
Log.Write("ATime:");
#endif
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
{
db._files[i].ATime = time;
ReadDateTimeVector(
dataVector,
numFiles,
delegate(int i, DateTime? time)
{
db._files[i].ATime = time;
#if DEBUG
Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a"));
Log.Write(
" " + (time.HasValue ? time.Value.ToString() : "n/a")
);
#endif
});
}
);
#if DEBUG
Log.WriteLine();
#endif
@@ -1094,13 +1193,19 @@ namespace SharpCompress.Common.SevenZip
#if DEBUG
Log.Write("MTime:");
#endif
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
{
db._files[i].MTime = time;
ReadDateTimeVector(
dataVector,
numFiles,
delegate(int i, DateTime? time)
{
db._files[i].MTime = time;
#if DEBUG
Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a"));
Log.Write(
" " + (time.HasValue ? time.Value.ToString() : "n/a")
);
#endif
});
}
);
#if DEBUG
Log.WriteLine();
#endif
@@ -1175,7 +1280,7 @@ namespace SharpCompress.Common.SevenZip
// TODO: Check Signature!
_header = new byte[0x20];
for (int offset = 0; offset < 0x20;)
for (int offset = 0; offset < 0x20; )
{
int delta = stream.Read(_header, offset, 0x20 - offset);
if (delta == 0)
@@ -1273,7 +1378,10 @@ namespace SharpCompress.Common.SevenZip
throw new InvalidOperationException();
}
var dataVector = ReadAndDecodePackedStreams(db._startPositionAfterHeader, db.PasswordProvider);
var dataVector = ReadAndDecodePackedStreams(
db._startPositionAfterHeader,
db.PasswordProvider
);
// compressed header without content is odd but ok
if (dataVector.Count == 0)
@@ -1346,7 +1454,11 @@ namespace SharpCompress.Common.SevenZip
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
@@ -1369,7 +1481,10 @@ namespace SharpCompress.Common.SevenZip
private void ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses.Count && _db._files[_startIndex + _currentIndex].Size == 0)
while (
_currentIndex < _extractStatuses.Count
&& _db._files[_startIndex + _currentIndex].Size == 0
)
{
OpenFile();
_stream.Dispose();
@@ -1449,8 +1564,13 @@ namespace SharpCompress.Common.SevenZip
packSizes[j] = db._packSizes[packStreamIndex + j];
}
s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes, folderInfo,
db.PasswordProvider);
s = DecoderStreamHelper.CreateDecoderStream(
_stream,
folderStartPackPos,
packSizes,
folderInfo,
db.PasswordProvider
);
_cachedStreams.Add(folderIndex, s);
}
return s;
@@ -1482,9 +1602,7 @@ namespace SharpCompress.Common.SevenZip
{
bool allFilesMode = (indices is null);
int numItems = allFilesMode
? db._files.Count
: indices.Length;
int numItems = allFilesMode ? db._files.Count : indices.Length;
if (numItems == 0)
{
@@ -1503,7 +1621,10 @@ namespace SharpCompress.Common.SevenZip
continue;
}
if (extractFolderInfoVector.Count == 0 || folderIndex != extractFolderInfoVector.Last()._folderIndex)
if (
extractFolderInfoVector.Count == 0
|| folderIndex != extractFolderInfoVector.Last()._folderIndex
)
{
extractFolderInfoVector.Add(new CExtractFolderInfo(-1, folderIndex));
}
@@ -1511,7 +1632,11 @@ namespace SharpCompress.Common.SevenZip
CExtractFolderInfo efi = extractFolderInfoVector.Last();
int startIndex = db._folderStartFileIndex[folderIndex];
for (int index = efi._extractStatuses.Count; index <= fileIndex - startIndex; index++)
for (
int index = efi._extractStatuses.Count;
index <= fileIndex - startIndex;
index++
)
{
efi._extractStatuses.Add(index == fileIndex - startIndex);
}
@@ -1552,8 +1677,13 @@ namespace SharpCompress.Common.SevenZip
// TODO: If the decoding fails the last file may be extracted incompletely. Delete it?
Stream s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes,
folderInfo, db.PasswordProvider);
Stream s = DecoderStreamHelper.CreateDecoderStream(
_stream,
folderStartPackPos,
packSizes,
folderInfo,
db.PasswordProvider
);
buffer ??= new byte[4 << 10];
for (; ; )
{

View File

@@ -5,4 +5,4 @@
internal int _inIndex;
internal int _outIndex;
}
}
}

View File

@@ -9,4 +9,4 @@ namespace SharpCompress.Common.SevenZip
internal int _numInStreams;
internal int _numOutStreams;
}
}
}

View File

@@ -35,4 +35,4 @@ namespace SharpCompress.Common.SevenZip
HasStream = true;
}
}
}
}

View File

@@ -54,4 +54,4 @@
return bytes;
}
}
}
}

View File

@@ -66,4 +66,4 @@ namespace SharpCompress.Common.SevenZip
}
}
}
}
}

View File

@@ -12,21 +12,21 @@ namespace SharpCompress.Common.SevenZip
public static uint Get32(byte[] buffer, int offset)
{
return buffer[offset]
+ ((uint)buffer[offset + 1] << 8)
+ ((uint)buffer[offset + 2] << 16)
+ ((uint)buffer[offset + 3] << 24);
+ ((uint)buffer[offset + 1] << 8)
+ ((uint)buffer[offset + 2] << 16)
+ ((uint)buffer[offset + 3] << 24);
}
public static ulong Get64(byte[] buffer, int offset)
{
return buffer[offset]
+ ((ulong)buffer[offset + 1] << 8)
+ ((ulong)buffer[offset + 2] << 16)
+ ((ulong)buffer[offset + 3] << 24)
+ ((ulong)buffer[offset + 4] << 32)
+ ((ulong)buffer[offset + 5] << 40)
+ ((ulong)buffer[offset + 6] << 48)
+ ((ulong)buffer[offset + 7] << 56);
+ ((ulong)buffer[offset + 1] << 8)
+ ((ulong)buffer[offset + 2] << 16)
+ ((ulong)buffer[offset + 3] << 24)
+ ((ulong)buffer[offset + 4] << 32)
+ ((ulong)buffer[offset + 5] << 40)
+ ((ulong)buffer[offset + 6] << 48)
+ ((ulong)buffer[offset + 7] << 56);
}
#endregion
@@ -183,4 +183,4 @@ namespace SharpCompress.Common.SevenZip
#endregion
}
}
}

View File

@@ -38,8 +38,9 @@ namespace SharpCompress.Common.SevenZip
public override bool IsSplitAfter => false;
public override int? Attrib => FilePart.Header.Attrib.HasValue ? (int?)FilePart.Header.Attrib.Value : null;
public override int? Attrib =>
FilePart.Header.Attrib.HasValue ? (int?)FilePart.Header.Attrib.Value : null;
internal override IEnumerable<FilePart> Parts => FilePart.AsEnumerable<FilePart>();
}
}
}

View File

@@ -11,8 +11,13 @@ namespace SharpCompress.Common.SevenZip
private readonly Stream _stream;
private readonly ArchiveDatabase _database;
internal SevenZipFilePart(Stream stream, ArchiveDatabase database, int index, CFileItem fileEntry, ArchiveEncoding archiveEncoding)
: base(archiveEncoding)
internal SevenZipFilePart(
Stream stream,
ArchiveDatabase database,
int index,
CFileItem fileEntry,
ArchiveEncoding archiveEncoding
) : base(archiveEncoding)
{
_stream = stream;
_database = database;
@@ -40,9 +45,15 @@ namespace SharpCompress.Common.SevenZip
{
return null!;
}
var folderStream = _database.GetFolderStream(_stream, Folder!, _database.PasswordProvider);
var folderStream = _database.GetFolderStream(
_stream,
Folder!,
_database.PasswordProvider
);
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++)
@@ -86,22 +97,23 @@ namespace SharpCompress.Common.SevenZip
{
case K_LZMA:
case K_LZMA2:
{
return CompressionType.LZMA;
}
{
return CompressionType.LZMA;
}
case K_PPMD:
{
return CompressionType.PPMd;
}
{
return CompressionType.PPMd;
}
case K_B_ZIP2:
{
return CompressionType.BZip2;
}
{
return CompressionType.BZip2;
}
default:
throw new NotImplementedException();
}
}
internal bool IsEncrypted => Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
internal bool IsEncrypted =>
Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
}
}

View File

@@ -6,8 +6,6 @@ namespace SharpCompress.Common.SevenZip
public class SevenZipVolume : Volume
{
public SevenZipVolume(Stream stream, ReaderOptions readerFactoryOptions, int index = 0)
: base(stream, readerFactoryOptions, index)
{
}
: base(stream, readerFactoryOptions, index) { }
}
}

View File

@@ -16,4 +16,4 @@
VolumeHeader = (byte)'V',
GlobalExtendedHeader = (byte)'g'
}
}
}

View File

@@ -9,7 +9,15 @@ namespace SharpCompress.Common.Tar.Headers
{
internal sealed class TarHeader
{
internal static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
internal static readonly DateTime EPOCH = new DateTime(
1970,
1,
1,
0,
0,
0,
DateTimeKind.Utc
);
public TarHeader(ArchiveEncoding archiveEncoding)
{
@@ -79,7 +87,11 @@ namespace SharpCompress.Common.Tar.Headers
// var truncated = Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(bytes, 0, 100));
//
// and then infinite recursion is occured in WriteLongFilenameHeader because truncated.Length is 102.
Name = ArchiveEncoding.Decode(ArchiveEncoding.Encode(Name), 0, 100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1));
Name = ArchiveEncoding.Decode(
ArchiveEncoding.Encode(Name),
0,
100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1)
);
Write(output);
}
}
@@ -126,7 +138,7 @@ namespace SharpCompress.Common.Tar.Headers
Size = ReadSize(buffer);
Mode = ReadAsciiInt64Base8(buffer, 100, 7);
if(EntryType == EntryType.Directory)
if (EntryType == EntryType.Directory)
Mode |= 0b1_000_000_000;
UserId = ReadAsciiInt64Base8(buffer, 108, 7);
@@ -136,8 +148,7 @@ namespace SharpCompress.Common.Tar.Headers
Magic = ArchiveEncoding.Decode(buffer, 257, 6).TrimNulls();
if (!string.IsNullOrEmpty(Magic)
&& "ustar".Equals(Magic))
if (!string.IsNullOrEmpty(Magic) && "ustar".Equals(Magic))
{
string namePrefix = ArchiveEncoding.Decode(buffer, 345, 157);
namePrefix = namePrefix.TrimNulls();
@@ -146,8 +157,7 @@ namespace SharpCompress.Common.Tar.Headers
Name = namePrefix + "/" + Name;
}
}
if (EntryType != EntryType.LongName
&& Name.Length == 0)
if (EntryType != EntryType.LongName && Name.Length == 0)
{
return false;
}
@@ -261,10 +271,16 @@ namespace SharpCompress.Common.Tar.Headers
return Convert.ToInt64(s);
}
private static readonly byte[] eightSpaces = {
(byte)' ', (byte)' ', (byte)' ', (byte)' ',
(byte)' ', (byte)' ', (byte)' ', (byte)' '
private static readonly byte[] eightSpaces =
{
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' '
};
internal static int RecalculateChecksum(byte[] buf)

View File

@@ -47,13 +47,17 @@ namespace SharpCompress.Common.Tar
public long Mode => _filePart.Header.Mode;
public long UserID => _filePart.Header.UserId;
public long GroupId => _filePart.Header.GroupId;
internal override IEnumerable<FilePart> Parts => _filePart.AsEnumerable<FilePart>();
internal static IEnumerable<TarEntry> GetEntries(StreamingMode mode, Stream stream,
CompressionType compressionType, ArchiveEncoding archiveEncoding)
internal static IEnumerable<TarEntry> GetEntries(
StreamingMode mode,
Stream stream,
CompressionType compressionType,
ArchiveEncoding archiveEncoding
)
{
foreach (TarHeader h in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding))
{
@@ -71,4 +75,4 @@ namespace SharpCompress.Common.Tar
}
}
}
}
}

View File

@@ -8,8 +8,7 @@ namespace SharpCompress.Common.Tar
{
private readonly Stream _seekableStream;
internal TarFilePart(TarHeader header, Stream seekableStream)
: base(header.ArchiveEncoding)
internal TarFilePart(TarHeader header, Stream seekableStream) : base(header.ArchiveEncoding)
{
_seekableStream = seekableStream;
Header = header;
@@ -34,4 +33,4 @@ namespace SharpCompress.Common.Tar
return null;
}
}
}
}

View File

@@ -7,7 +7,11 @@ namespace SharpCompress.Common.Tar
{
internal static class TarHeaderFactory
{
internal static IEnumerable<TarHeader?> ReadHeader(StreamingMode mode, Stream stream, ArchiveEncoding archiveEncoding)
internal static IEnumerable<TarHeader?> ReadHeader(
StreamingMode mode,
Stream stream,
ArchiveEncoding archiveEncoding
)
{
while (true)
{
@@ -24,6 +28,7 @@ namespace SharpCompress.Common.Tar
switch (mode)
{
case StreamingMode.Seekable:
{
header.DataStartPosition = reader.BaseStream.Position;
@@ -32,14 +37,15 @@ namespace SharpCompress.Common.Tar
}
break;
case StreamingMode.Streaming:
{
header.PackedStream = new TarReadOnlySubStream(stream, header.Size);
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
{
throw new InvalidFormatException("Invalid StreamingMode");
}
}
}
catch
@@ -60,4 +66,4 @@ namespace SharpCompress.Common.Tar
return 512 - zeros + size;
}
}
}
}

View File

@@ -9,7 +9,8 @@ namespace SharpCompress.Common.Tar
private bool _isDisposed;
private long _amountRead;
public TarReadOnlySubStream(Stream stream, long bytesToRead) : base(stream, throwOnDispose: false)
public TarReadOnlySubStream(Stream stream, long bytesToRead)
: base(stream, throwOnDispose: false)
{
BytesLeftToRead = bytesToRead;
}
@@ -56,7 +57,11 @@ namespace SharpCompress.Common.Tar
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
@@ -86,7 +91,6 @@ namespace SharpCompress.Common.Tar
++_amountRead;
}
return value;
}
public override long Seek(long offset, SeekOrigin origin)
@@ -104,4 +108,4 @@ namespace SharpCompress.Common.Tar
throw new NotSupportedException();
}
}
}
}

View File

@@ -6,8 +6,6 @@ namespace SharpCompress.Common.Tar
public class TarVolume : Volume
{
public TarVolume(Stream stream, ReaderOptions readerOptions, int index = 0)
: base(stream, readerOptions, index)
{
}
: base(stream, readerOptions, index) { }
}
}

View File

@@ -32,7 +32,10 @@ namespace SharpCompress.Common
public virtual int Index { get; internal set; }
public string FileName { get { return (_actualStream as FileStream)?.Name!; } }
public string FileName
{
get { return (_actualStream as FileStream)?.Name!; }
}
/// <summary>
/// RarArchive is part of a multi-part archive.

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