mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 21:21:49 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d577fe1ac6 | ||
|
|
9f976aaf78 | ||
|
|
8a7d7e366f | ||
|
|
540ab1c6fa | ||
|
|
6792afbdb1 | ||
|
|
e5a7185671 | ||
|
|
cdaf453b2d | ||
|
|
f9cc80e1de | ||
|
|
7beff9e83c | ||
|
|
8f49f1b6f8 | ||
|
|
7e336a0247 | ||
|
|
e37e8bdadc | ||
|
|
40bd61b16b | ||
|
|
87fbb45099 | ||
|
|
e822f9a95c | ||
|
|
8a5a9159e1 | ||
|
|
73b3c6b419 | ||
|
|
f9bd7ebdb0 | ||
|
|
540618c062 | ||
|
|
9e96dec8c9 | ||
|
|
7b7af612ba | ||
|
|
3a747ba87e | ||
|
|
87e57e3a9a | ||
|
|
785d0dcebf | ||
|
|
2314776f55 | ||
|
|
473f5d8189 | ||
|
|
be971cb6f7 | ||
|
|
149f5e4fb5 | ||
|
|
1793fc949d |
@@ -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:
|
||||
|
||||
28
USAGE.md
28
USAGE.md
@@ -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}");
|
||||
}
|
||||
```
|
||||
@@ -49,7 +49,7 @@ Task("Test")
|
||||
var settings = new DotNetCoreTestSettings
|
||||
{
|
||||
Configuration = "Release",
|
||||
Framework = "netcoreapp2.0"
|
||||
Framework = "netcoreapp2.1"
|
||||
};
|
||||
DotNetCoreTest(file.ToString(), settings);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#if !NO_FILE
|
||||
using System.Linq;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Common;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
87
src/SharpCompress/Common/ExtractionMethods.cs
Normal file
87
src/SharpCompress/Common/ExtractionMethods.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace SharpCompress.Readers
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
public class ExtractionOptions
|
||||
{
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1077,6 +1077,10 @@ namespace SharpCompress.Compressors.BZip2
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -51,5 +51,10 @@ namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
return BaseStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
return BaseStream.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user