mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-05 05:24:56 +00:00
Compare commits
6 Commits
system_buf
...
0.14.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a64fe28b0 | ||
|
|
e320ccfa9a | ||
|
|
9628ff9456 | ||
|
|
d540f78cfc | ||
|
|
66420cd299 | ||
|
|
dd0594471f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,3 +13,4 @@ project.lock.json
|
||||
test/TestArchives/Scratch
|
||||
.vs
|
||||
tools
|
||||
.vscode
|
||||
|
||||
@@ -10,7 +10,7 @@ Writer classes allow forward-only Writing
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Rar | Rar | Decompress (1) | RarArchive | RarReader | N/A |
|
||||
| Zip (2) | None, DEFLATE, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
|
||||
| Tar | None, BZip2, GZip | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| Tar | None, BZip2, GZip, LZip | Both | TarArchive | TarReader | TarWriter (3) |
|
||||
| GZip (single file) | GZip | Both | GZipArchive | GZipReader | GZipWriter |
|
||||
| 7Zip (4) | LZMA, LZMA2, BZip2, PPMd, BCJ, BCJ2, Deflate | Decompress | SevenZipArchive | N/A | N/A |
|
||||
|
||||
@@ -30,3 +30,4 @@ For those who want to directly compress/decompress bits
|
||||
| LZMAStream | Both |
|
||||
| PPMdStream | Both |
|
||||
| ADCStream | Decompress |
|
||||
| LZipStream | Decompress |
|
||||
|
||||
@@ -31,6 +31,10 @@ I'm always looking for help or ideas. Please submit code or email with ideas. Un
|
||||
|
||||
## Version Log
|
||||
|
||||
### Version 0.14.0
|
||||
|
||||
* [Support for LZip reading in for Tars](https://github.com/adamhathcock/sharpcompress/pull/191)
|
||||
|
||||
### Version 0.13.1
|
||||
|
||||
* [Fix null password on ReaderFactory. Fix null options on SevenZipArchive](https://github.com/adamhathcock/sharpcompress/pull/188)
|
||||
|
||||
6
USAGE.md
6
USAGE.md
@@ -80,7 +80,7 @@ using (var archive = RarArchive.Open("Test.rar"))
|
||||
### Use ReaderFactory to autodetect archive type and Open the entry stream
|
||||
|
||||
```C#
|
||||
using (Stream stream = File.OpenRead("Tar.tar.bz2")))
|
||||
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
|
||||
using (var reader = ReaderFactory.Open(stream))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
@@ -101,7 +101,7 @@ using (var reader = ReaderFactory.Open(stream))
|
||||
### Use ReaderFactory to autodetect archive type and Open the entry stream
|
||||
|
||||
```C#
|
||||
using (Stream stream = File.OpenRead("Tar.tar.bz2")))
|
||||
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
|
||||
using (var reader = ReaderFactory.Open(stream))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
@@ -128,4 +128,4 @@ using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOption
|
||||
{
|
||||
writer.WriteAll("D:\\temp", "*", SearchOption.AllDirectories);
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.GZip;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.GZip;
|
||||
using SharpCompress.Writers;
|
||||
@@ -104,28 +103,26 @@ namespace SharpCompress.Archives.GZip
|
||||
public static bool IsGZipFile(Stream stream)
|
||||
{
|
||||
// read the header on the first read
|
||||
using (var header = ByteArrayPool.RentScope(10))
|
||||
byte[] header = new byte[10];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
int n = stream.Read(header);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n != 10)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n != 10)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -141,10 +141,8 @@ namespace SharpCompress.Archives.SevenZip
|
||||
private static bool SignatureMatch(Stream stream)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
using (var signatureBytes = reader.ReadScope(6))
|
||||
{
|
||||
return signatureBytes.BinaryEquals(SIGNATURE);
|
||||
}
|
||||
byte[] signatureBytes = reader.ReadBytes(6);
|
||||
return signatureBytes.BinaryEquals(SIGNATURE);
|
||||
}
|
||||
|
||||
protected override IReader CreateReaderForSolidExtraction()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
LZMA,
|
||||
BCJ,
|
||||
BCJ2,
|
||||
LZip,
|
||||
Unknown
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using SharpCompress.Common.Tar.Headers;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.Converters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.GZip
|
||||
{
|
||||
@@ -37,85 +36,79 @@ namespace SharpCompress.Common.GZip
|
||||
private void ReadAndValidateGzipHeader(Stream stream)
|
||||
{
|
||||
// read the header on the first read
|
||||
using (var header = ByteArrayPool.RentScope(10))
|
||||
byte[] header = new byte[10];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
int n = stream.Read(header);
|
||||
return;
|
||||
}
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (n != 10)
|
||||
{
|
||||
throw new ZlibException("Not a valid GZIP stream.");
|
||||
}
|
||||
|
||||
if (n != 10)
|
||||
{
|
||||
throw new ZlibException("Not a valid GZIP stream.");
|
||||
}
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
Int32 timet = DataConverter.LittleEndian.GetInt32(header, 4);
|
||||
DateModified = TarHeader.Epoch.AddSeconds(timet);
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = stream.Read(header, 0, 2); // 2-byte length field
|
||||
|
||||
Int32 timet = DataConverter.LittleEndian.GetInt32(header.Array, 4);
|
||||
DateModified = TarHeader.Epoch.AddSeconds(timet);
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
byte[] extra = new byte[extraLength];
|
||||
n = stream.Read(extra, 0, extra.Length);
|
||||
if (n != extraLength)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = stream.Read(header.Array, 0, 2); // 2-byte length field
|
||||
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
using (var extra = ByteArrayPool.RentScope(extraLength))
|
||||
{
|
||||
n = stream.Read(extra);
|
||||
if (n != extraLength)
|
||||
{
|
||||
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((header[3] & 0x08) == 0x08)
|
||||
{
|
||||
name = ReadZeroTerminatedString(stream);
|
||||
}
|
||||
if ((header[3] & 0x10) == 0x010)
|
||||
{
|
||||
ReadZeroTerminatedString(stream);
|
||||
}
|
||||
if ((header[3] & 0x02) == 0x02)
|
||||
{
|
||||
stream.ReadByte(); // CRC16, ignore
|
||||
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
|
||||
}
|
||||
}
|
||||
if ((header[3] & 0x08) == 0x08)
|
||||
{
|
||||
name = ReadZeroTerminatedString(stream);
|
||||
}
|
||||
if ((header[3] & 0x10) == 0x010)
|
||||
{
|
||||
ReadZeroTerminatedString(stream);
|
||||
}
|
||||
if ((header[3] & 0x02) == 0x02)
|
||||
{
|
||||
stream.ReadByte(); // CRC16, ignore
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadZeroTerminatedString(Stream stream)
|
||||
{
|
||||
using (var buf1 = ByteArrayPool.RentScope(1))
|
||||
byte[] buf1 = new byte[1];
|
||||
var list = new List<byte>();
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
var list = new List<byte>();
|
||||
bool done = false;
|
||||
do
|
||||
// workitem 7740
|
||||
int n = stream.Read(buf1, 0, 1);
|
||||
if (n != 1)
|
||||
{
|
||||
// workitem 7740
|
||||
int n = stream.Read(buf1);
|
||||
if (n != 1)
|
||||
{
|
||||
throw new ZlibException("Unexpected EOF reading GZIP header.");
|
||||
}
|
||||
if (buf1[0] == 0)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(buf1[0]);
|
||||
}
|
||||
throw new ZlibException("Unexpected EOF reading GZIP header.");
|
||||
}
|
||||
if (buf1[0] == 0)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(buf1[0]);
|
||||
}
|
||||
while (!done);
|
||||
byte[] a = list.ToArray();
|
||||
return ArchiveEncoding.Default.GetString(a, 0, a.Length);
|
||||
}
|
||||
while (!done);
|
||||
byte[] a = list.ToArray();
|
||||
return ArchiveEncoding.Default.GetString(a, 0, a.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,82 +47,81 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
nameSize = nameSize > 4 * 1024 ? (short)(4 * 1024) : nameSize;
|
||||
|
||||
using (var fileNameBytes = reader.ReadScope(nameSize))
|
||||
byte[] fileNameBytes = reader.ReadBytes(nameSize);
|
||||
|
||||
switch (HeaderType)
|
||||
{
|
||||
switch (HeaderType)
|
||||
case HeaderType.FileHeader:
|
||||
{
|
||||
case HeaderType.FileHeader:
|
||||
if (FileFlags.HasFlag(FileFlags.UNICODE))
|
||||
{
|
||||
if (FileFlags.HasFlag(FileFlags.UNICODE))
|
||||
int length = 0;
|
||||
while (length < fileNameBytes.Length
|
||||
&& fileNameBytes[length] != 0)
|
||||
{
|
||||
int length = 0;
|
||||
while (length < fileNameBytes.Count
|
||||
&& fileNameBytes[length] != 0)
|
||||
{
|
||||
length++;
|
||||
}
|
||||
if (length != nameSize)
|
||||
{
|
||||
length++;
|
||||
FileName = FileNameDecoder.Decode(fileNameBytes, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = DecodeDefault(fileNameBytes);
|
||||
}
|
||||
length++;
|
||||
}
|
||||
if (length != nameSize)
|
||||
{
|
||||
length++;
|
||||
FileName = FileNameDecoder.Decode(fileNameBytes, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = DecodeDefault(fileNameBytes);
|
||||
}
|
||||
FileName = ConvertPath(FileName, HostOS);
|
||||
}
|
||||
break;
|
||||
case HeaderType.NewSubHeader:
|
||||
else
|
||||
{
|
||||
int datasize = HeaderSize - NEWLHD_SIZE - nameSize;
|
||||
if (FileFlags.HasFlag(FileFlags.SALT))
|
||||
{
|
||||
datasize -= SALT_SIZE;
|
||||
}
|
||||
if (datasize > 0)
|
||||
{
|
||||
SubData = reader.ReadBytes(datasize);
|
||||
}
|
||||
|
||||
if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
|
||||
{
|
||||
RecoverySectors = SubData[8] + (SubData[9] << 8)
|
||||
+ (SubData[10] << 16) + (SubData[11] << 24);
|
||||
}
|
||||
FileName = DecodeDefault(fileNameBytes);
|
||||
}
|
||||
break;
|
||||
FileName = ConvertPath(FileName, HostOS);
|
||||
}
|
||||
|
||||
if (FileFlags.HasFlag(FileFlags.SALT))
|
||||
break;
|
||||
case HeaderType.NewSubHeader:
|
||||
{
|
||||
Salt = reader.ReadBytes(SALT_SIZE);
|
||||
}
|
||||
if (FileFlags.HasFlag(FileFlags.EXTTIME))
|
||||
{
|
||||
// verify that the end of the header hasn't been reached before reading the Extended Time.
|
||||
// some tools incorrectly omit Extended Time despite specifying FileFlags.EXTTIME, which most parsers tolerate.
|
||||
if (ReadBytes + reader.CurrentReadByteCount <= HeaderSize - 2)
|
||||
int datasize = HeaderSize - NEWLHD_SIZE - nameSize;
|
||||
if (FileFlags.HasFlag(FileFlags.SALT))
|
||||
{
|
||||
ushort extendedFlags = reader.ReadUInt16();
|
||||
FileLastModifiedTime = ProcessExtendedTime(extendedFlags, FileLastModifiedTime, reader, 0);
|
||||
FileCreatedTime = ProcessExtendedTime(extendedFlags, null, reader, 1);
|
||||
FileLastAccessedTime = ProcessExtendedTime(extendedFlags, null, reader, 2);
|
||||
FileArchivedTime = ProcessExtendedTime(extendedFlags, null, reader, 3);
|
||||
datasize -= SALT_SIZE;
|
||||
}
|
||||
if (datasize > 0)
|
||||
{
|
||||
SubData = reader.ReadBytes(datasize);
|
||||
}
|
||||
|
||||
if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
|
||||
{
|
||||
RecoverySectors = SubData[8] + (SubData[9] << 8)
|
||||
+ (SubData[10] << 16) + (SubData[11] << 24);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FileFlags.HasFlag(FileFlags.SALT))
|
||||
{
|
||||
Salt = reader.ReadBytes(SALT_SIZE);
|
||||
}
|
||||
if (FileFlags.HasFlag(FileFlags.EXTTIME))
|
||||
{
|
||||
// verify that the end of the header hasn't been reached before reading the Extended Time.
|
||||
// some tools incorrectly omit Extended Time despite specifying FileFlags.EXTTIME, which most parsers tolerate.
|
||||
if (ReadBytes + reader.CurrentReadByteCount <= HeaderSize - 2)
|
||||
{
|
||||
ushort extendedFlags = reader.ReadUInt16();
|
||||
FileLastModifiedTime = ProcessExtendedTime(extendedFlags, FileLastModifiedTime, reader, 0);
|
||||
FileCreatedTime = ProcessExtendedTime(extendedFlags, null, reader, 1);
|
||||
FileLastAccessedTime = ProcessExtendedTime(extendedFlags, null, reader, 2);
|
||||
FileArchivedTime = ProcessExtendedTime(extendedFlags, null, reader, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//only the full .net framework will do other code pages than unicode/utf8
|
||||
private string DecodeDefault(ByteArrayPoolScope bytes)
|
||||
private string DecodeDefault(byte[] bytes)
|
||||
{
|
||||
return ArchiveEncoding.Default.GetString(bytes.Array, 0, bytes.Count);
|
||||
return ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private long UInt32To64(uint x, uint y)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Text;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
@@ -8,12 +7,12 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
/// </summary>
|
||||
internal static class FileNameDecoder
|
||||
{
|
||||
internal static int GetChar(ByteArrayPoolScope name, int pos)
|
||||
internal static int GetChar(byte[] name, int pos)
|
||||
{
|
||||
return name[pos] & 0xff;
|
||||
}
|
||||
|
||||
internal static string Decode(ByteArrayPoolScope name, int encPos)
|
||||
internal static string Decode(byte[] name, int encPos)
|
||||
{
|
||||
int decPos = 0;
|
||||
int flags = 0;
|
||||
@@ -23,7 +22,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
int high = 0;
|
||||
int highByte = GetChar(name, encPos++);
|
||||
StringBuilder buf = new StringBuilder();
|
||||
while (encPos < name.Count)
|
||||
while (encPos < name.Length)
|
||||
{
|
||||
if (flagBits == 0)
|
||||
{
|
||||
@@ -55,7 +54,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
if ((length & 0x80) != 0)
|
||||
{
|
||||
int correction = GetChar(name, encPos++);
|
||||
for (length = (length & 0x7f) + 2; length > 0 && decPos < name.Count; 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));
|
||||
@@ -63,7 +62,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
else
|
||||
{
|
||||
for (length += 2; length > 0 && decPos < name.Count; length--, decPos++)
|
||||
for (length += 2; length > 0 && decPos < name.Length; length--, decPos++)
|
||||
{
|
||||
buf.Append((char)(GetChar(name, decPos)));
|
||||
}
|
||||
|
||||
@@ -62,8 +62,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
if (headerSizeDiff > 0)
|
||||
{
|
||||
using (reader.ReadScope(headerSizeDiff))
|
||||
{ }
|
||||
reader.ReadBytes(headerSizeDiff);
|
||||
}
|
||||
|
||||
return header;
|
||||
|
||||
@@ -52,39 +52,35 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
if (firstByte == 0x52)
|
||||
{
|
||||
MemoryStream buffer = new MemoryStream();
|
||||
using (var nextThreeBytes = reader.ReadScope(3))
|
||||
byte[] nextThreeBytes = reader.ReadBytes(3);
|
||||
if ((nextThreeBytes[0] == 0x45)
|
||||
&& (nextThreeBytes[1] == 0x7E)
|
||||
&& (nextThreeBytes[2] == 0x5E))
|
||||
{
|
||||
if ((nextThreeBytes[0] == 0x45)
|
||||
&& (nextThreeBytes[1] == 0x7E)
|
||||
&& (nextThreeBytes[2] == 0x5E))
|
||||
{
|
||||
//old format and isvalid
|
||||
buffer.WriteByte(0x52);
|
||||
buffer.Write(nextThreeBytes.Array, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
break;
|
||||
}
|
||||
using (var secondThreeBytes = reader.ReadScope(3))
|
||||
{
|
||||
if ((nextThreeBytes[0] == 0x61)
|
||||
&& (nextThreeBytes[1] == 0x72)
|
||||
&& (nextThreeBytes[2] == 0x21)
|
||||
&& (secondThreeBytes[0] == 0x1A)
|
||||
&& (secondThreeBytes[1] == 0x07)
|
||||
&& (secondThreeBytes[2] == 0x00))
|
||||
{
|
||||
//new format and isvalid
|
||||
buffer.WriteByte(0x52);
|
||||
buffer.Write(nextThreeBytes.Array, 0, 3);
|
||||
buffer.Write(secondThreeBytes.Array, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
break;
|
||||
}
|
||||
buffer.Write(nextThreeBytes.Array, 0, 3);
|
||||
buffer.Write(secondThreeBytes.Array, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
}
|
||||
//old format and isvalid
|
||||
buffer.WriteByte(0x52);
|
||||
buffer.Write(nextThreeBytes, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
break;
|
||||
}
|
||||
byte[] secondThreeBytes = reader.ReadBytes(3);
|
||||
if ((nextThreeBytes[0] == 0x61)
|
||||
&& (nextThreeBytes[1] == 0x72)
|
||||
&& (nextThreeBytes[2] == 0x21)
|
||||
&& (secondThreeBytes[0] == 0x1A)
|
||||
&& (secondThreeBytes[1] == 0x07)
|
||||
&& (secondThreeBytes[2] == 0x00))
|
||||
{
|
||||
//new format and isvalid
|
||||
buffer.WriteByte(0x52);
|
||||
buffer.Write(nextThreeBytes, 0, 3);
|
||||
buffer.Write(secondThreeBytes, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
break;
|
||||
}
|
||||
buffer.Write(nextThreeBytes, 0, 3);
|
||||
buffer.Write(secondThreeBytes, 0, 3);
|
||||
rewindableStream.Rewind(buffer);
|
||||
}
|
||||
if (count > MAX_SFX_SIZE)
|
||||
{
|
||||
|
||||
@@ -31,22 +31,15 @@ namespace SharpCompress.Common.Rar
|
||||
}
|
||||
|
||||
public override byte[] ReadBytes(int count)
|
||||
{
|
||||
byte[] b = new byte[count];
|
||||
Read(b, 0, count);
|
||||
return b;
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int index, int count)
|
||||
{
|
||||
if (UseEncryption)
|
||||
{
|
||||
return ReadAndDecryptBytes(buffer, index, count);
|
||||
return ReadAndDecryptBytes(count);
|
||||
}
|
||||
return base.Read(buffer, index, count);
|
||||
return base.ReadBytes(count);
|
||||
}
|
||||
|
||||
private int ReadAndDecryptBytes(byte[] buffer, int index, int count)
|
||||
private byte[] ReadAndDecryptBytes(int count)
|
||||
{
|
||||
int queueSize = data.Count;
|
||||
int sizeToRead = count - queueSize;
|
||||
@@ -56,41 +49,23 @@ namespace SharpCompress.Common.Rar
|
||||
int alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf);
|
||||
for (int i = 0; i < alignedSize / 16; i++)
|
||||
{
|
||||
using (var cipherText = PrivateReadScope(16))
|
||||
{
|
||||
var readBytes = rijndael.ProcessBlock(cipherText);
|
||||
foreach (var readByte in readBytes)
|
||||
{
|
||||
data.Enqueue(readByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = index; i < count; i++)
|
||||
{
|
||||
buffer[i] = data.Dequeue();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
//long ax = System.currentTimeMillis();
|
||||
byte[] cipherText = base.ReadBytes(16);
|
||||
var readBytes = rijndael.ProcessBlock(cipherText);
|
||||
foreach (var readByte in readBytes)
|
||||
data.Enqueue(readByte);
|
||||
|
||||
|
||||
private ByteArrayPoolScope PrivateReadScope(int count)
|
||||
{
|
||||
var scope = ByteArrayPool.RentScope(count);
|
||||
int numRead = 0;
|
||||
do
|
||||
{
|
||||
int n = base.Read(scope.Array, numRead, count);
|
||||
if (n == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
numRead += n;
|
||||
count -= n;
|
||||
} while (count > 0);
|
||||
scope.OverrideSize(numRead);
|
||||
return scope;
|
||||
|
||||
}
|
||||
|
||||
var decryptedBytes = new byte[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
decryptedBytes[i] = data.Dequeue();
|
||||
}
|
||||
return decryptedBytes;
|
||||
}
|
||||
|
||||
public void ClearQueue()
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Rar
|
||||
{
|
||||
@@ -56,21 +55,17 @@ namespace SharpCompress.Common.Rar
|
||||
for (int i = 0; i < alignedSize / 16; i++)
|
||||
{
|
||||
//long ax = System.currentTimeMillis();
|
||||
using (var cipherText = ByteArrayPool.RentScope(RarRijndael.CRYPTO_BLOCK_SIZE))
|
||||
{
|
||||
actualStream.Read(cipherText.Array, 0, RarRijndael.CRYPTO_BLOCK_SIZE);
|
||||
var readBytes = rijndael.ProcessBlock(cipherText);
|
||||
foreach (var readByte in readBytes)
|
||||
{
|
||||
data.Enqueue(readByte);
|
||||
}
|
||||
}
|
||||
byte[] cipherText = new byte[RarRijndael.CRYPTO_BLOCK_SIZE];
|
||||
actualStream.Read(cipherText, 0, RarRijndael.CRYPTO_BLOCK_SIZE);
|
||||
|
||||
var readBytes = rijndael.ProcessBlock(cipherText);
|
||||
foreach (var readByte in readBytes)
|
||||
data.Enqueue(readByte);
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
buffer[offset + i] = data.Dequeue();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Rar
|
||||
{
|
||||
@@ -97,24 +96,22 @@ namespace SharpCompress.Common.Rar
|
||||
return rijndael;
|
||||
}
|
||||
|
||||
public byte[] ProcessBlock(ByteArrayPoolScope cipherText)
|
||||
public byte[] ProcessBlock(byte[] cipherText)
|
||||
{
|
||||
using (var plainText = ByteArrayPool.RentScope(CRYPTO_BLOCK_SIZE))
|
||||
var plainText = new byte[CRYPTO_BLOCK_SIZE];
|
||||
var decryptedBytes = new List<byte>();
|
||||
rijndael.ProcessBlock(cipherText, 0, plainText, 0);
|
||||
|
||||
for (int j = 0; j < plainText.Length; j++)
|
||||
{
|
||||
var decryptedBytes = new List<byte>();
|
||||
rijndael.ProcessBlock(cipherText, plainText);
|
||||
|
||||
for (int j = 0; j < plainText.Count; j++)
|
||||
{
|
||||
decryptedBytes.Add((byte)(plainText[j] ^ aesInitializationVector[j % 16])); //32:114, 33:101
|
||||
}
|
||||
|
||||
for (int j = 0; j < aesInitializationVector.Length; j++)
|
||||
{
|
||||
aesInitializationVector[j] = cipherText[j];
|
||||
}
|
||||
return decryptedBytes.ToArray();
|
||||
decryptedBytes.Add((byte) (plainText[j] ^ aesInitializationVector[j%16])); //32:114, 33:101
|
||||
}
|
||||
|
||||
for (int j = 0; j < aesInitializationVector.Length; j++)
|
||||
{
|
||||
aesInitializationVector[j] = cipherText[j];
|
||||
}
|
||||
return decryptedBytes.ToArray();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SharpCompress.Converters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Tar.Headers
|
||||
{
|
||||
@@ -88,75 +87,63 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
internal bool Read(BinaryReader reader)
|
||||
{
|
||||
var buffer = ReadBlock(reader);
|
||||
try
|
||||
if (buffer.Length == 0)
|
||||
{
|
||||
if (buffer.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReadEntryType(buffer.Array) == EntryType.LongName)
|
||||
{
|
||||
Name = ReadLongName(reader, buffer.Array);
|
||||
buffer.Dispose();
|
||||
buffer = ReadBlock(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = ArchiveEncoding.Default.GetString(buffer.Array, 0, 100).TrimNulls();
|
||||
}
|
||||
|
||||
EntryType = ReadEntryType(buffer.Array);
|
||||
Size = ReadSize(buffer.Array);
|
||||
|
||||
//Mode = ReadASCIIInt32Base8(buffer, 100, 7);
|
||||
//UserId = ReadASCIIInt32Base8(buffer, 108, 7);
|
||||
//GroupId = ReadASCIIInt32Base8(buffer, 116, 7);
|
||||
long unixTimeStamp = ReadASCIIInt64Base8(buffer.Array, 136, 11);
|
||||
LastModifiedTime = Epoch.AddSeconds(unixTimeStamp).ToLocalTime();
|
||||
|
||||
Magic = ArchiveEncoding.Default.GetString(buffer.Array, 257, 6).TrimNulls();
|
||||
|
||||
if (!string.IsNullOrEmpty(Magic)
|
||||
&& "ustar".Equals(Magic))
|
||||
{
|
||||
string namePrefix = ArchiveEncoding.Default.GetString(buffer.Array, 345, 157);
|
||||
namePrefix = namePrefix.TrimNulls();
|
||||
if (!string.IsNullOrEmpty(namePrefix))
|
||||
{
|
||||
Name = namePrefix + "/" + Name;
|
||||
}
|
||||
}
|
||||
if (EntryType != EntryType.LongName
|
||||
&& Name.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
|
||||
if (ReadEntryType(buffer) == EntryType.LongName)
|
||||
{
|
||||
buffer.Dispose();
|
||||
Name = ReadLongName(reader, buffer);
|
||||
buffer = ReadBlock(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = ArchiveEncoding.Default.GetString(buffer, 0, 100).TrimNulls();
|
||||
}
|
||||
|
||||
EntryType = ReadEntryType(buffer);
|
||||
Size = ReadSize(buffer);
|
||||
|
||||
//Mode = ReadASCIIInt32Base8(buffer, 100, 7);
|
||||
//UserId = ReadASCIIInt32Base8(buffer, 108, 7);
|
||||
//GroupId = ReadASCIIInt32Base8(buffer, 116, 7);
|
||||
long unixTimeStamp = ReadASCIIInt64Base8(buffer, 136, 11);
|
||||
LastModifiedTime = Epoch.AddSeconds(unixTimeStamp).ToLocalTime();
|
||||
|
||||
Magic = ArchiveEncoding.Default.GetString(buffer, 257, 6).TrimNulls();
|
||||
|
||||
if (!string.IsNullOrEmpty(Magic)
|
||||
&& "ustar".Equals(Magic))
|
||||
{
|
||||
string namePrefix = ArchiveEncoding.Default.GetString(buffer, 345, 157);
|
||||
namePrefix = namePrefix.TrimNulls();
|
||||
if (!string.IsNullOrEmpty(namePrefix))
|
||||
{
|
||||
Name = namePrefix + "/" + Name;
|
||||
}
|
||||
}
|
||||
if (EntryType != EntryType.LongName
|
||||
&& Name.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private string ReadLongName(BinaryReader reader, byte[] buffer)
|
||||
{
|
||||
var size = ReadSize(buffer);
|
||||
var nameLength = (int)size;
|
||||
using (var nameBytes = reader.ReadScope(nameLength))
|
||||
{
|
||||
var remainingBytesToRead = BlockSize - (nameLength % BlockSize);
|
||||
var nameBytes = reader.ReadBytes(nameLength);
|
||||
var remainingBytesToRead = BlockSize - (nameLength % BlockSize);
|
||||
|
||||
// Read the rest of the block and discard the data
|
||||
if (remainingBytesToRead < BlockSize)
|
||||
{
|
||||
using (reader.ReadScope(remainingBytesToRead))
|
||||
{
|
||||
}
|
||||
}
|
||||
return ArchiveEncoding.Default.GetString(nameBytes.Array, 0, nameBytes.Count).TrimNulls();
|
||||
// Read the rest of the block and discard the data
|
||||
if (remainingBytesToRead < BlockSize)
|
||||
{
|
||||
reader.ReadBytes(remainingBytesToRead);
|
||||
}
|
||||
return ArchiveEncoding.Default.GetString(nameBytes, 0, nameBytes.Length).TrimNulls();
|
||||
}
|
||||
|
||||
private static EntryType ReadEntryType(byte[] buffer)
|
||||
@@ -173,11 +160,11 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
return ReadASCIIInt64Base8(buffer, 124, 11);
|
||||
}
|
||||
|
||||
private static ByteArrayPoolScope ReadBlock(BinaryReader reader)
|
||||
private static byte[] ReadBlock(BinaryReader reader)
|
||||
{
|
||||
var buffer = reader.ReadScope(BlockSize);
|
||||
byte[] buffer = reader.ReadBytes(BlockSize);
|
||||
|
||||
if (buffer.Count != 0 && buffer.Count < BlockSize)
|
||||
if (buffer.Length != 0 && buffer.Length < BlockSize)
|
||||
{
|
||||
throw new InvalidOperationException("Buffer is invalid size");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
@@ -30,16 +29,12 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
ExternalFileAttributes = reader.ReadUInt32();
|
||||
RelativeOffsetOfEntryHeader = reader.ReadUInt32();
|
||||
|
||||
using (var name = reader.ReadScope(nameLength))
|
||||
{
|
||||
Name = DecodeString(name);
|
||||
}
|
||||
using (var extra = reader.ReadScope(extraLength))
|
||||
using (var comment = reader.ReadScope(commentLength))
|
||||
{
|
||||
Comment = DecodeString(comment);
|
||||
LoadExtra(extra);
|
||||
}
|
||||
byte[] name = reader.ReadBytes(nameLength);
|
||||
Name = DecodeString(name);
|
||||
byte[] extra = reader.ReadBytes(extraLength);
|
||||
byte[] comment = reader.ReadBytes(commentLength);
|
||||
Comment = DecodeString(comment);
|
||||
LoadExtra(extra);
|
||||
|
||||
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
|
||||
if (unicodePathExtra != null)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
@@ -23,12 +22,10 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
UncompressedSize = reader.ReadUInt32();
|
||||
ushort nameLength = reader.ReadUInt16();
|
||||
ushort extraLength = reader.ReadUInt16();
|
||||
using (var name = reader.ReadScope(nameLength))
|
||||
using (var extra = reader.ReadScope(extraLength))
|
||||
{
|
||||
Name = DecodeString(name);
|
||||
LoadExtra(extra);
|
||||
}
|
||||
byte[] name = reader.ReadBytes(nameLength);
|
||||
byte[] extra = reader.ReadBytes(extraLength);
|
||||
Name = DecodeString(name);
|
||||
LoadExtra(extra);
|
||||
|
||||
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
|
||||
if (unicodePathExtra != null)
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SharpCompress.Converters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
@@ -31,14 +30,14 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
}
|
||||
}
|
||||
|
||||
protected string DecodeString(ByteArrayPoolScope str)
|
||||
protected string DecodeString(byte[] str)
|
||||
{
|
||||
if (FlagUtility.HasFlag(Flags, HeaderFlags.UTF8))
|
||||
{
|
||||
return Encoding.UTF8.GetString(str.Array, 0, str.Count);
|
||||
return Encoding.UTF8.GetString(str, 0, str.Length);
|
||||
}
|
||||
|
||||
return ArchiveEncoding.Default.GetString(str.Array, 0, str.Count);
|
||||
return ArchiveEncoding.Default.GetString(str, 0, str.Length);
|
||||
}
|
||||
|
||||
protected byte[] EncodeString(string str)
|
||||
@@ -77,22 +76,20 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
|
||||
internal uint Crc { get; set; }
|
||||
|
||||
protected void LoadExtra(ByteArrayPoolScope extra)
|
||||
protected void LoadExtra(byte[] extra)
|
||||
{
|
||||
for (int i = 0; i < extra.Count - 4;)
|
||||
for (int i = 0; i < extra.Length - 4;)
|
||||
{
|
||||
ExtraDataType type = (ExtraDataType)DataConverter.LittleEndian.GetUInt16(extra.Array, i);
|
||||
ExtraDataType type = (ExtraDataType)DataConverter.LittleEndian.GetUInt16(extra, i);
|
||||
if (!Enum.IsDefined(typeof(ExtraDataType), type))
|
||||
{
|
||||
type = ExtraDataType.NotImplementedExtraData;
|
||||
}
|
||||
|
||||
ushort length = DataConverter.LittleEndian.GetUInt16(extra.Array, i + 2);
|
||||
using (var data = ByteArrayPool.RentScope(length))
|
||||
{
|
||||
Buffer.BlockCopy(extra.Array, i + 4, data.Array, 0, length);
|
||||
Extra.Add(LocalEntryHeaderExtraFactory.Create(type, length, data.Array));
|
||||
}
|
||||
ushort length = DataConverter.LittleEndian.GetUInt16(extra, i + 2);
|
||||
byte[] data = new byte[length];
|
||||
Buffer.BlockCopy(extra, i + 4, data, 0, length);
|
||||
Extra.Add(LocalEntryHeaderExtraFactory.Create(type, length, data));
|
||||
|
||||
i += length + 4;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.BZip2
|
||||
{
|
||||
@@ -92,14 +91,12 @@ namespace SharpCompress.Compressors.BZip2
|
||||
public static bool IsBZip2(Stream stream)
|
||||
{
|
||||
BinaryReader br = new BinaryReader(stream);
|
||||
using (var chars = br.ReadScope(2))
|
||||
byte[] chars = br.ReadBytes(2);
|
||||
if (chars.Length < 2 || chars[0] != 'B' || chars[1] != 'Z')
|
||||
{
|
||||
if (chars.Count < 2 || chars[0] != 'B' || chars[1] != 'Z')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Converters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
@@ -414,74 +413,67 @@ namespace SharpCompress.Compressors.Deflate
|
||||
int fnLength = (FileName == null) ? 0 : filenameBytes.Length + 1;
|
||||
|
||||
int bufferLength = 10 + cbLength + fnLength;
|
||||
var header = ByteArrayPool.RentWritable(bufferLength);
|
||||
try
|
||||
var header = new byte[bufferLength];
|
||||
int i = 0;
|
||||
|
||||
// ID
|
||||
header[i++] = 0x1F;
|
||||
header[i++] = 0x8B;
|
||||
|
||||
// compression method
|
||||
header[i++] = 8;
|
||||
byte flag = 0;
|
||||
if (Comment != null)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// ID
|
||||
header[i++] = 0x1F;
|
||||
header[i++] = 0x8B;
|
||||
|
||||
// compression method
|
||||
header[i++] = 8;
|
||||
byte flag = 0;
|
||||
if (Comment != null)
|
||||
{
|
||||
flag ^= 0x10;
|
||||
}
|
||||
if (FileName != null)
|
||||
{
|
||||
flag ^= 0x8;
|
||||
}
|
||||
|
||||
// flag
|
||||
header[i++] = flag;
|
||||
|
||||
// mtime
|
||||
if (!LastModified.HasValue)
|
||||
{
|
||||
LastModified = DateTime.Now;
|
||||
}
|
||||
TimeSpan delta = LastModified.Value - UnixEpoch;
|
||||
var timet = (Int32)delta.TotalSeconds;
|
||||
DataConverter.LittleEndian.PutBytes(header, i, timet);
|
||||
i += 4;
|
||||
|
||||
// xflg
|
||||
header[i++] = 0; // this field is totally useless
|
||||
|
||||
// OS
|
||||
header[i++] = 0xFF; // 0xFF == unspecified
|
||||
|
||||
// extra field length - only if FEXTRA is set, which it is not.
|
||||
//header[i++]= 0;
|
||||
//header[i++]= 0;
|
||||
|
||||
// filename
|
||||
if (fnLength != 0)
|
||||
{
|
||||
Array.Copy(filenameBytes, 0, header, i, fnLength - 1);
|
||||
i += fnLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
|
||||
// comment
|
||||
if (cbLength != 0)
|
||||
{
|
||||
Array.Copy(commentBytes, 0, header, i, cbLength - 1);
|
||||
i += cbLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
|
||||
BaseStream._stream.Write(header, 0, bufferLength);
|
||||
|
||||
return bufferLength; // bytes written
|
||||
flag ^= 0x10;
|
||||
}
|
||||
finally
|
||||
if (FileName != null)
|
||||
{
|
||||
ByteArrayPool.Return(header);
|
||||
flag ^= 0x8;
|
||||
}
|
||||
|
||||
// flag
|
||||
header[i++] = flag;
|
||||
|
||||
// mtime
|
||||
if (!LastModified.HasValue)
|
||||
{
|
||||
LastModified = DateTime.Now;
|
||||
}
|
||||
TimeSpan delta = LastModified.Value - UnixEpoch;
|
||||
var timet = (Int32)delta.TotalSeconds;
|
||||
DataConverter.LittleEndian.PutBytes(header, i, timet);
|
||||
i += 4;
|
||||
|
||||
// xflg
|
||||
header[i++] = 0; // this field is totally useless
|
||||
|
||||
// OS
|
||||
header[i++] = 0xFF; // 0xFF == unspecified
|
||||
|
||||
// extra field length - only if FEXTRA is set, which it is not.
|
||||
//header[i++]= 0;
|
||||
//header[i++]= 0;
|
||||
|
||||
// filename
|
||||
if (fnLength != 0)
|
||||
{
|
||||
Array.Copy(filenameBytes, 0, header, i, fnLength - 1);
|
||||
i += fnLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
|
||||
// comment
|
||||
if (cbLength != 0)
|
||||
{
|
||||
Array.Copy(commentBytes, 0, header, i, cbLength - 1);
|
||||
i += cbLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
|
||||
BaseStream._stream.Write(header, 0, header.Length);
|
||||
|
||||
return header.Length; // bytes written
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Tar.Headers;
|
||||
using SharpCompress.Converters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
@@ -268,48 +267,46 @@ namespace SharpCompress.Compressors.Deflate
|
||||
}
|
||||
|
||||
// Read and potentially verify the GZIP trailer: CRC32 and size mod 2^32
|
||||
using (var trailer = ByteArrayPool.RentScope(8))
|
||||
byte[] trailer = new byte[8];
|
||||
|
||||
// workitem 8679
|
||||
if (_z.AvailableBytesIn != 8)
|
||||
{
|
||||
|
||||
// workitem 8679
|
||||
if (_z.AvailableBytesIn != 8)
|
||||
// Make sure we have read to the end of the stream
|
||||
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, _z.AvailableBytesIn);
|
||||
int bytesNeeded = 8 - _z.AvailableBytesIn;
|
||||
int bytesRead = _stream.Read(trailer,
|
||||
_z.AvailableBytesIn,
|
||||
bytesNeeded);
|
||||
if (bytesNeeded != bytesRead)
|
||||
{
|
||||
// Make sure we have read to the end of the stream
|
||||
Array.Copy(_z.InputBuffer, _z.NextIn, trailer.Array, 0, _z.AvailableBytesIn);
|
||||
int bytesNeeded = 8 - _z.AvailableBytesIn;
|
||||
int bytesRead = _stream.Read(trailer.Array,
|
||||
_z.AvailableBytesIn,
|
||||
bytesNeeded);
|
||||
if (bytesNeeded != bytesRead)
|
||||
{
|
||||
throw new ZlibException(String.Format(
|
||||
"Protocol error. AvailableBytesIn={0}, expected 8",
|
||||
_z.AvailableBytesIn + bytesRead));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(_z.InputBuffer, _z.NextIn, trailer.Array, 0, trailer.Count);
|
||||
throw new ZlibException(String.Format(
|
||||
"Protocol error. AvailableBytesIn={0}, expected 8",
|
||||
_z.AvailableBytesIn + bytesRead));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length);
|
||||
}
|
||||
|
||||
Int32 crc32_expected = DataConverter.LittleEndian.GetInt32(trailer.Array, 0);
|
||||
Int32 crc32_actual = crc.Crc32Result;
|
||||
Int32 isize_expected = DataConverter.LittleEndian.GetInt32(trailer.Array, 4);
|
||||
Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF);
|
||||
Int32 crc32_expected = DataConverter.LittleEndian.GetInt32(trailer, 0);
|
||||
Int32 crc32_actual = crc.Crc32Result;
|
||||
Int32 isize_expected = DataConverter.LittleEndian.GetInt32(trailer, 4);
|
||||
Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF);
|
||||
|
||||
if (crc32_actual != crc32_expected)
|
||||
{
|
||||
throw new ZlibException(
|
||||
String.Format("Bad CRC32 in GZIP stream. (actual({0:X8})!=expected({1:X8}))",
|
||||
crc32_actual, crc32_expected));
|
||||
}
|
||||
if (crc32_actual != crc32_expected)
|
||||
{
|
||||
throw new ZlibException(
|
||||
String.Format("Bad CRC32 in GZIP stream. (actual({0:X8})!=expected({1:X8}))",
|
||||
crc32_actual, crc32_expected));
|
||||
}
|
||||
|
||||
if (isize_actual != isize_expected)
|
||||
{
|
||||
throw new ZlibException(
|
||||
String.Format("Bad size in GZIP stream. (actual({0})!=expected({1}))", isize_actual,
|
||||
isize_expected));
|
||||
}
|
||||
if (isize_actual != isize_expected)
|
||||
{
|
||||
throw new ZlibException(
|
||||
String.Format("Bad size in GZIP stream. (actual({0})!=expected({1}))", isize_actual,
|
||||
isize_expected));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -430,61 +427,57 @@ namespace SharpCompress.Compressors.Deflate
|
||||
int totalBytesRead = 0;
|
||||
|
||||
// read the header on the first read
|
||||
using (var header = ByteArrayPool.RentScope(10))
|
||||
byte[] header = new byte[10];
|
||||
int n = _stream.Read(header, 0, header.Length);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
int n = _stream.Read(header);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n != 10)
|
||||
{
|
||||
throw new ZlibException("Not a valid GZIP stream.");
|
||||
}
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
|
||||
Int32 timet = DataConverter.LittleEndian.GetInt32(header.Array, 4);
|
||||
_GzipMtime = TarHeader.Epoch.AddSeconds(timet);
|
||||
totalBytesRead += n;
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = _stream.Read(header.Array, 0, 2); // 2-byte length field
|
||||
totalBytesRead += n;
|
||||
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
using (var extra = ByteArrayPool.RentScope(extraLength))
|
||||
{
|
||||
n = _stream.Read(extra);
|
||||
if (n != extraLength)
|
||||
{
|
||||
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
|
||||
}
|
||||
totalBytesRead += n;
|
||||
}
|
||||
}
|
||||
if ((header[3] & 0x08) == 0x08)
|
||||
{
|
||||
_GzipFileName = ReadZeroTerminatedString();
|
||||
}
|
||||
if ((header[3] & 0x10) == 0x010)
|
||||
{
|
||||
_GzipComment = ReadZeroTerminatedString();
|
||||
}
|
||||
if ((header[3] & 0x02) == 0x02)
|
||||
{
|
||||
Read(_buf1, 0, 1); // CRC16, ignore
|
||||
}
|
||||
|
||||
return totalBytesRead;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n != 10)
|
||||
{
|
||||
throw new ZlibException("Not a valid GZIP stream.");
|
||||
}
|
||||
|
||||
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
|
||||
{
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
|
||||
Int32 timet = DataConverter.LittleEndian.GetInt32(header, 4);
|
||||
_GzipMtime = TarHeader.Epoch.AddSeconds(timet);
|
||||
totalBytesRead += n;
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = _stream.Read(header, 0, 2); // 2-byte length field
|
||||
totalBytesRead += n;
|
||||
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
byte[] extra = new byte[extraLength];
|
||||
n = _stream.Read(extra, 0, extra.Length);
|
||||
if (n != extraLength)
|
||||
{
|
||||
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
|
||||
}
|
||||
totalBytesRead += n;
|
||||
}
|
||||
if ((header[3] & 0x08) == 0x08)
|
||||
{
|
||||
_GzipFileName = ReadZeroTerminatedString();
|
||||
}
|
||||
if ((header[3] & 0x10) == 0x010)
|
||||
{
|
||||
_GzipComment = ReadZeroTerminatedString();
|
||||
}
|
||||
if ((header[3] & 0x02) == 0x02)
|
||||
{
|
||||
Read(_buf1, 0, 1); // CRC16, ignore
|
||||
}
|
||||
|
||||
return totalBytesRead;
|
||||
}
|
||||
|
||||
public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
|
||||
|
||||
153
src/SharpCompress/Compressors/LZMA/LZipStream.cs
Normal file
153
src/SharpCompress/Compressors/LZMA/LZipStream.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.LZMA
|
||||
{
|
||||
// TODO:
|
||||
// - Write as well as read
|
||||
// - Multi-volume support
|
||||
// - Use of the data size / member size values at the end of the stream
|
||||
|
||||
/// <summary>
|
||||
/// Stream supporting the LZIP format, as documented at http://www.nongnu.org/lzip/manual/lzip_manual.html
|
||||
/// </summary>
|
||||
public class LZipStream : Stream
|
||||
{
|
||||
private readonly Stream stream;
|
||||
private bool disposed;
|
||||
private readonly bool leaveOpen;
|
||||
|
||||
public LZipStream(Stream stream, CompressionMode mode)
|
||||
: this(stream, mode, false)
|
||||
{
|
||||
}
|
||||
|
||||
public LZipStream(Stream stream, CompressionMode mode, bool leaveOpen)
|
||||
{
|
||||
if (mode != CompressionMode.Decompress)
|
||||
{
|
||||
throw new NotImplementedException("Only LZip decompression is currently supported");
|
||||
}
|
||||
Mode = mode;
|
||||
this.leaveOpen = leaveOpen;
|
||||
int dictionarySize = ValidateAndReadSize(stream);
|
||||
if (dictionarySize == 0)
|
||||
{
|
||||
throw new IOException("Not an LZip stream");
|
||||
}
|
||||
byte[] properties = GetProperties(dictionarySize);
|
||||
this.stream = new LzmaStream(properties, stream);
|
||||
}
|
||||
|
||||
#region Stream methods
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
disposed = true;
|
||||
if (disposing && !leaveOpen)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public CompressionMode Mode { get; }
|
||||
|
||||
public override bool CanRead => stream.CanRead;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
// TODO: Both Length and Position are sometimes feasible, but would require
|
||||
// reading the output length when we initialize.
|
||||
public override long Length { get { throw new NotImplementedException(); } }
|
||||
|
||||
public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) => stream.Read(buffer, offset, count);
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given stream is positioned at the start of a v1 LZip
|
||||
/// file, as indicated by the ASCII characters "LZIP" and a version byte
|
||||
/// of 1, followed by at least one byte.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to read from. Must not be null.</param>
|
||||
/// <returns><c>true</c> if the given stream is an LZip file, <c>false</c> otherwise.</returns>
|
||||
public static bool IsLZipFile(Stream stream) => ValidateAndReadSize(stream) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Reads the 6-byte header of the stream, and returns 0 if either the header
|
||||
/// couldn't be read or it isn't a validate LZIP header, or the dictionary
|
||||
/// size if it *is* a valid LZIP file.
|
||||
/// </summary>
|
||||
private static int ValidateAndReadSize(Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
// Read the header
|
||||
byte[] header = new byte[6];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
|
||||
// TODO: Handle reading only part of the header?
|
||||
|
||||
if (n != 6)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (header[0] != 'L' || header[1] != 'Z' || header[2] != 'I' || header[3] != 'P' || header[4] != 1 /* version 1 */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int basePower = header[5] & 0x1F;
|
||||
int subtractionNumerator = (header[5] & 0xE0) >> 5;
|
||||
return (1 << basePower) - subtractionNumerator * (1 << (basePower - 4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a byte array to communicate the parameters and dictionary size to LzmaStream.
|
||||
/// </summary>
|
||||
private static byte[] GetProperties(int dictionarySize) =>
|
||||
new byte[]
|
||||
{
|
||||
// Parameters as per http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format
|
||||
// but encoded as a single byte in the format LzmaStream expects.
|
||||
// literal_context_bits = 3
|
||||
// literal_pos_state_bits = 0
|
||||
// pos_state_bits = 2
|
||||
93,
|
||||
// Dictionary size as 4-byte little-endian value
|
||||
(byte)(dictionarySize & 0xff),
|
||||
(byte)((dictionarySize >> 8) & 0xff),
|
||||
(byte)((dictionarySize >> 16) & 0xff),
|
||||
(byte)((dictionarySize >> 24) & 0xff)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto
|
||||
namespace Org.BouncyCastle.Crypto
|
||||
{
|
||||
/// <remarks>Base interface for a symmetric key block cipher.</remarks>
|
||||
public interface IBlockCipher
|
||||
@@ -20,11 +18,13 @@ namespace Org.BouncyCastle.Crypto
|
||||
bool IsPartialBlockOkay { get; }
|
||||
|
||||
/// <summary>Process a block.</summary>
|
||||
/// <param name="input">The input buffer.</param>
|
||||
/// <param name="output">The output buffer.</param>
|
||||
/// <param name="inBuf">The input buffer.</param>
|
||||
/// <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
|
||||
/// <param name="outBuf">The output buffer.</param>
|
||||
/// <param name="outOff">The offset into <paramref>outBuf</paramref> to write the output block.</param>
|
||||
/// <exception cref="DataLengthException">If input block is wrong size, or outBuf too small.</exception>
|
||||
/// <returns>The number of bytes processed and produced.</returns>
|
||||
int ProcessBlock(ByteArrayPoolScope input, ByteArrayPoolScope output);
|
||||
int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff);
|
||||
|
||||
/// <summary>
|
||||
/// Reset the cipher to the same state as it was after the last init (if there was one).
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Engines
|
||||
{
|
||||
@@ -587,24 +586,28 @@ namespace Org.BouncyCastle.Crypto.Engines
|
||||
return BC / 2;
|
||||
}
|
||||
|
||||
public int ProcessBlock(ByteArrayPoolScope input, ByteArrayPoolScope output)
|
||||
public int ProcessBlock(
|
||||
byte[] input,
|
||||
int inOff,
|
||||
byte[] output,
|
||||
int outOff)
|
||||
{
|
||||
if (workingKey == null)
|
||||
{
|
||||
throw new InvalidOperationException("Rijndael engine not initialised");
|
||||
}
|
||||
|
||||
if ((input.Offset + (BC / 2)) > input.Count)
|
||||
if ((inOff + (BC / 2)) > input.Length)
|
||||
{
|
||||
throw new DataLengthException("input buffer too short");
|
||||
}
|
||||
|
||||
if ((output.Offset + (BC / 2)) > output.Count)
|
||||
if ((outOff + (BC / 2)) > output.Length)
|
||||
{
|
||||
throw new DataLengthException("output buffer too short");
|
||||
}
|
||||
|
||||
UnPackBlock(input.Array, input.Offset);
|
||||
UnPackBlock(input, inOff);
|
||||
|
||||
if (forEncryption)
|
||||
{
|
||||
@@ -615,7 +618,7 @@ namespace Org.BouncyCastle.Crypto.Engines
|
||||
DecryptBlock(workingKey);
|
||||
}
|
||||
|
||||
PackBlock(output.Array, output.Offset);
|
||||
PackBlock(output, outOff);
|
||||
|
||||
return BC / 2;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
#if !NO_BUFFERS
|
||||
using System.Buffers;
|
||||
#endif
|
||||
|
||||
namespace SharpCompress.IO
|
||||
{
|
||||
public static class ByteArrayPool
|
||||
{
|
||||
#if !NO_BUFFERS
|
||||
private static readonly ArrayPool<byte> POOL = ArrayPool<byte>.Create();
|
||||
#endif
|
||||
public static ArraySegment<byte> Rent(int size)
|
||||
{
|
||||
#if NO_BUFFERS
|
||||
return new ArraySegment<byte>(new byte[size]);
|
||||
#else
|
||||
return new ArraySegment<byte>(POOL.Rent(size), 0, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static byte[] RentWritable(int size)
|
||||
{
|
||||
#if NO_BUFFERS
|
||||
return new byte[size];
|
||||
#else
|
||||
return POOL.Rent(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static ByteArrayPoolScope RentScope(int size)
|
||||
{
|
||||
return new ByteArrayPoolScope(Rent(size));
|
||||
}
|
||||
|
||||
|
||||
public static void Return(ArraySegment<byte> array)
|
||||
{
|
||||
#if NO_BUFFERS
|
||||
#else
|
||||
POOL.Return(array.Array);
|
||||
#endif
|
||||
}
|
||||
public static void Return(byte[] array)
|
||||
{
|
||||
#if NO_BUFFERS
|
||||
#else
|
||||
POOL.Return(array);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.IO
|
||||
{
|
||||
public struct ByteArrayPoolScope : IDisposable
|
||||
{
|
||||
private readonly ArraySegment<byte> array;
|
||||
private int? overridenSize;
|
||||
public ByteArrayPoolScope(ArraySegment<byte> array)
|
||||
{
|
||||
this.array = array;
|
||||
overridenSize = null;
|
||||
}
|
||||
|
||||
public byte[] Array => array.Array;
|
||||
public int Offset => array.Offset;
|
||||
public int Count => overridenSize ?? array.Count;
|
||||
|
||||
public byte this[int index]
|
||||
{
|
||||
get { return Array[index]; }
|
||||
set { Array[index] = value; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ByteArrayPool.Return(array);
|
||||
}
|
||||
|
||||
public void OverrideSize(int newSize)
|
||||
{
|
||||
overridenSize = newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.IO
|
||||
{
|
||||
public static class ByteArrayPoolScopeExtensions
|
||||
{
|
||||
public static int Read(this Stream stream, ByteArrayPoolScope scope)
|
||||
{
|
||||
return stream.Read(scope.Array, scope.Offset, scope.Count);
|
||||
}
|
||||
|
||||
public static ByteArrayPoolScope ReadScope(this BinaryReader stream, int count)
|
||||
{
|
||||
var scope = ByteArrayPool.RentScope(count);
|
||||
int numRead = 0;
|
||||
do
|
||||
{
|
||||
int n = stream.Read(scope.Array, numRead, count);
|
||||
if (n == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
numRead += n;
|
||||
count -= n;
|
||||
} while (count > 0);
|
||||
scope.OverrideSize(numRead);
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,7 @@ namespace SharpCompress.IO
|
||||
|
||||
public override int Read(byte[] buffer, int index, int count)
|
||||
{
|
||||
int read = base.Read(buffer, index, count);
|
||||
CurrentReadByteCount += read;
|
||||
return read;
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(char[] buffer, int index, int count)
|
||||
@@ -38,18 +36,12 @@ namespace SharpCompress.IO
|
||||
|
||||
public override bool ReadBoolean()
|
||||
{
|
||||
using (var b = this.ReadScope(1))
|
||||
{
|
||||
return b.Array.First() != 0;
|
||||
}
|
||||
return ReadBytes(1).Single() != 0;
|
||||
}
|
||||
|
||||
public override byte ReadByte()
|
||||
{
|
||||
using (var b = this.ReadScope(1))
|
||||
{
|
||||
return b.Array.First();
|
||||
}
|
||||
return ReadBytes(1).Single();
|
||||
}
|
||||
|
||||
public override byte[] ReadBytes(int count)
|
||||
@@ -87,26 +79,17 @@ namespace SharpCompress.IO
|
||||
|
||||
public override short ReadInt16()
|
||||
{
|
||||
using (var b = this.ReadScope(2))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetInt16(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetInt16(ReadBytes(2), 0);
|
||||
}
|
||||
|
||||
public override int ReadInt32()
|
||||
{
|
||||
using (var b = this.ReadScope(4))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetInt32(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetInt32(ReadBytes(4), 0);
|
||||
}
|
||||
|
||||
public override long ReadInt64()
|
||||
{
|
||||
using (var b = this.ReadScope(8))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetInt64(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetInt64(ReadBytes(8), 0);
|
||||
}
|
||||
|
||||
public override sbyte ReadSByte()
|
||||
@@ -126,26 +109,17 @@ namespace SharpCompress.IO
|
||||
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
using (var b = this.ReadScope(2))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetUInt16(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetUInt16(ReadBytes(2), 0);
|
||||
}
|
||||
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
using (var b = this.ReadScope(4))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetUInt32(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetUInt32(ReadBytes(4), 0);
|
||||
}
|
||||
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
using (var b = this.ReadScope(8))
|
||||
{
|
||||
return DataConverter.LittleEndian.GetUInt64(b.Array, 0);
|
||||
}
|
||||
return DataConverter.LittleEndian.GetUInt64(ReadBytes(8), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using SharpCompress.Readers.GZip;
|
||||
using SharpCompress.Readers.Rar;
|
||||
using SharpCompress.Readers.Tar;
|
||||
using SharpCompress.Readers.Zip;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
|
||||
namespace SharpCompress.Readers
|
||||
{
|
||||
@@ -64,6 +65,18 @@ namespace SharpCompress.Readers
|
||||
}
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (LZipStream.IsLZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress, true);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.LZip);
|
||||
}
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (RarArchive.IsRarFile(rewindableStream, options))
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
|
||||
namespace SharpCompress.Readers.Tar
|
||||
{
|
||||
@@ -38,6 +39,10 @@ namespace SharpCompress.Readers.Tar
|
||||
{
|
||||
return new GZipStream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case CompressionType.LZip:
|
||||
{
|
||||
return new LZipStream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case CompressionType.None:
|
||||
{
|
||||
return stream;
|
||||
@@ -87,6 +92,19 @@ namespace SharpCompress.Readers.Tar
|
||||
}
|
||||
throw new InvalidFormatException("Not a tar file.");
|
||||
}
|
||||
|
||||
rewindableStream.Rewind(false);
|
||||
if (LZipStream.IsLZipFile(rewindableStream))
|
||||
{
|
||||
rewindableStream.Rewind(false);
|
||||
LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress, false);
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.LZip);
|
||||
}
|
||||
throw new InvalidFormatException("Not a tar file.");
|
||||
}
|
||||
rewindableStream.Rewind(true);
|
||||
return new TarReader(rewindableStream, options, CompressionType.None);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress
|
||||
{
|
||||
@@ -138,41 +137,37 @@ namespace SharpCompress
|
||||
|
||||
public static void Skip(this Stream source, long advanceAmount)
|
||||
{
|
||||
using (var buffer = ByteArrayPool.RentScope(32 * 1024))
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
int read = 0;
|
||||
int readCount = 0;
|
||||
do
|
||||
{
|
||||
int read = 0;
|
||||
int readCount = 0;
|
||||
do
|
||||
readCount = buffer.Length;
|
||||
if (readCount > advanceAmount)
|
||||
{
|
||||
readCount = buffer.Count;
|
||||
if (readCount > advanceAmount)
|
||||
{
|
||||
readCount = (int)advanceAmount;
|
||||
}
|
||||
read = source.Read(buffer.Array, 0, readCount);
|
||||
if (read <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
advanceAmount -= read;
|
||||
if (advanceAmount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
readCount = (int)advanceAmount;
|
||||
}
|
||||
read = source.Read(buffer, 0, readCount);
|
||||
if (read <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
advanceAmount -= read;
|
||||
if (advanceAmount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
public static void SkipAll(this Stream source)
|
||||
{
|
||||
using (var buffer = ByteArrayPool.RentScope(32 * 1024))
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
}
|
||||
while (source.Read(buffer) > 0);
|
||||
}
|
||||
while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
|
||||
}
|
||||
|
||||
public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
|
||||
@@ -236,17 +231,15 @@ namespace SharpCompress
|
||||
|
||||
public static long TransferTo(this Stream source, Stream destination)
|
||||
{
|
||||
using (var array = ByteArrayPool.RentScope(81920))
|
||||
byte[] array = new byte[81920];
|
||||
int count;
|
||||
long total = 0;
|
||||
while ((count = source.Read(array, 0, array.Length)) != 0)
|
||||
{
|
||||
int count;
|
||||
long total = 0;
|
||||
while ((count = source.Read(array.Array, 0, array.Count)) != 0)
|
||||
{
|
||||
total += count;
|
||||
destination.Write(array.Array, 0, count);
|
||||
}
|
||||
return total;
|
||||
total += count;
|
||||
destination.Write(array, 0, count);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static bool ReadFully(this Stream stream, byte[] buffer)
|
||||
@@ -268,14 +261,14 @@ namespace SharpCompress
|
||||
{
|
||||
return source.Replace('\0', ' ').Trim();
|
||||
}
|
||||
|
||||
public static bool BinaryEquals(this ByteArrayPoolScope source, byte[] target)
|
||||
|
||||
public static bool BinaryEquals(this byte[] source, byte[] target)
|
||||
{
|
||||
if (source.Count != target.Length)
|
||||
if (source.Length != target.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < source.Count; ++i)
|
||||
for (int i = 0; i < source.Length; ++i)
|
||||
{
|
||||
if (source[i] != target[i])
|
||||
{
|
||||
@@ -284,5 +277,10 @@ namespace SharpCompress
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void CopyTo(this byte[] array, byte[] destination, int index)
|
||||
{
|
||||
Array.Copy(array, 0, destination, index, array.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.13.1",
|
||||
"version": "0.14.0",
|
||||
"title": "SharpCompress - Pure C# Decompression/Compression",
|
||||
"authors": [ "Adam Hathcock" ],
|
||||
"language": "en-US",
|
||||
@@ -16,22 +16,15 @@
|
||||
"allowUnsafe": true
|
||||
},
|
||||
"frameworks": {
|
||||
"net35": {
|
||||
},
|
||||
"net40": {
|
||||
"buildOptions": {
|
||||
"define": [ "NO_BUFFERS" ]
|
||||
}
|
||||
},
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.0.0"
|
||||
},
|
||||
"frameworkAssemblies": {
|
||||
"System.Runtime": { "type": "build" }
|
||||
}
|
||||
},
|
||||
".NETPortable,Version=v4.0,Profile=Profile328": {
|
||||
"buildOptions": {
|
||||
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT", "NO_BUFFERS" ]
|
||||
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT" ]
|
||||
},
|
||||
"frameworkAssemblies": {
|
||||
"mscorlib": { "type": "build" },
|
||||
@@ -41,7 +34,7 @@
|
||||
},
|
||||
".NETPortable,Version=v4.5,Profile=Profile259": {
|
||||
"buildOptions": {
|
||||
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT", "NO_BUFFERS" ]
|
||||
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT" ]
|
||||
},
|
||||
"frameworkAssemblies": {
|
||||
"System": { "type": "build" },
|
||||
@@ -58,25 +51,10 @@
|
||||
}
|
||||
},
|
||||
"netstandard1.0": {
|
||||
"buildOptions": {
|
||||
"define": [ "NO_FILE", "NO_CRYPTO", "NO_BUFFERS" ]
|
||||
},
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Text.Encoding.Extensions": "4.0.11"
|
||||
}
|
||||
},
|
||||
"netstandard1.1": {
|
||||
"buildOptions": {
|
||||
"define": [ "NO_FILE", "NO_CRYPTO" ]
|
||||
},
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.0.0",
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
@@ -88,7 +66,6 @@
|
||||
},
|
||||
"netstandard1.3": {
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.0.0",
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
|
||||
@@ -33,6 +33,12 @@ namespace SharpCompress.Test
|
||||
Read("Tar.tar.gz", CompressionType.GZip);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tar_LZip_Reader()
|
||||
{
|
||||
Read("Tar.tar.lz", CompressionType.LZip);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tar_BZip2_Entry_Stream()
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0",
|
||||
"SharpCompress": { "target" : "project"},
|
||||
"xunit": "2.2.0-beta3-build3402",
|
||||
"xunit": "2.2.0-beta2-build3300",
|
||||
"dotnet-test-xunit": "2.2.0-preview2-build1029"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
test/TestArchives/Archives/Tar.tar.lz
Normal file
BIN
test/TestArchives/Archives/Tar.tar.lz
Normal file
Binary file not shown.
Reference in New Issue
Block a user