Compare commits

..

7 Commits

Author SHA1 Message Date
Adam Hathcock
af2408de74 Encryptor is stateful. It's also reused when multiple runs of open entry stream is called. Need to change that. Need Pkware test. 2016-11-21 12:02:35 +00:00
Adam Hathcock
0a64fe28b0 Oops, removed too much from project.json 2016-10-14 09:03:15 +01:00
Adam Hathcock
e320ccfa9a 0.14.0 2016-10-14 08:59:19 +01:00
Adam Hathcock
9628ff9456 Merge pull request #191 from jskeet/lzip
Initial read-only support for LZip
2016-10-14 08:50:32 +01:00
Jon Skeet
d540f78cfc Initial read-only support for LZip
LZip has no notion of flienames, so an LzipReader wouldn't make very much sense;
I've just implemented the stream, and hooked it into tar support.
2016-10-12 15:08:56 +01:00
Adam Hathcock
66420cd299 Merge pull request #189 from ziaa/master
Remove unbalanced parentheses in code samples
2016-10-08 18:25:30 +01:00
Seyed Zia Azimi
dd0594471f Remove unbalanced parentheses in samples 2016-10-07 19:33:41 +03:30
39 changed files with 712 additions and 745 deletions

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ project.lock.json
test/TestArchives/Scratch
.vs
tools
.vscode

View File

@@ -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 |

View File

@@ -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)

View File

@@ -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);
}
```
```

View File

@@ -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>

View File

@@ -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()

View File

@@ -11,6 +11,7 @@
LZMA,
BCJ,
BCJ2,
LZip,
Unknown
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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)));
}

View File

@@ -62,8 +62,7 @@ namespace SharpCompress.Common.Rar.Headers
if (headerSizeDiff > 0)
{
using (reader.ReadScope(headerSizeDiff))
{ }
reader.ReadBytes(headerSizeDiff);
}
return header;

View File

@@ -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)
{

View File

@@ -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()

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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");
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -9,10 +9,11 @@ namespace SharpCompress.Common.Zip
{
private static readonly CRC32 crc32 = new CRC32();
private readonly UInt32[] _Keys = {0x12345678, 0x23456789, 0x34567890};
private readonly string password;
private PkwareTraditionalEncryptionData(string password)
{
Initialize(password);
this.password = password;
}
private byte MagicByte
@@ -28,6 +29,7 @@ namespace SharpCompress.Common.Zip
byte[] encryptionHeader)
{
var encryptor = new PkwareTraditionalEncryptionData(password);
encryptor.InitializeKeys();
byte[] plainTextHeader = encryptor.Decrypt(encryptionHeader, encryptionHeader.Length);
if (plainTextHeader[11] != (byte)((header.Crc >> 24) & 0xff))
{
@@ -84,7 +86,7 @@ namespace SharpCompress.Common.Zip
return cipherText;
}
private void Initialize(string password)
internal void InitializeKeys()
{
byte[] p = StringToByteArray(password);
for (int i = 0; i < password.Length; i++)

View File

@@ -147,6 +147,7 @@ namespace SharpCompress.Common.Zip
}
if (Header.PkwareTraditionalEncryptionData != null)
{
Header.PkwareTraditionalEncryptionData.InitializeKeys();
return new PkwareTraditionalCryptoStream(plainStream, Header.PkwareTraditionalEncryptionData,
CryptoMode.Decrypt);
}

View File

@@ -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;
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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)

View 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)
};
}
}

View File

@@ -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).

View File

@@ -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;
}

View File

@@ -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
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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))
{

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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",

View File

@@ -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()
{

View File

@@ -183,6 +183,32 @@ namespace SharpCompress.Test
Assert.Equal(new FileInfo(scratchPath1).Length, new FileInfo(scratchPath2).Length);
}
[Fact]
public void Zip_Read_Entry_Twice()
{
string scratchPath = "C:\\Users\\adam\\Downloads\\Archive1.zip";
using (var archive = ArchiveFactory.Open(scratchPath, new ReaderOptions()
{
Password = "12345678"
}))
{
var entries = archive.Entries.Where(entry => !entry.IsDirectory);
foreach (var entry in entries)
{
for (int i = 0; i < 2; i++)
{
using (var memoryStream = new MemoryStream())
using (var entryStream = entry.OpenEntryStream())
{
entryStream.CopyTo(memoryStream);
}
}
}
}
}
[Fact]
public void Zip_Removal_Poly()
{

View File

@@ -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"
}
}

Binary file not shown.