Compare commits

..

29 Commits
0.21 ... 0.22

Author SHA1 Message Date
Adam Hathcock
d577fe1ac6 Merge pull request #385 from twirpx/master
Fixed EFS flag handling
2018-07-09 08:48:34 +01:00
Adam Hathcock
9f976aaf78 Merge branch 'master' into master 2018-07-09 08:48:26 +01:00
Adam Hathcock
8a7d7e366f Merge pull request #396 from andreas-eriksson/Rar5IsEncrypted
Correctly set IsEncrypted for entries in Rar5.
2018-07-09 08:48:12 +01:00
Adam Hathcock
540ab1c6fa Merge branch 'master' into master 2018-07-09 08:47:32 +01:00
Adam Hathcock
6792afbdb1 Merge branch 'master' into Rar5IsEncrypted 2018-07-09 08:44:32 +01:00
Adam Hathcock
e5a7185671 Mark for 0.22 2018-07-09 08:42:45 +01:00
Adam Hathcock
cdaf453b2d Update dependencies and tests to .NET Core 2.1 2018-07-09 08:39:37 +01:00
Andreas Eriksson
f9cc80e1de Correctly set IsEncrypted for entries in Rar5. 2018-06-29 15:51:40 +02:00
Adam Hathcock
7beff9e83c Merge pull request #395 from adamhathcock/zip-slip-readers
Zip slip for Readers
2018-06-28 11:56:44 +01:00
Adam Hathcock
8f49f1b6f8 Merge remote-tracking branch 'origin/master' into zip-slip-readers 2018-06-28 11:52:43 +01:00
Adam Hathcock
7e336a0247 Slip in new SDK 2018-06-28 11:51:17 +01:00
Adam Hathcock
e37e8bdadc Move path handling for extraction to be common
Reader and Archive now share more extraction logic
2018-06-28 11:46:51 +01:00
Adam Hathcock
40bd61b16b Merge pull request #389 from frankyjuang/patch-1
Fix comment
2018-06-08 08:59:52 +01:00
Juang, Yi-Lin
87fbb45099 Fix comment 2018-06-08 11:27:43 +08:00
twirpx
e822f9a95c Tests fixed to use explicit use of 866 encoding because of usage file named in Russian in several tests 2018-05-30 22:17:27 +05:00
twirpx
8a5a9159e1 Fixed DirectoryEntryHeader Name/Comment decoding in case of EFS flags set 2018-05-30 21:47:31 +05:00
twirpx
73b3c6b419 Merge branch 'master' of https://github.com/adamhathcock/sharpcompress 2018-05-30 20:28:15 +05:00
Adam Hathcock
f9bd7ebdb0 Merge pull request #384 from MrJul/perf-readbyte
Implemented ReadByte/WriteByte on streams to improve performance
2018-05-28 09:21:28 +01:00
Julien Lebosquain
540618c062 Implemented ReadByte/WriteByte on streams to improve performance 2018-05-27 16:31:44 +02:00
Adam Hathcock
9e96dec8c9 Merge pull request #383 from itn3000/add-filename-encoding-example
add example for custom file encoding
2018-05-23 09:14:46 +01:00
itn3000
7b7af612ba add example for custom file encoding 2018-05-23 09:46:36 +09:00
Adam Hathcock
3a747ba87e Update USAGE with new stream handling 2018-05-16 08:51:33 +01:00
Adam Hathcock
87e57e3a9a Mark for 0.21.1 2018-05-15 09:14:56 +01:00
Adam Hathcock
785d0dcebf Merge pull request #381 from adamhathcock/issue-380
Allow forced encoding to override default encoding
2018-05-15 09:13:16 +01:00
Adam Hathcock
2314776f55 Also check for CustomDecoder 2018-05-15 08:28:11 +01:00
Adam Hathcock
473f5d8189 Make GetDecoder use GetEncoding for forced 2018-05-14 16:20:57 +01:00
Adam Hathcock
be971cb6f7 Allow forced encoding to override default encoding 2018-05-14 16:08:31 +01:00
twirpx
149f5e4fb5 Minor fixes 2017-08-22 11:46:32 +05:00
twirpx
1793fc949d Fixed bug: Passing default ReaderOptions when creating ZipReader for solid extraction 2017-08-16 08:57:36 +05:00
35 changed files with 428 additions and 183 deletions

View File

@@ -2,7 +2,7 @@ version: 2
jobs:
build:
docker:
- image: microsoft/dotnet:2.0.7-sdk-2.1.105
- image: microsoft/dotnet:2.1.301-sdk
steps:
- checkout
- run:

View File

@@ -1,8 +1,8 @@
# SharpCompress Usage
## Stream Rules
## Stream Rules (changed with 0.21)
When dealing with Streams, the rule should be that you don't close a stream you didn't create. This, in effect, should mean you should always put a Stream in a using block to dispose it.
When dealing with Streams, the rule should be that you don't close a stream you didn't create. This, in effect, should mean you should always put a Stream in a using block to dispose it.
However, the .NET Framework often has classes that will dispose streams by default to make things "easy" like the following:
@@ -23,13 +23,12 @@ using (var reader = new StreamReader(fileStream))
}
```
To deal with the "correct" rules as well as the expectations of users, I've decided on this:
* When writing, leave streams open.
* When reading, close streams
To deal with the "correct" rules as well as the expectations of users, I've decided to always close wrapped streams as of 0.21.
To be explicit though, consider always using the overloads that use `ReaderOptions` or `WriterOptions` and explicitly set `LeaveStreamOpen` the way you want.
If using Compression Stream classes directly and you don't want the wrapped stream to be closed. Use the `NonDisposingStream` as a wrapped to prevent the stream being disposed. The change in 0.21 simplified a lot even though the usage is a bit more convoluted.
## Samples
Also, look over the tests for more thorough [examples](https://github.com/adamhathcock/sharpcompress/tree/master/tests/SharpCompress.Test)
@@ -128,3 +127,20 @@ using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOption
writer.WriteAll("D:\\temp", "*", SearchOption.AllDirectories);
}
```
### Extract zip which has non-utf8 encoded filename(cp932)
```C#
var opts = new SharpCompress.Readers.ReaderOptions();
var encoding = Encoding.GetEncoding(932);
opts.ArchiveEncoding = new SharpCompress.Common.ArchiveEncoding();
opts.ArchiveEncoding.CustomDecoder = (data, x, y) =>
{
return encoding.GetString(data);
};
var tr = SharpCompress.Archives.Zip.ZipArchive.Open("test.zip", opts);
foreach(var entry in tr.Entries)
{
Console.WriteLine($"{entry.Key}");
}
```

View File

@@ -49,7 +49,7 @@ Task("Test")
var settings = new DotNetCoreTestSettings
{
Configuration = "Release",
Framework = "netcoreapp2.0"
Framework = "netcoreapp2.1"
};
DotNetCoreTest(file.ToString(), settings);
}

View File

@@ -1,7 +1,6 @@
using System.IO;
using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Readers;
namespace SharpCompress.Archives
{
@@ -46,50 +45,8 @@ namespace SharpCompress.Archives
public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory,
ExtractionOptions options = null)
{
string destinationFileName;
string file = Path.GetFileName(entry.Key);
string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (options.ExtractFullPath)
{
string folder = Path.GetDirectoryName(entry.Key);
string destdir = Path.GetFullPath(
Path.Combine(fullDestinationDirectoryPath, folder)
);
if (!Directory.Exists(destdir))
{
if (!destdir.StartsWith(fullDestinationDirectoryPath))
{
throw new ExtractionException("Entry is trying to create a directory outside of the destination directory.");
}
Directory.CreateDirectory(destdir);
}
destinationFileName = Path.Combine(destdir, file);
}
else
{
destinationFileName = Path.Combine(fullDestinationDirectoryPath, file);
}
if (!entry.IsDirectory)
{
destinationFileName = Path.GetFullPath(destinationFileName);
if (!destinationFileName.StartsWith(fullDestinationDirectoryPath))
{
throw new ExtractionException("Entry is trying to write a file outside of the destination directory.");
}
entry.WriteToFile(destinationFileName, options);
}
ExtractionMethods.WriteEntryToDirectory(entry, destinationDirectory, options,
entry.WriteToFile);
}
/// <summary>
@@ -98,23 +55,15 @@ namespace SharpCompress.Archives
public static void WriteToFile(this IArchiveEntry entry, string destinationFileName,
ExtractionOptions options = null)
{
FileMode fm = FileMode.Create;
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (!options.Overwrite)
{
fm = FileMode.CreateNew;
}
using (FileStream fs = File.Open(destinationFileName, fm))
{
entry.WriteTo(fs);
}
entry.PreserveExtractionOptions(destinationFileName, options);
ExtractionMethods.WriteEntryToFile(entry, destinationFileName, options,
(x, fm) =>
{
using (FileStream fs = File.Open(destinationFileName, fm))
{
entry.WriteTo(fs);
}
});
}
#endif
}

View File

@@ -1,6 +1,6 @@
#if !NO_FILE
using System.Linq;
using SharpCompress.Readers;
using SharpCompress.Common;
#endif

View File

@@ -28,8 +28,13 @@ namespace SharpCompress.Common
public ArchiveEncoding()
{
Default = Encoding.UTF8;
Password = Encoding.UTF8;
#if NETSTANDARD1_0
Default = Encoding.GetEncoding("cp437");
Password = Encoding.GetEncoding("cp437");
#else
Default = Encoding.GetEncoding(437);
Password = Encoding.GetEncoding(437);
#endif
}
#if NETSTANDARD1_3 || NETSTANDARD2_0
@@ -44,21 +49,16 @@ namespace SharpCompress.Common
return Decode(bytes, 0, bytes.Length);
}
public string Decode437(byte[] bytes)
{
#if NETSTANDARD1_0
return Decode(bytes, 0, bytes.Length);
#else
var extendedAsciiEncoding = Encoding.GetEncoding(437);
return extendedAsciiEncoding.GetString(bytes, 0, bytes.Length);
#endif
}
public string Decode(byte[] bytes, int start, int length)
{
return GetDecoder().Invoke(bytes, start, length);
}
public string DecodeUTF8(byte[] bytes)
{
return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
public byte[] Encode(string str)
{
return GetEncoding().GetBytes(str);
@@ -71,7 +71,7 @@ namespace SharpCompress.Common
public Func<byte[], int, int, string> GetDecoder()
{
return CustomDecoder ?? ((bytes, index, count) => (Default ?? Encoding.UTF8).GetString(bytes, index, count));
return CustomDecoder ?? ((bytes, index, count) => GetEncoding().GetString(bytes, index, count));
}
}
}

View File

@@ -56,7 +56,7 @@ namespace SharpCompress.Common
public abstract bool IsEncrypted { get; }
/// <summary>
/// Entry is password protected and encrypted and cannot be extracted.
/// Entry is directory.
/// </summary>
public abstract bool IsDirectory { get; }
@@ -83,4 +83,4 @@ namespace SharpCompress.Common
/// </summary>
public virtual int? Attrib => throw new NotImplementedException();
}
}
}

View File

@@ -66,6 +66,16 @@ namespace SharpCompress.Common
return read;
}
public override int ReadByte()
{
int value = _stream.ReadByte();
if (value == -1)
{
_completed = true;
}
return value;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();

View File

@@ -0,0 +1,87 @@
#if !NO_FILE
using System;
using System.IO;
#endif
namespace SharpCompress.Common
{
internal static class ExtractionMethods
{
#if !NO_FILE
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteEntryToDirectory(IEntry entry, string destinationDirectory,
ExtractionOptions options, Action<string, ExtractionOptions> write)
{
string destinationFileName;
string file = Path.GetFileName(entry.Key);
string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (options.ExtractFullPath)
{
string folder = Path.GetDirectoryName(entry.Key);
string destdir = Path.GetFullPath(
Path.Combine(fullDestinationDirectoryPath, folder)
);
if (!Directory.Exists(destdir))
{
if (!destdir.StartsWith(fullDestinationDirectoryPath))
{
throw new ExtractionException("Entry is trying to create a directory outside of the destination directory.");
}
Directory.CreateDirectory(destdir);
}
destinationFileName = Path.Combine(destdir, file);
}
else
{
destinationFileName = Path.Combine(fullDestinationDirectoryPath, file);
}
if (!entry.IsDirectory)
{
destinationFileName = Path.GetFullPath(destinationFileName);
if (!destinationFileName.StartsWith(fullDestinationDirectoryPath))
{
throw new ExtractionException("Entry is trying to write a file outside of the destination directory.");
}
write(destinationFileName, options);
}
else if (options.ExtractFullPath && !Directory.Exists(destinationFileName))
{
Directory.CreateDirectory(destinationFileName);
}
}
public static void WriteEntryToFile(IEntry entry, string destinationFileName,
ExtractionOptions options,
Action<string, FileMode> openAndWrite)
{
FileMode fm = FileMode.Create;
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (!options.Overwrite)
{
fm = FileMode.CreateNew;
}
openAndWrite(destinationFileName, fm);
entry.PreserveExtractionOptions(destinationFileName, options);
}
#endif
}
}

View File

@@ -1,4 +1,4 @@
namespace SharpCompress.Readers
namespace SharpCompress.Common
{
public class ExtractionOptions
{

View File

@@ -104,24 +104,27 @@ namespace SharpCompress.Common.Rar.Headers
throw new InvalidFormatException("rar5 header size / extra size inconsistency");
}
isEncryptedRar5 = false;
while (RemainingHeaderBytes(reader) > 0) {
var size = reader.ReadRarVIntUInt16();
int n = RemainingHeaderBytes(reader);
var type = reader.ReadRarVIntUInt16();
switch (type) {
//TODO
// case 1: // file encryption
// {
// var version = reader.ReadRarVIntByte();
// if (version != 0) throw new InvalidFormatException("unknown encryption algorithm "+ version);
//
// }
// break;
// case 2: // file hash
// {
//
// }
// break;
//TODO
case 1: // file encryption
{
isEncryptedRar5 = true;
//var version = reader.ReadRarVIntByte();
//if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version);
}
break;
// case 2: // file hash
// {
//
// }
// break;
case 3: // file time
{
ushort flags = reader.ReadRarVIntUInt16();
@@ -435,8 +438,8 @@ namespace SharpCompress.Common.Rar.Headers
public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY);
//!!! TODO rar5
public bool IsEncrypted => HasFlag(FileFlagsV4.PASSWORD);
private bool isEncryptedRar5 = false;
public bool IsEncrypted => IsRar5 ? isEncryptedRar5: HasFlag(FileFlagsV4.PASSWORD);
internal DateTime? FileLastModifiedTime { get; private set; }

View File

@@ -72,6 +72,22 @@ namespace SharpCompress.Common.Tar
return read;
}
public override int ReadByte()
{
if (BytesLeftToRead <= 0)
{
return -1;
}
int value = Stream.ReadByte();
if (value != -1)
{
--BytesLeftToRead;
++_amountRead;
}
return value;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();

View File

@@ -34,15 +34,23 @@ namespace SharpCompress.Common.Zip.Headers
byte[] extra = reader.ReadBytes(extraLength);
byte[] comment = reader.ReadBytes(commentLength);
// According to .ZIP File Format Specification
//
// For example: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
//
// Bit 11: Language encoding flag (EFS). If this bit is set,
// the filename and comment fields for this file
// MUST be encoded using UTF-8. (see APPENDIX D)
if (Flags.HasFlag(HeaderFlags.Efs))
{
Name = ArchiveEncoding.Decode(name);
Comment = ArchiveEncoding.Decode(comment);
Name = ArchiveEncoding.DecodeUTF8(name);
Comment = ArchiveEncoding.DecodeUTF8(comment);
}
else
{
Name = ArchiveEncoding.Decode437(name);
Comment = ArchiveEncoding.Decode437(comment);
Name = ArchiveEncoding.Decode(name);
Comment = ArchiveEncoding.Decode(comment);
}
LoadExtra(extra);

View File

@@ -26,14 +26,21 @@ namespace SharpCompress.Common.Zip.Headers
byte[] name = reader.ReadBytes(nameLength);
byte[] extra = reader.ReadBytes(extraLength);
// According to .ZIP File Format Specification
//
// For example: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
//
// Bit 11: Language encoding flag (EFS). If this bit is set,
// the filename and comment fields for this file
// MUST be encoded using UTF-8. (see APPENDIX D)
if (Flags.HasFlag(HeaderFlags.Efs))
{
Name = ArchiveEncoding.Decode(name);
Name = ArchiveEncoding.DecodeUTF8(name);
}
else
{
// Use IBM Code Page 437 (IBM PC character encoding set)
Name = ArchiveEncoding.Decode437(name);
Name = ArchiveEncoding.Decode(name);
}
LoadExtra(extra);

View File

@@ -67,6 +67,11 @@ namespace SharpCompress.Compressors.BZip2
return stream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return stream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
@@ -82,6 +87,11 @@ namespace SharpCompress.Compressors.BZip2
stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
stream.WriteByte(value);
}
/// <summary>
/// Consumes two bytes to test if there is a BZip2 header
/// </summary>

View File

@@ -1077,6 +1077,10 @@ namespace SharpCompress.Compressors.BZip2
{
}
public override void WriteByte(byte value)
{
}
public override bool CanRead => true;
public override bool CanSeek => false;

View File

@@ -1929,6 +1929,11 @@ namespace SharpCompress.Compressors.BZip2
return 0;
}
public override int ReadByte()
{
return -1;
}
public override long Seek(long offset, SeekOrigin origin)
{
return 0;

View File

@@ -282,6 +282,15 @@ namespace SharpCompress.Compressors.Deflate
return _baseStream.Read(buffer, offset, count);
}
public override int ReadByte()
{
if (_disposed)
{
throw new ObjectDisposedException("DeflateStream");
}
return _baseStream.ReadByte();
}
/// <summary>
/// Calling this method always throws a <see cref="NotImplementedException"/>.
/// </summary>
@@ -340,6 +349,15 @@ namespace SharpCompress.Compressors.Deflate
_baseStream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
if (_disposed)
{
throw new ObjectDisposedException("DeflateStream");
}
_baseStream.WriteByte(value);
}
#endregion
public MemoryStream InputBuffer => new MemoryStream(_baseStream._z.InputBuffer, _baseStream._z.NextIn,

View File

@@ -270,6 +270,15 @@ namespace SharpCompress.Compressors.Deflate
return _baseStream.Read(buffer, offset, count);
}
public override int ReadByte()
{
if (_disposed)
{
throw new ObjectDisposedException("ZlibStream");
}
return _baseStream.ReadByte();
}
/// <summary>
/// Calling this method always throws a <see cref="NotImplementedException"/>.
/// </summary>
@@ -321,6 +330,15 @@ namespace SharpCompress.Compressors.Deflate
_baseStream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
if (_disposed)
{
throw new ObjectDisposedException("ZlibStream");
}
_baseStream.WriteByte(value);
}
#endregion System.IO.Stream methods
}
}

View File

@@ -193,6 +193,22 @@ namespace SharpCompress.Compressors.LZMA
return count;
}
public override int ReadByte()
{
if (_mFinished)
{
return -1;
}
if (!_mIter.MoveNext())
{
_mFinished = true;
return -1;
}
return _mIter.Current;
}
public IEnumerable<byte> Run()
{
const uint kBurstSize = (1u << 18);

View File

@@ -110,6 +110,8 @@ namespace SharpCompress.Compressors.LZMA
public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count);
public override int ReadByte() => _stream.ReadByte();
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotImplementedException();
@@ -120,6 +122,12 @@ namespace SharpCompress.Compressors.LZMA
_writeCount += count;
}
public override void WriteByte(byte value)
{
_stream.WriteByte(value);
++_writeCount;
}
#endregion
/// <summary>

View File

@@ -51,5 +51,10 @@ namespace SharpCompress.Compressors.Xz.Filters
{
return BaseStream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return BaseStream.ReadByte();
}
}
}

View File

@@ -47,6 +47,12 @@ namespace SharpCompress.Crypto
hash = CalculateCrc(table, hash, buffer, offset, count);
}
public override void WriteByte(byte value)
{
stream.WriteByte(value);
hash = CalculateCrc(table, hash, value);
}
public override bool CanRead => stream.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => stream.CanWrite;
@@ -98,9 +104,16 @@ namespace SharpCompress.Crypto
unchecked
{
for (int i = offset, end = offset + count; i < end; i++)
crc = (crc >> 8) ^ table[(crc ^ buffer[i]) & 0xFF];
{
crc = CalculateCrc(table, crc, buffer[i]);
}
}
return crc;
}
private static uint CalculateCrc(uint[] table, uint crc, byte b)
{
return (crc >> 8) ^ table[(crc ^ b) & 0xFF];
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
namespace SharpCompress.IO
@@ -49,5 +49,11 @@ namespace SharpCompress.IO
writableStream.Write(buffer, offset, count);
Count += (uint)count;
}
public override void WriteByte(byte value)
{
writableStream.WriteByte(value);
++Count;
}
}
}

View File

@@ -47,6 +47,19 @@ namespace SharpCompress.IO
return read;
}
public override int ReadByte()
{
int value = Stream.ReadByte();
if (value == -1)
{
return -1;
}
++currentEntryTotalReadBytes;
listener.FireCompressedBytesRead(currentEntryTotalReadBytes, currentEntryTotalReadBytes);
return value;
}
public override long Seek(long offset, SeekOrigin origin)
{
return Stream.Seek(offset, origin);
@@ -61,5 +74,10 @@ namespace SharpCompress.IO
{
Stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
Stream.WriteByte(value);
}
}
}

View File

@@ -44,6 +44,11 @@ namespace SharpCompress.IO
return Stream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return Stream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
return Stream.Seek(offset, origin);
@@ -58,5 +63,10 @@ namespace SharpCompress.IO
{
Stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
Stream.WriteByte(value);
}
}
}

View File

@@ -51,6 +51,20 @@ namespace SharpCompress.IO
return read;
}
public override int ReadByte()
{
if (BytesLeftToRead <= 0)
{
return -1;
}
int value = Stream.ReadByte();
if (value != -1)
{
--BytesLeftToRead;
}
return value;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();

View File

@@ -42,36 +42,8 @@ namespace SharpCompress.Readers
public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory,
ExtractionOptions options = null)
{
string destinationFileName = string.Empty;
string file = Path.GetFileName(reader.Entry.Key);
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (options.ExtractFullPath)
{
string folder = Path.GetDirectoryName(reader.Entry.Key);
string destdir = Path.Combine(destinationDirectory, folder);
if (!Directory.Exists(destdir))
{
Directory.CreateDirectory(destdir);
}
destinationFileName = Path.Combine(destdir, file);
}
else
{
destinationFileName = Path.Combine(destinationDirectory, file);
}
if (!reader.Entry.IsDirectory)
{
reader.WriteEntryToFile(destinationFileName, options);
}
else if (options.ExtractFullPath && !Directory.Exists(destinationFileName))
{
Directory.CreateDirectory(destinationFileName);
}
ExtractionMethods.WriteEntryToDirectory(reader.Entry, destinationDirectory, options,
reader.WriteEntryToFile);
}
/// <summary>
@@ -80,21 +52,14 @@ namespace SharpCompress.Readers
public static void WriteEntryToFile(this IReader reader, string destinationFileName,
ExtractionOptions options = null)
{
FileMode fm = FileMode.Create;
options = options ?? new ExtractionOptions()
{
Overwrite = true
};
if (!options.Overwrite)
{
fm = FileMode.CreateNew;
}
using (FileStream fs = File.Open(destinationFileName, fm))
{
reader.WriteEntryTo(fs);
}
reader.Entry.PreserveExtractionOptions(destinationFileName, options);
ExtractionMethods.WriteEntryToFile(reader.Entry, destinationFileName, options,
(x, fm) =>
{
using (FileStream fs = File.Open(destinationFileName, fm))
{
reader.WriteEntryTo(fs);
}
});
}
#endif
}

View File

@@ -2,9 +2,9 @@
<PropertyGroup>
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.21.0</VersionPrefix>
<AssemblyVersion>0.21.0</AssemblyVersion>
<FileVersion>0.21.0</FileVersion>
<VersionPrefix>0.22.0</VersionPrefix>
<AssemblyVersion>0.22.0</AssemblyVersion>
<FileVersion>0.22.0</FileVersion>
<Authors>Adam Hathcock</Authors>
<TargetFrameworks Condition="'$(LibraryFrameworks)'==''">net45;net35;netstandard1.0;netstandard1.3;netstandard2.0</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -28,12 +28,12 @@
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
</ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
</ItemGroup>
</Project>

View File

@@ -44,6 +44,11 @@ namespace SharpCompress.Test
return stream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return stream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
@@ -55,7 +60,8 @@ namespace SharpCompress.Test
}
public override void Write(byte[] buffer, int offset, int count)
{throw new NotSupportedException();
{
throw new NotSupportedException();
}
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<AssemblyName>SharpCompress.Test</AssemblyName>
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
@@ -12,9 +12,9 @@
<ProjectReference Include="..\..\src\SharpCompress\SharpCompress.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Xunit.SkippableFact" Version="1.3.3" />
<PackageReference Include="Xunit.SkippableFact" Version="1.3.6" />
</ItemGroup>
</Project>

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using SharpCompress.Readers;
using Xunit;
@@ -203,13 +204,16 @@ namespace SharpCompress.Test
Assert.Equal(fi1.Attributes, fi2.Attributes);
}
protected void CompareArchivesByPath(string file1, string file2)
{
protected void CompareArchivesByPath(string file1, string file2) {
ReaderOptions readerOptions = new ReaderOptions();
readerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
//don't compare the order. OS X reads files from the file system in a different order therefore makes the archive ordering different
var archive1Entries = new List<string>();
var archive2Entries = new List<string>();
using (var archive1 = ReaderFactory.Open(File.OpenRead(file1)))
using (var archive2 = ReaderFactory.Open(File.OpenRead(file2)))
using (var archive1 = ReaderFactory.Open(File.OpenRead(file1), readerOptions))
using (var archive2 = ReaderFactory.Open(File.OpenRead(file2), readerOptions))
{
while (archive1.MoveToNextEntry())
{

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Text;
using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -19,12 +20,15 @@ namespace SharpCompress.Test
protected void Write(CompressionType compressionType, string archive, string archiveToVerifyAgainst)
{
ResetScratch();
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive)))
{
using (var writer = WriterFactory.Open(stream, type, new WriterOptions(compressionType)
{
LeaveStreamOpen = true
}))
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive))) {
WriterOptions writerOptions = new WriterOptions(compressionType)
{
LeaveStreamOpen = true,
};
writerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
using (var writer = WriterFactory.Open(stream, type, writerOptions))
{
writer.WriteAll(ORIGINAL_FILES_PATH, "*", SearchOption.AllDirectories);
}
@@ -32,13 +36,19 @@ namespace SharpCompress.Test
CompareArchivesByPath(Path.Combine(SCRATCH2_FILES_PATH, archive),
Path.Combine(TEST_ARCHIVES_PATH, archiveToVerifyAgainst));
using (Stream stream = File.OpenRead(Path.Combine(SCRATCH2_FILES_PATH, archive)))
using (var reader = ReaderFactory.Open(new NonDisposingStream(stream)))
using (Stream stream = File.OpenRead(Path.Combine(SCRATCH2_FILES_PATH, archive)))
{
reader.WriteAllToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions()
ReaderOptions readerOptions = new ReaderOptions();
readerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
using (var reader = ReaderFactory.Open(new NonDisposingStream(stream), readerOptions))
{
ExtractFullPath = true
});
reader.WriteAllToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions()
{
ExtractFullPath = true
});
}
}
VerifyFiles();
}

View File

@@ -205,6 +205,9 @@ namespace SharpCompress.Test.Zip
public override int Read(byte[] buffer, int offset, int count)
{ return stream.Read(buffer, offset, count); }
public override int ReadByte()
{ return stream.ReadByte(); }
public override long Seek(long offset, SeekOrigin origin)
{ throw new NotImplementedException(); }
@@ -213,6 +216,9 @@ namespace SharpCompress.Test.Zip
public override void Write(byte[] buffer, int offset, int count)
{ stream.Write(buffer, offset, count); }
public override void WriteByte(byte value)
{ stream.WriteByte(value); }
}
}
}

View File

@@ -7,6 +7,7 @@ using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;
using Xunit;
namespace SharpCompress.Test.Zip
@@ -162,7 +163,11 @@ namespace SharpCompress.Test.Zip
{
var entry = archive.Entries.Single(x => x.Key.EndsWith("jpg"));
archive.RemoveEntry(entry);
archive.SaveTo(scratchPath, CompressionType.Deflate);
WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate);
writerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
archive.SaveTo(scratchPath, writerOptions);
}
CompareArchivesByPath(modified, scratchPath);
}
@@ -179,7 +184,11 @@ namespace SharpCompress.Test.Zip
using (var archive = ZipArchive.Open(unmodified))
{
archive.AddEntry("jpg\\test.jpg", jpg);
archive.SaveTo(scratchPath, CompressionType.Deflate);
WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate);
writerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
archive.SaveTo(scratchPath, writerOptions);
}
CompareArchivesByPath(modified, scratchPath);
}
@@ -276,7 +285,11 @@ namespace SharpCompress.Test.Zip
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
archive.SaveTo(scratchPath, CompressionType.Deflate);
WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate);
writerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
archive.SaveTo(scratchPath, writerOptions);
}
CompareArchivesByPath(unmodified, scratchPath);
Directory.Delete(SCRATCH_FILES_PATH, true);