Compare commits

..

16 Commits

Author SHA1 Message Date
Adam Hathcock
0dfdba3ea1 Change more ReadBytes 2016-10-07 16:02:08 +01:00
Adam Hathcock
3d4b1904ca use pool in MarkingBinaryReader and BinaryReader 2016-10-07 15:41:31 +01:00
Adam Hathcock
cd7e480e51 Dumb mistake on buffer usage 2016-10-07 11:56:31 +01:00
Adam Hathcock
4f092f4c44 update xunit 2016-10-07 11:51:50 +01:00
Adam Hathcock
aa55e1643c Merge branch 'master' into system_buffers 2016-10-07 11:49:29 +01:00
Adam Hathcock
844ba228ee Make 0.13.1 2016-10-03 13:44:19 +01:00
Adam Hathcock
7efc701b32 Merge pull request #188 from adamhathcock/fix_nulls
Fix null password on ReaderFactory.  Fix null options on SevenZipArchive
2016-10-03 13:41:55 +01:00
Adam Hathcock
d7e29f7c4d Fix occasionally failing test 2016-10-03 13:37:04 +01:00
Adam Hathcock
f26ba91386 Fix null password on ReaderFactory. Fix null options on SevenZipArchive 2016-10-03 13:32:53 +01:00
Adam Hathcock
c73ac2039c Merge pull request #185 from adamhathcock/ppmd_allocation_zipwriter
Make PpmdProperties lazy to avoid unnecessary allocations.
2016-10-03 13:04:14 +01:00
Adam Hathcock
671f9cd0cb Empty commit to kick build 2016-10-03 12:58:23 +01:00
Adam Hathcock
131b5b9714 Can't use Lazy on .NET 3.5 :( 2016-10-03 11:20:29 +01:00
Adam Hathcock
771986c50c Start using buffers. Minimal in algorithms for now. 2016-10-03 11:09:09 +01:00
Adam Hathcock
74af0889b9 Make PpmdProperties lazy to avoid unnecessary allocations. 2016-10-03 10:16:26 +01:00
Adam Hathcock
e5ee399045 Merge pull request #181 from claunia/patch-1
Update FORMATS.md
2016-09-30 07:08:52 +01:00
deeb7a0f64 Update FORMATS.md
Add ADC to formats list.
2016-09-29 22:53:51 +01:00
35 changed files with 784 additions and 495 deletions

View File

@@ -28,4 +28,5 @@ For those who want to directly compress/decompress bits
| GZipStream | Both |
| DeflateStream | Both |
| LZMAStream | Both |
| PPMdStream | Both |
| PPMdStream | Both |
| ADCStream | Decompress |

View File

@@ -9,7 +9,7 @@ The major feature is support for non-seekable streams so large files can be proc
## Need Help?
Post Issues on Github!
Check the [Supported Formats](FORMATS.md) and [basic usage.](USAGE.md)
Check the [Supported Formats](FORMATS.md) and [Basic Usage.](USAGE.md)
## A Simple Request
@@ -31,25 +31,36 @@ I'm always looking for help or ideas. Please submit code or email with ideas. Un
## Version Log
### Version 0.13.1
* [Fix null password on ReaderFactory. Fix null options on SevenZipArchive](https://github.com/adamhathcock/sharpcompress/pull/188)
* [Make PpmdProperties lazy to avoid unnecessary allocations.](https://github.com/adamhathcock/sharpcompress/pull/185)
### Version 0.13.0
* Breaking change: Big refactor of Options on API.
* 7Zip supports Deflate
### Version 0.12.4
* Forward only zip issue fix https://github.com/adamhathcock/sharpcompress/issues/160
* Try to fix frameworks again by copying targets from JSON.NET
### Version 0.12.3
* 7Zip fixes https://github.com/adamhathcock/sharpcompress/issues/73
* Maybe all profiles will work with project.json now
### Version 0.12.2
* Support Profile 259 again
### Version 0.12.1
* Support Silverlight 5
### Version 0.12.0
* .NET Core RTM!
* Bug fix for Tar long paths

View File

@@ -4,6 +4,7 @@ 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;
@@ -103,26 +104,28 @@ namespace SharpCompress.Archives.GZip
public static bool IsGZipFile(Stream stream)
{
// read the header on the first read
byte[] header = new byte[10];
int n = stream.Read(header, 0, header.Length);
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
using (var header = ByteArrayPool.RentScope(10))
{
return false;
}
int n = stream.Read(header);
if (n != 10)
{
return false;
}
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
{
return false;
}
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
{
return false;
}
if (n != 10)
{
return false;
}
return true;
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
{
return false;
}
return true;
}
}
/// <summary>

View File

@@ -30,7 +30,7 @@ namespace SharpCompress.Archives.SevenZip
/// </summary>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
public static SevenZipArchive Open(FileInfo fileInfo, ReaderOptions readerOptions)
public static SevenZipArchive Open(FileInfo fileInfo, ReaderOptions readerOptions = null)
{
fileInfo.CheckNotNull("fileInfo");
return new SevenZipArchive(fileInfo, readerOptions ?? new ReaderOptions());
@@ -44,7 +44,7 @@ namespace SharpCompress.Archives.SevenZip
public static SevenZipArchive Open(Stream stream, ReaderOptions readerOptions = null)
{
stream.CheckNotNull("stream");
return new SevenZipArchive(stream, readerOptions);
return new SevenZipArchive(stream, readerOptions ?? new ReaderOptions());
}
#if !NO_FILE
@@ -141,8 +141,10 @@ namespace SharpCompress.Archives.SevenZip
private static bool SignatureMatch(Stream stream)
{
BinaryReader reader = new BinaryReader(stream);
byte[] signatureBytes = reader.ReadBytes(6);
return signatureBytes.BinaryEquals(SIGNATURE);
using (var signatureBytes = reader.ReadScope(6))
{
return signatureBytes.BinaryEquals(SIGNATURE);
}
}
protected override IReader CreateReaderForSolidExtraction()

View File

@@ -5,6 +5,7 @@ using SharpCompress.Common.Tar.Headers;
using SharpCompress.Compressors;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Converters;
using SharpCompress.IO;
namespace SharpCompress.Common.GZip
{
@@ -36,79 +37,85 @@ namespace SharpCompress.Common.GZip
private void ReadAndValidateGzipHeader(Stream stream)
{
// read the header on the first read
byte[] header = new byte[10];
int n = stream.Read(header, 0, header.Length);
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
using (var header = ByteArrayPool.RentScope(10))
{
return;
}
int n = stream.Read(header);
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);
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
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
byte[] extra = new byte[extraLength];
n = stream.Read(extra, 0, extra.Length);
if (n != extraLength)
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
{
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
return;
}
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);
DateModified = TarHeader.Epoch.AddSeconds(timet);
if ((header[3] & 0x04) == 0x04)
{
// 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
}
}
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)
{
byte[] buf1 = new byte[1];
var list = new List<byte>();
bool done = false;
do
using (var buf1 = ByteArrayPool.RentScope(1))
{
// workitem 7740
int n = stream.Read(buf1, 0, 1);
if (n != 1)
var list = new List<byte>();
bool done = false;
do
{
throw new ZlibException("Unexpected EOF reading GZIP header.");
}
if (buf1[0] == 0)
{
done = true;
}
else
{
list.Add(buf1[0]);
// 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]);
}
}
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,81 +47,82 @@ namespace SharpCompress.Common.Rar.Headers
nameSize = nameSize > 4 * 1024 ? (short)(4 * 1024) : nameSize;
byte[] fileNameBytes = reader.ReadBytes(nameSize);
switch (HeaderType)
using (var fileNameBytes = reader.ReadScope(nameSize))
{
case HeaderType.FileHeader:
switch (HeaderType)
{
if (FileFlags.HasFlag(FileFlags.UNICODE))
case HeaderType.FileHeader:
{
int length = 0;
while (length < fileNameBytes.Length
&& fileNameBytes[length] != 0)
if (FileFlags.HasFlag(FileFlags.UNICODE))
{
length++;
}
if (length != nameSize)
{
length++;
FileName = FileNameDecoder.Decode(fileNameBytes, length);
int length = 0;
while (length < fileNameBytes.Count
&& fileNameBytes[length] != 0)
{
length++;
}
if (length != nameSize)
{
length++;
FileName = FileNameDecoder.Decode(fileNameBytes, length);
}
else
{
FileName = DecodeDefault(fileNameBytes);
}
}
else
{
FileName = DecodeDefault(fileNameBytes);
}
FileName = ConvertPath(FileName, HostOS);
}
else
break;
case HeaderType.NewSubHeader:
{
FileName = DecodeDefault(fileNameBytes);
}
FileName = ConvertPath(FileName, HostOS);
}
break;
case HeaderType.NewSubHeader:
{
int datasize = HeaderSize - NEWLHD_SIZE - nameSize;
if (FileFlags.HasFlag(FileFlags.SALT))
{
datasize -= SALT_SIZE;
}
if (datasize > 0)
{
SubData = reader.ReadBytes(datasize);
}
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);
if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes))
{
RecoverySectors = SubData[8] + (SubData[9] << 8)
+ (SubData[10] << 16) + (SubData[11] << 24);
}
}
break;
}
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)
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);
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(byte[] bytes)
private string DecodeDefault(ByteArrayPoolScope bytes)
{
return ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length);
return ArchiveEncoding.Default.GetString(bytes.Array, 0, bytes.Count);
}
private long UInt32To64(uint x, uint y)

View File

@@ -1,4 +1,5 @@
using System.Text;
using SharpCompress.IO;
namespace SharpCompress.Common.Rar.Headers
{
@@ -7,12 +8,12 @@ namespace SharpCompress.Common.Rar.Headers
/// </summary>
internal static class FileNameDecoder
{
internal static int GetChar(byte[] name, int pos)
internal static int GetChar(ByteArrayPoolScope name, int pos)
{
return name[pos] & 0xff;
}
internal static string Decode(byte[] name, int encPos)
internal static string Decode(ByteArrayPoolScope name, int encPos)
{
int decPos = 0;
int flags = 0;
@@ -22,7 +23,7 @@ namespace SharpCompress.Common.Rar.Headers
int high = 0;
int highByte = GetChar(name, encPos++);
StringBuilder buf = new StringBuilder();
while (encPos < name.Length)
while (encPos < name.Count)
{
if (flagBits == 0)
{
@@ -54,7 +55,7 @@ namespace SharpCompress.Common.Rar.Headers
if ((length & 0x80) != 0)
{
int correction = GetChar(name, encPos++);
for (length = (length & 0x7f) + 2; length > 0 && decPos < name.Length; length--, decPos++)
for (length = (length & 0x7f) + 2; length > 0 && decPos < name.Count; length--, decPos++)
{
low = (GetChar(name, decPos) + correction) & 0xff;
buf.Append((char)((highByte << 8) + low));
@@ -62,7 +63,7 @@ namespace SharpCompress.Common.Rar.Headers
}
else
{
for (length += 2; length > 0 && decPos < name.Length; length--, decPos++)
for (length += 2; length > 0 && decPos < name.Count; length--, decPos++)
{
buf.Append((char)(GetChar(name, decPos)));
}

View File

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

View File

@@ -52,35 +52,39 @@ namespace SharpCompress.Common.Rar.Headers
if (firstByte == 0x52)
{
MemoryStream buffer = new MemoryStream();
byte[] nextThreeBytes = reader.ReadBytes(3);
if ((nextThreeBytes[0] == 0x45)
&& (nextThreeBytes[1] == 0x7E)
&& (nextThreeBytes[2] == 0x5E))
using (var nextThreeBytes = reader.ReadScope(3))
{
//old format and isvalid
buffer.WriteByte(0x52);
buffer.Write(nextThreeBytes, 0, 3);
rewindableStream.Rewind(buffer);
break;
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);
}
}
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

@@ -32,14 +32,21 @@ namespace SharpCompress.Common.Rar
public override byte[] ReadBytes(int count)
{
if (UseEncryption)
{
return ReadAndDecryptBytes(count);
}
return base.ReadBytes(count);
byte[] b = new byte[count];
Read(b, 0, count);
return b;
}
private byte[] ReadAndDecryptBytes(int count)
public override int Read(byte[] buffer, int index, int count)
{
if (UseEncryption)
{
return ReadAndDecryptBytes(buffer, index, count);
}
return base.Read(buffer, index, count);
}
private int ReadAndDecryptBytes(byte[] buffer, int index, int count)
{
int queueSize = data.Count;
int sizeToRead = count - queueSize;
@@ -49,23 +56,41 @@ namespace SharpCompress.Common.Rar
int alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf);
for (int i = 0; i < alignedSize / 16; i++)
{
//long ax = System.currentTimeMillis();
byte[] cipherText = base.ReadBytes(16);
var readBytes = rijndael.ProcessBlock(cipherText);
foreach (var readByte in readBytes)
data.Enqueue(readByte);
using (var cipherText = PrivateReadScope(16))
{
var readBytes = rijndael.ProcessBlock(cipherText);
foreach (var readByte in readBytes)
{
data.Enqueue(readByte);
}
}
}
}
var decryptedBytes = new byte[count];
for (int i = 0; i < count; i++)
for (int i = index; i < count; i++)
{
decryptedBytes[i] = data.Dequeue();
buffer[i] = data.Dequeue();
}
return decryptedBytes;
return count;
}
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;
}
public void ClearQueue()

View File

@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.IO;
namespace SharpCompress.Common.Rar
{
@@ -55,17 +56,21 @@ namespace SharpCompress.Common.Rar
for (int i = 0; i < alignedSize / 16; i++)
{
//long ax = System.currentTimeMillis();
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);
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);
}
}
}
for (int i = 0; i < count; i++)
{
buffer[offset + i] = data.Dequeue();
}
}
return count;
}

View File

@@ -6,6 +6,7 @@ using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using SharpCompress.IO;
namespace SharpCompress.Common.Rar
{
@@ -96,22 +97,24 @@ namespace SharpCompress.Common.Rar
return rijndael;
}
public byte[] ProcessBlock(byte[] cipherText)
public byte[] ProcessBlock(ByteArrayPoolScope cipherText)
{
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++)
using (var plainText = ByteArrayPool.RentScope(CRYPTO_BLOCK_SIZE))
{
decryptedBytes.Add((byte) (plainText[j] ^ aesInitializationVector[j%16])); //32:114, 33:101
}
var decryptedBytes = new List<byte>();
rijndael.ProcessBlock(cipherText, plainText);
for (int j = 0; j < aesInitializationVector.Length; j++)
{
aesInitializationVector[j] = cipherText[j];
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();
}
return decryptedBytes.ToArray();
}
public void Dispose()

View File

@@ -2,6 +2,7 @@
using System.IO;
using System.Text;
using SharpCompress.Converters;
using SharpCompress.IO;
namespace SharpCompress.Common.Tar.Headers
{
@@ -87,63 +88,75 @@ namespace SharpCompress.Common.Tar.Headers
internal bool Read(BinaryReader reader)
{
var buffer = ReadBlock(reader);
if (buffer.Length == 0)
try
{
return false;
}
if (ReadEntryType(buffer) == EntryType.LongName)
{
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))
if (buffer.Count == 0)
{
Name = namePrefix + "/" + Name;
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;
}
if (EntryType != EntryType.LongName
&& Name.Length == 0)
finally
{
return false;
buffer.Dispose();
}
return true;
}
private string ReadLongName(BinaryReader reader, byte[] buffer)
{
var size = ReadSize(buffer);
var nameLength = (int)size;
var nameBytes = reader.ReadBytes(nameLength);
var remainingBytesToRead = BlockSize - (nameLength % BlockSize);
// Read the rest of the block and discard the data
if (remainingBytesToRead < BlockSize)
using (var nameBytes = reader.ReadScope(nameLength))
{
reader.ReadBytes(remainingBytesToRead);
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();
}
return ArchiveEncoding.Default.GetString(nameBytes, 0, nameBytes.Length).TrimNulls();
}
private static EntryType ReadEntryType(byte[] buffer)
@@ -160,11 +173,11 @@ namespace SharpCompress.Common.Tar.Headers
return ReadASCIIInt64Base8(buffer, 124, 11);
}
private static byte[] ReadBlock(BinaryReader reader)
private static ByteArrayPoolScope ReadBlock(BinaryReader reader)
{
byte[] buffer = reader.ReadBytes(BlockSize);
var buffer = reader.ReadScope(BlockSize);
if (buffer.Length != 0 && buffer.Length < BlockSize)
if (buffer.Count != 0 && buffer.Count < BlockSize)
{
throw new InvalidOperationException("Buffer is invalid size");
}

View File

@@ -8,10 +8,10 @@ namespace SharpCompress.Common
{
private readonly Stream actualStream;
internal Volume(Stream stream, ReaderOptions readerFactoryOptions)
internal Volume(Stream stream, ReaderOptions readerOptions)
{
actualStream = stream;
ReaderOptions = readerFactoryOptions;
ReaderOptions = readerOptions;
}
internal Stream Stream { get { return new NonDisposingStream(actualStream); } }

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.Linq;
using SharpCompress.IO;
namespace SharpCompress.Common.Zip.Headers
{
@@ -29,12 +30,16 @@ namespace SharpCompress.Common.Zip.Headers
ExternalFileAttributes = reader.ReadUInt32();
RelativeOffsetOfEntryHeader = reader.ReadUInt32();
byte[] name = reader.ReadBytes(nameLength);
Name = DecodeString(name);
byte[] extra = reader.ReadBytes(extraLength);
byte[] comment = reader.ReadBytes(commentLength);
Comment = DecodeString(comment);
LoadExtra(extra);
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);
}
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
if (unicodePathExtra != null)

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.Linq;
using SharpCompress.IO;
namespace SharpCompress.Common.Zip.Headers
{
@@ -22,10 +23,12 @@ namespace SharpCompress.Common.Zip.Headers
UncompressedSize = reader.ReadUInt32();
ushort nameLength = reader.ReadUInt16();
ushort extraLength = reader.ReadUInt16();
byte[] name = reader.ReadBytes(nameLength);
byte[] extra = reader.ReadBytes(extraLength);
Name = DecodeString(name);
LoadExtra(extra);
using (var name = reader.ReadScope(nameLength))
using (var extra = reader.ReadScope(extraLength))
{
Name = DecodeString(name);
LoadExtra(extra);
}
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
if (unicodePathExtra != null)

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using SharpCompress.Converters;
using SharpCompress.IO;
namespace SharpCompress.Common.Zip.Headers
{
@@ -30,14 +31,14 @@ namespace SharpCompress.Common.Zip.Headers
}
}
protected string DecodeString(byte[] str)
protected string DecodeString(ByteArrayPoolScope str)
{
if (FlagUtility.HasFlag(Flags, HeaderFlags.UTF8))
{
return Encoding.UTF8.GetString(str, 0, str.Length);
return Encoding.UTF8.GetString(str.Array, 0, str.Count);
}
return ArchiveEncoding.Default.GetString(str, 0, str.Length);
return ArchiveEncoding.Default.GetString(str.Array, 0, str.Count);
}
protected byte[] EncodeString(string str)
@@ -76,20 +77,22 @@ namespace SharpCompress.Common.Zip.Headers
internal uint Crc { get; set; }
protected void LoadExtra(byte[] extra)
protected void LoadExtra(ByteArrayPoolScope extra)
{
for (int i = 0; i < extra.Length - 4;)
for (int i = 0; i < extra.Count - 4;)
{
ExtraDataType type = (ExtraDataType)DataConverter.LittleEndian.GetUInt16(extra, i);
ExtraDataType type = (ExtraDataType)DataConverter.LittleEndian.GetUInt16(extra.Array, i);
if (!Enum.IsDefined(typeof(ExtraDataType), type))
{
type = ExtraDataType.NotImplementedExtraData;
}
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));
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));
}
i += length + 4;
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using SharpCompress.IO;
namespace SharpCompress.Compressors.BZip2
{
@@ -91,12 +92,14 @@ namespace SharpCompress.Compressors.BZip2
public static bool IsBZip2(Stream stream)
{
BinaryReader br = new BinaryReader(stream);
byte[] chars = br.ReadBytes(2);
if (chars.Length < 2 || chars[0] != 'B' || chars[1] != 'Z')
using (var chars = br.ReadScope(2))
{
return false;
if (chars.Count < 2 || chars[0] != 'B' || chars[1] != 'Z')
{
return false;
}
return true;
}
return true;
}
}
}

View File

@@ -30,6 +30,7 @@ using System;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Converters;
using SharpCompress.IO;
namespace SharpCompress.Compressors.Deflate
{
@@ -413,67 +414,74 @@ namespace SharpCompress.Compressors.Deflate
int fnLength = (FileName == null) ? 0 : filenameBytes.Length + 1;
int bufferLength = 10 + cbLength + fnLength;
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)
var header = ByteArrayPool.RentWritable(bufferLength);
try
{
flag ^= 0x10;
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
}
if (FileName != null)
finally
{
flag ^= 0x8;
ByteArrayPool.Return(header);
}
// 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,6 +30,7 @@ using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.Tar.Headers;
using SharpCompress.Converters;
using SharpCompress.IO;
namespace SharpCompress.Compressors.Deflate
{
@@ -267,46 +268,48 @@ namespace SharpCompress.Compressors.Deflate
}
// Read and potentially verify the GZIP trailer: CRC32 and size mod 2^32
byte[] trailer = new byte[8];
// workitem 8679
if (_z.AvailableBytesIn != 8)
using (var trailer = ByteArrayPool.RentScope(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)
// workitem 8679
if (_z.AvailableBytesIn != 8)
{
throw new ZlibException(String.Format(
"Protocol error. AvailableBytesIn={0}, expected 8",
_z.AvailableBytesIn + 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);
}
}
else
{
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length);
}
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);
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);
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
@@ -427,57 +430,61 @@ namespace SharpCompress.Compressors.Deflate
int totalBytesRead = 0;
// read the header on the first read
byte[] header = new byte[10];
int n = _stream.Read(header, 0, header.Length);
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
using (var header = ByteArrayPool.RentScope(10))
{
return 0;
}
int n = _stream.Read(header);
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)
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
{
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
return 0;
}
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;
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;
}
}
public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count)

View File

@@ -3,13 +3,6 @@ using SharpCompress.Converters;
namespace SharpCompress.Compressors.PPMd
{
public enum PpmdVersion
{
H,
H7z,
I1
}
public class PpmdProperties
{
public PpmdVersion Version = PpmdVersion.I1;

View File

@@ -0,0 +1,9 @@
namespace SharpCompress.Compressors.PPMd
{
public enum PpmdVersion
{
H,
H7z,
I1
}
}

View File

@@ -1,4 +1,6 @@
namespace Org.BouncyCastle.Crypto
using SharpCompress.IO;
namespace Org.BouncyCastle.Crypto
{
/// <remarks>Base interface for a symmetric key block cipher.</remarks>
public interface IBlockCipher
@@ -18,13 +20,11 @@
bool IsPartialBlockOkay { get; }
/// <summary>Process a block.</summary>
/// <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>
/// <param name="input">The input buffer.</param>
/// <param name="output">The output buffer.</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(byte[] inBuf, int inOff, byte[] outBuf, int outOff);
int ProcessBlock(ByteArrayPoolScope input, ByteArrayPoolScope output);
/// <summary>
/// Reset the cipher to the same state as it was after the last init (if there was one).

View File

@@ -1,5 +1,6 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using SharpCompress.IO;
namespace Org.BouncyCastle.Crypto.Engines
{
@@ -586,28 +587,24 @@ namespace Org.BouncyCastle.Crypto.Engines
return BC / 2;
}
public int ProcessBlock(
byte[] input,
int inOff,
byte[] output,
int outOff)
public int ProcessBlock(ByteArrayPoolScope input, ByteArrayPoolScope output)
{
if (workingKey == null)
{
throw new InvalidOperationException("Rijndael engine not initialised");
}
if ((inOff + (BC / 2)) > input.Length)
if ((input.Offset + (BC / 2)) > input.Count)
{
throw new DataLengthException("input buffer too short");
}
if ((outOff + (BC / 2)) > output.Length)
if ((output.Offset + (BC / 2)) > output.Count)
{
throw new DataLengthException("output buffer too short");
}
UnPackBlock(input, inOff);
UnPackBlock(input.Array, input.Offset);
if (forEncryption)
{
@@ -618,7 +615,7 @@ namespace Org.BouncyCastle.Crypto.Engines
DecryptBlock(workingKey);
}
PackBlock(output, outOff);
PackBlock(output.Array, output.Offset);
return BC / 2;
}

View File

@@ -0,0 +1,52 @@
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

@@ -0,0 +1,35 @@
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

@@ -0,0 +1,30 @@
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,7 +26,9 @@ namespace SharpCompress.IO
public override int Read(byte[] buffer, int index, int count)
{
throw new NotSupportedException();
int read = base.Read(buffer, index, count);
CurrentReadByteCount += read;
return read;
}
public override int Read(char[] buffer, int index, int count)
@@ -36,12 +38,18 @@ namespace SharpCompress.IO
public override bool ReadBoolean()
{
return ReadBytes(1).Single() != 0;
using (var b = this.ReadScope(1))
{
return b.Array.First() != 0;
}
}
public override byte ReadByte()
{
return ReadBytes(1).Single();
using (var b = this.ReadScope(1))
{
return b.Array.First();
}
}
public override byte[] ReadBytes(int count)
@@ -79,17 +87,26 @@ namespace SharpCompress.IO
public override short ReadInt16()
{
return DataConverter.LittleEndian.GetInt16(ReadBytes(2), 0);
using (var b = this.ReadScope(2))
{
return DataConverter.LittleEndian.GetInt16(b.Array, 0);
}
}
public override int ReadInt32()
{
return DataConverter.LittleEndian.GetInt32(ReadBytes(4), 0);
using (var b = this.ReadScope(4))
{
return DataConverter.LittleEndian.GetInt32(b.Array, 0);
}
}
public override long ReadInt64()
{
return DataConverter.LittleEndian.GetInt64(ReadBytes(8), 0);
using (var b = this.ReadScope(8))
{
return DataConverter.LittleEndian.GetInt64(b.Array, 0);
}
}
public override sbyte ReadSByte()
@@ -109,17 +126,26 @@ namespace SharpCompress.IO
public override ushort ReadUInt16()
{
return DataConverter.LittleEndian.GetUInt16(ReadBytes(2), 0);
using (var b = this.ReadScope(2))
{
return DataConverter.LittleEndian.GetUInt16(b.Array, 0);
}
}
public override uint ReadUInt32()
{
return DataConverter.LittleEndian.GetUInt32(ReadBytes(4), 0);
using (var b = this.ReadScope(4))
{
return DataConverter.LittleEndian.GetUInt32(b.Array, 0);
}
}
public override ulong ReadUInt64()
{
return DataConverter.LittleEndian.GetUInt64(ReadBytes(8), 0);
using (var b = this.ReadScope(8))
{
return DataConverter.LittleEndian.GetUInt64(b.Array, 0);
}
}
}
}

View File

@@ -29,7 +29,7 @@ namespace SharpCompress.Readers
Options = options;
}
internal ReaderOptions Options { get; private set; }
internal ReaderOptions Options { get; }
public ArchiveType ArchiveType { get; }

View File

@@ -33,7 +33,7 @@ namespace SharpCompress.Readers
};
RewindableStream rewindableStream = new RewindableStream(stream);
rewindableStream.StartRecording();
if (ZipArchive.IsZipFile(rewindableStream, null))
if (ZipArchive.IsZipFile(rewindableStream, options.Password))
{
rewindableStream.Rewind(true);
return ZipReader.Open(rewindableStream, options);

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.IO;
namespace SharpCompress
{
@@ -137,37 +138,41 @@ namespace SharpCompress
public static void Skip(this Stream source, long advanceAmount)
{
byte[] buffer = new byte[32 * 1024];
int read = 0;
int readCount = 0;
do
using (var buffer = ByteArrayPool.RentScope(32 * 1024))
{
readCount = buffer.Length;
if (readCount > advanceAmount)
int read = 0;
int readCount = 0;
do
{
readCount = (int)advanceAmount;
}
read = source.Read(buffer, 0, readCount);
if (read <= 0)
{
break;
}
advanceAmount -= read;
if (advanceAmount == 0)
{
break;
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;
}
}
while (true);
}
while (true);
}
public static void SkipAll(this Stream source)
{
byte[] buffer = new byte[32 * 1024];
do
using (var buffer = ByteArrayPool.RentScope(32 * 1024))
{
do
{
}
while (source.Read(buffer) > 0);
}
while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
}
public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
@@ -231,15 +236,17 @@ namespace SharpCompress
public static long TransferTo(this Stream source, Stream destination)
{
byte[] array = new byte[81920];
int count;
long total = 0;
while ((count = source.Read(array, 0, array.Length)) != 0)
using (var array = ByteArrayPool.RentScope(81920))
{
total += count;
destination.Write(array, 0, count);
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;
}
return total;
}
public static bool ReadFully(this Stream stream, byte[] buffer)
@@ -261,14 +268,14 @@ namespace SharpCompress
{
return source.Replace('\0', ' ').Trim();
}
public static bool BinaryEquals(this byte[] source, byte[] target)
public static bool BinaryEquals(this ByteArrayPoolScope source, byte[] target)
{
if (source.Length != target.Length)
if (source.Count != target.Length)
{
return false;
}
for (int i = 0; i < source.Length; ++i)
for (int i = 0; i < source.Count; ++i)
{
if (source[i] != target[i])
{
@@ -277,10 +284,5 @@ 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

@@ -19,10 +19,10 @@ namespace SharpCompress.Writers.Zip
{
private readonly CompressionType compressionType;
private readonly CompressionLevel compressionLevel;
private readonly PpmdProperties ppmdProperties = new PpmdProperties(); // Caching properties to speed up PPMd
private readonly List<ZipCentralDirectoryEntry> entries = new List<ZipCentralDirectoryEntry>();
private readonly string zipComment;
private long streamPosition;
private PpmdProperties ppmdProps;
public ZipWriter(Stream destination, ZipWriterOptions zipWriterOptions)
: base(ArchiveType.Zip)
@@ -34,6 +34,18 @@ namespace SharpCompress.Writers.Zip
InitalizeStream(destination, !zipWriterOptions.LeaveStreamOpen);
}
private PpmdProperties PpmdProperties
{
get
{
if (ppmdProps == null)
{
ppmdProps = new PpmdProperties();
}
return ppmdProps;
}
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
@@ -252,8 +264,8 @@ namespace SharpCompress.Writers.Zip
}
case ZipCompressionMethod.PPMd:
{
counting.Write(writer.ppmdProperties.Properties, 0, 2);
return new PpmdStream(writer.ppmdProperties, counting, true);
counting.Write(writer.PpmdProperties.Properties, 0, 2);
return new PpmdStream(writer.PpmdProperties, counting, true);
}
default:
{

View File

@@ -1,5 +1,5 @@
{
"version": "0.13.0",
"version": "0.13.1",
"title": "SharpCompress - Pure C# Decompression/Compression",
"authors": [ "Adam Hathcock" ],
"language": "en-US",
@@ -16,15 +16,22 @@
"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" ]
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT", "NO_BUFFERS" ]
},
"frameworkAssemblies": {
"mscorlib": { "type": "build" },
@@ -34,7 +41,7 @@
},
".NETPortable,Version=v4.5,Profile=Profile259": {
"buildOptions": {
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT" ]
"define": [ "NO_FILE", "NO_CRYPTO", "SILVERLIGHT", "NO_BUFFERS" ]
},
"frameworkAssemblies": {
"System": { "type": "build" },
@@ -52,7 +59,7 @@
},
"netstandard1.0": {
"buildOptions": {
"define": [ "NO_FILE", "NO_CRYPTO" ]
"define": [ "NO_FILE", "NO_CRYPTO", "NO_BUFFERS" ]
},
"dependencies": {
"System.Collections": "4.0.11",
@@ -64,8 +71,24 @@
"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",
"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.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

@@ -228,6 +228,8 @@ namespace SharpCompress.Test
[Fact]
public void TestSharpCompressWithEmptyStream()
{
ResetScratch();
MemoryStream stream = new NonSeekableMemoryStream();
using (IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
@@ -250,7 +252,9 @@ namespace SharpCompress.Test
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = entry.Read(buf, 0, bufSize)) > 0)
{
tempStream.Write(buf, 0, bytesRead);
}
}
}
}

View File

@@ -14,7 +14,7 @@
"dependencies": {
"Microsoft.Extensions.PlatformAbstractions": "1.0.0",
"SharpCompress": { "target" : "project"},
"xunit": "2.2.0-beta2-build3300",
"xunit": "2.2.0-beta3-build3402",
"dotnet-test-xunit": "2.2.0-preview2-build1029"
}
}