Compare commits

..

3 Commits

Author SHA1 Message Date
Adam Hathcock
00263a8225 TarEntry handles longnames 2013-11-23 12:58:35 +00:00
Adam Hathcock
eae4965f32 Trying to write tests for long names 2013-11-23 12:42:46 +00:00
Adam Hathcock
e219a9931a Fixed reading/writing of ustar names 2013-11-23 12:42:21 +00:00
127 changed files with 1041 additions and 1911 deletions

1
.gitignore vendored
View File

@@ -8,4 +8,3 @@ TestArchives/Scratch/
TestArchives/Scratch2/
TestResults/
*.nupkg
packages/*/

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Adam Hathcock
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -2,23 +2,21 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>sharpcompress</id>
<version>0.11.1</version>
<version>0.10.1.3</version>
<title>SharpCompress - Pure C# Decompression/Compression</title>
<authors>Adam Hathcock</authors>
<owners>Adam Hathcock</owners>
<licenseUrl>https://github.com/adamhathcock/sharpcompress/blob/master/LICENSE.txt</licenseUrl>
<licenseUrl>http://sharpcompress.codeplex.com/license</licenseUrl>
<projectUrl>https://github.com/adamhathcock/sharpcompress</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>SharpCompress is a compression library for .NET/Mono/Silverlight/WP7/WindowsStore that can unrar, decompress 7zip, zip/unzip, tar/untar bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</description>
<releaseNotes />
<language>en-US</language>
<tags>rar unrar zip unzip bzip2 gzip tar 7zip</tags>
<dependencies>
</dependencies>
<tags>rar unrar zip unzip bzip2 gzip tar 7zip .net40 .net35 sl4</tags>
</metadata>
<files>
<file src="..\bin\Full\SharpCompress.dll" target="lib\net40\SharpCompress.dll" />
<file src="..\bin\WindowsStore\SharpCompress.dll" target="lib\netcore45\SharpCompress.dll" />
<file src="..\bin\Portable\SharpCompress.dll" target="lib\portable-net4+sl5+wp8+win8\SharpCompress.dll" />
<file src="..\bin\Portable\SharpCompress.dll" target="lib\portable-net4+sl4+wp7+win8\SharpCompress.dll" />
</files>
</package>

View File

@@ -3,7 +3,7 @@ SharpCompress
Github mirror of http://sharpcompress.codeplex.com
SharpCompress is a compression library for .NET/Mono/Silverlight/WP7 that can unrar, un7zip, unzip, untar unbzip2 and ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip are implemented.
SharpCompress is a compression library for .NET/Mono/Silverlight/WP7 that can unrar, un7zip, unzip, untar unbzip2 and ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
@@ -21,25 +21,6 @@ TODOs (always lots):
* Zip64
* Multi-volume Zip support.
Version 0.11:
==============
- Been over a year, contains mainly fixes from contributors!
- Possible breaking change: ArchiveEncoding is UTF8 by default now.
- TAR supports writing long names using longlink
- RAR Protect Header added
Version 0.10.3:
==============
- Finally fixed Disposal issue when creating a new archive with the Archive API
Version 0.10.2:
==============
- Fixed Rar Header reading for invalid extended time headers.
- Windows Store assembly is now strong named
- Known issues with Long Tar names being worked on
- Updated to VS2013
- Portable targets SL5 and Windows Phone 8 (up from SL4 and WP7)
Version 0.10.1:
==============
- Fixed 7Zip extraction performance problem
@@ -62,4 +43,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -120,7 +120,7 @@ namespace SharpCompress.Test
void archive_EntryExtractionBegin(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
{
this.entryTotal = e.Item.Size;
Console.WriteLine("Initializing File Entry Extraction: " + e.Item.Key);
Console.WriteLine("Initializing File Entry Extraction: " + e.Item.FilePath);
}
private long? entryTotal;

View File

@@ -23,7 +23,7 @@ namespace SharpCompress.Test
using (var archive = ArchiveFactory.Open(stream))
{
var entry = archive.Entries.First();
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.FilePath));
}
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
@@ -37,7 +37,7 @@ namespace SharpCompress.Test
using (var archive = GZipArchive.Open(stream))
{
var entry = archive.Entries.First();
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.FilePath));
}
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));

View File

@@ -10,65 +10,6 @@ namespace SharpCompress.Test
[TestClass]
public class RarArchiveTests : ArchiveTests
{
[TestMethod]
public void Rar_EncryptedFileAndHeader_Archive()
{
ReadRarPassword("Rar.encrypted_filesAndHeader.rar", "test");
}
[TestMethod]
public void Rar_EncryptedFileOnly_Archive()
{
ReadRarPassword("Rar.encrypted_filesOnly.rar", "test");
}
[TestMethod]
public void Rar_Encrypted_Archive()
{
ReadRarPassword("Encrypted.rar", "test");
}
private void ReadRarPassword(string testArchive, string password)
{
ResetScratch();
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testArchive)))
using (var archive = RarArchive.Open(stream, Options.KeepStreamsOpen, password))
{
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
Assert.AreEqual(entry.CompressionType, CompressionType.Rar);
entry.WriteToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
}
}
}
VerifyFiles();
}
[TestMethod]
[ExpectedException(typeof(InvalidFormatException))]
public void Rar_Multi_Archive_Encrypted()
{
ArchiveFileReadPassword("EncryptedParts.part01.rar", "test");
}
protected void ArchiveFileReadPassword(string archiveName, string password)
{
ResetScratch();
using (var archive = RarArchive.Open(Path.Combine(TEST_ARCHIVES_PATH, archiveName), Options.None, password))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(SCRATCH_FILES_PATH,
ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
}
}
VerifyFiles();
}
[TestMethod]
public void Rar_None_ArchiveStreamRead()
{
@@ -81,6 +22,7 @@ namespace SharpCompress.Test
ArchiveStreamRead("Rar.rar");
}
[TestMethod]
public void Rar_test_invalid_exttime_ArchiveStreamRead()
{
@@ -123,7 +65,7 @@ namespace SharpCompress.Test
{
using (var archive = RarArchive.Open(stream))
{
Assert.IsFalse(archive.IsSolid);
Assert.IsFalse(archive.IsSolidArchive());
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(SCRATCH_FILES_PATH,
@@ -190,7 +132,7 @@ namespace SharpCompress.Test
{
using (var archive = RarArchive.Open(stream))
{
Assert.IsFalse(archive.IsSolid);
Assert.IsFalse(archive.IsSolidArchive());
Assert.IsTrue(archive.Entries.Any(entry => entry.IsDirectory));
}
}

View File

@@ -33,29 +33,6 @@ namespace SharpCompress.Test
VerifyFiles();
}
//[TestMethod]
public void Rar_Multi_Reader_Encrypted()
{
var testArchives = new string[] { "EncryptedParts.part01.rar",
"EncryptedParts.part02.rar",
"EncryptedParts.part03.rar",
"EncryptedParts.part04.rar",
"EncryptedParts.part05.rar",
"EncryptedParts.part06.rar"};
ResetScratch();
using (var reader = RarReader.Open(testArchives.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
.Select(p => File.OpenRead(p))))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
}
}
VerifyFiles();
}
[TestMethod]
public void Rar_Multi_Reader_Delete_Files()
{
@@ -123,6 +100,7 @@ namespace SharpCompress.Test
public void Rar_Encrypted_Reader()
{
ReadRar("Encrypted.rar", "test");
}
private void ReadRar(string testArchive, string password)
@@ -157,8 +135,8 @@ namespace SharpCompress.Test
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
using (var entryStream = reader.OpenEntryStream())
{
string file = Path.GetFileName(reader.Entry.Key);
string folder = Path.GetDirectoryName(reader.Entry.Key);
string file = Path.GetFileName(reader.Entry.FilePath);
string folder = Path.GetDirectoryName(reader.Entry.FilePath);
string destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
if (!Directory.Exists(destdir))
{
@@ -225,7 +203,7 @@ namespace SharpCompress.Test
{
while (reader.MoveToNextEntry())
{
if (reader.Entry.Key.Contains("jpg"))
if (reader.Entry.FilePath.Contains("jpg"))
{
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
@@ -243,7 +221,7 @@ namespace SharpCompress.Test
{
while (reader.MoveToNextEntry())
{
if (reader.Entry.Key.Contains("jpg"))
if (reader.Entry.FilePath.Contains("jpg"))
{
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.Rar);
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);

View File

@@ -42,7 +42,7 @@
</StartupObject>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\SharpCompress\SharpCompress.pfx</AssemblyOriginatorKeyFile>

View File

@@ -42,7 +42,7 @@
</StartupObject>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\SharpCompress\SharpCompress.pfx</AssemblyOriginatorKeyFile>
@@ -97,9 +97,9 @@
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SharpCompress\SharpCompress.Unsigned.csproj">
<Project>{27d535cb-2fd3-4621-8c9a-46161fc77a5d}</Project>
<Name>SharpCompress.Unsigned</Name>
<ProjectReference Include="..\SharpCompress\SharpCompress.csproj">
<Project>{10A689CF-76A2-4A4F-96E4-553C33398438}</Project>
<Name>SharpCompress</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -30,71 +30,13 @@ namespace SharpCompress.Test
[TestMethod]
public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne()
public void TarArchivePathReadLongName()
{
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar");
using (var archive = TarArchive.Open(unmodified))
{
Assert.AreEqual(5, archive.Entries.Count);
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "very long filename/"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 1.txt"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 2.txt"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "z_file 3.txt"));
}
}
[TestMethod]
public void Tar_VeryLongFilepathReadback()
{
string archive = "Tar_VeryLongFilepathReadback.tar";
ResetScratch();
// create a very long filename
string longFilename = "";
for (int i = 0; i < 600; i = longFilename.Length)
longFilename += i.ToString("D10") + "-";
longFilename += ".txt";
// Step 1: create a tar file containing a file with a long name
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive)))
using (var writer = SharpCompress.Writer.WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.None))
using (Stream inputStream = new MemoryStream())
{
StreamWriter sw = new StreamWriter(inputStream);
sw.Write("dummy filecontent");
sw.Flush();
inputStream.Position = 0;
writer.Write(longFilename, inputStream, null);
}
// Step 2: check if the written tar file can be read correctly
string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
using (var archive2 = TarArchive.Open(unmodified))
{
Assert.AreEqual(1, archive2.Entries.Count);
Assert.IsTrue(archive2.Entries.Any(entry => entry.Key == longFilename));
foreach (var entry in archive2.Entries)
Assert.AreEqual("dummy filecontent", new StreamReader(entry.OpenEntryStream()).ReadLine());
}
}
[TestMethod]
public void Tar_UstarArchivePathReadLongName()
{
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar");
using(var archive = TarArchive.Open(unmodified))
{
Assert.AreEqual(6, archive.Entries.Count);
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Some file with veeeeeeeeeery loooooooooong name"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/"));
Assert.IsTrue(archive.Entries.Any(entry => entry.Key == "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name"));
Assert.AreEqual(2, archive.Entries.Count);
Assert.AreEqual(archive.Entries.Last().FilePath, @"very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg");
}
}
@@ -112,6 +54,22 @@ namespace SharpCompress.Test
}
CompareArchivesByPath(unmodified, scratchPath);
}
[TestMethod]
public void Tar_Create_New_Long_FileName()
{
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.tar");
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar");
base.ResetScratch();
using (var archive = TarArchive.Create())
{
archive.AddAllFromDirectory(ORIGINAL_FILES_PATH);
archive.SaveTo(scratchPath, CompressionType.None);
}
CompareArchivesByPath(unmodified, scratchPath);
}
[TestMethod]
public void Tar_Random_Write_Add()
{
@@ -129,6 +87,23 @@ namespace SharpCompress.Test
CompareArchivesByPath(modified, scratchPath);
}
[TestMethod]
public void Tar_Random_Write_Add_Long_name()
{
string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg\\test.jpg");
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar");
base.ResetScratch();
using (var archive = TarArchive.Create())
{
archive.AddEntry(@"very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg", jpg);
archive.SaveTo(scratchPath, CompressionType.None);
}
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar");
CompareArchivesByPath(unmodified, scratchPath);
}
[TestMethod]
public void Tar_Random_Write_Remove()
{
@@ -139,7 +114,7 @@ namespace SharpCompress.Test
base.ResetScratch();
using (var archive = TarArchive.Open(unmodified))
{
var entry = archive.Entries.Where(x => x.Key.EndsWith("jpg")).Single();
var entry = archive.Entries.Where(x => x.FilePath.EndsWith("jpg")).Single();
archive.RemoveEntry(entry);
archive.SaveTo(scratchPath, CompressionType.None);
}

View File

@@ -46,8 +46,8 @@ namespace SharpCompress.Test
Assert.AreEqual(reader.Entry.CompressionType, CompressionType.BZip2);
using (var entryStream = reader.OpenEntryStream())
{
string file = Path.GetFileName(reader.Entry.Key);
string folder = Path.GetDirectoryName(reader.Entry.Key);
string file = Path.GetFileName(reader.Entry.FilePath);
string folder = Path.GetDirectoryName(reader.Entry.FilePath);
string destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
if (!Directory.Exists(destdir))
{
@@ -81,7 +81,7 @@ namespace SharpCompress.Test
using (var entryStream = reader.OpenEntryStream())
{
entryStream.SkipEntry();
names.Add(reader.Entry.Key);
names.Add(reader.Entry.FilePath);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
@@ -9,15 +8,15 @@ using SharpCompress.Reader;
namespace SharpCompress.Test
{
[TestClass]
public class TestBase
{
protected static string SOLUTION_BASE_PATH=null;
protected static string TEST_ARCHIVES_PATH;
protected static string ORIGINAL_FILES_PATH;
protected static string MISC_TEST_FILES_PATH;
protected static string SCRATCH_FILES_PATH;
protected static string SCRATCH2_FILES_PATH;
protected const string TEST_BASE_PATH = @"C:\Git\sharpcompress";
protected static readonly string TEST_ARCHIVES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Archives");
protected static readonly string ORIGINAL_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Original");
protected static readonly string MISC_TEST_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "MiscTest");
protected static readonly string SCRATCH_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch");
protected static readonly string SCRATCH2_FILES_PATH = Path.Combine(TEST_BASE_PATH, "TestArchives", "Scratch2");
protected static IEnumerable<string> GetRarArchives()
{
yield return Path.Combine(TEST_ARCHIVES_PATH, "Rar.none.rar");
@@ -145,7 +144,7 @@ namespace SharpCompress.Test
while (archive1.MoveToNextEntry())
{
Assert.IsTrue(archive2.MoveToNextEntry());
Assert.AreEqual(archive1.Entry.Key, archive2.Entry.Key);
Assert.AreEqual(archive1.Entry.FilePath, archive2.Entry.FilePath);
}
Assert.IsFalse(archive2.MoveToNextEntry());
}
@@ -153,15 +152,16 @@ namespace SharpCompress.Test
private static readonly object testLock = new object();
[AssemblyInitialize]
public static void InitializePaths(TestContext ctx)
[TestInitialize]
public void TestSetup()
{
SOLUTION_BASE_PATH = Path.GetDirectoryName(Path.GetDirectoryName(ctx.TestDir));
TEST_ARCHIVES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Archives");
ORIGINAL_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Original");
MISC_TEST_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "MiscTest");
SCRATCH_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Scratch");
SCRATCH2_FILES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Scratch2");
Monitor.Enter(testLock);
}
[TestCleanup]
public void TestCleanup()
{
Monitor.Exit(testLock);
}
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SharpCompress.Archive;
using SharpCompress.Archive.Zip;
@@ -140,7 +138,26 @@ namespace SharpCompress.Test
base.ResetScratch();
using (var archive = ZipArchive.Open(unmodified))
{
var entry = archive.Entries.Single(x => x.Key.EndsWith("jpg"));
var entry = archive.Entries.Where(x => x.FilePath.EndsWith("jpg")).Single();
archive.RemoveEntry(entry);
archive.SaveTo(scratchPath, CompressionType.Deflate);
}
CompareArchivesByPath(modified, scratchPath);
}
[TestMethod]
[ExpectedException(typeof(ArchiveException))]
public void Zip_Random_Write_Remove_Fail()
{
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip");
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
string modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip");
base.ResetScratch();
using (var stream = File.OpenRead(unmodified))
using (var archive = ZipArchive.Open(stream))
{
var entry = archive.Entries.Where(x => x.FilePath.EndsWith("jpg")).Single();
archive.RemoveEntry(entry);
archive.SaveTo(scratchPath, CompressionType.Deflate);
}
@@ -164,133 +181,19 @@ namespace SharpCompress.Test
CompareArchivesByPath(modified, scratchPath);
}
[TestMethod]
public void Zip_Save_Twice()
{
string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip");
string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip");
ResetScratch();
using (var arc = ZipArchive.Create())
{
string str = "test.txt";
var source = new MemoryStream(Encoding.UTF8.GetBytes(str));
arc.AddEntry("test.txt", source, true, source.Length);
arc.SaveTo(scratchPath1, CompressionType.Deflate);
arc.SaveTo(scratchPath2, CompressionType.Deflate);
}
Assert.AreEqual(new FileInfo(scratchPath1).Length, new FileInfo(scratchPath2).Length);
}
[TestMethod]
public void Zip_Removal_Poly()
{
ResetScratch();
string scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
using (ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath))
{
var e = vfs.Entries.First(v => v.Key.EndsWith("jpg"));
vfs.RemoveEntry(e);
Assert.IsNull(vfs.Entries.FirstOrDefault(v => v.Key.EndsWith("jpg")));
Assert.IsNull(((IArchive)vfs).Entries.FirstOrDefault(v => v.Key.EndsWith("jpg")));
}
}
[TestMethod]
[ExpectedException(typeof(ArchiveException))]
public void Zip_Create_NoDups()
{
using (var arc = ZipArchive.Create())
{
arc.AddEntry("1.txt", new MemoryStream());
arc.AddEntry("\\1.txt", new MemoryStream());
}
}
[TestMethod]
public void Zip_Create_Same_Stream()
{
string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip");
string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip");
using (var arc = ZipArchive.Create())
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("qwert")))
{
arc.AddEntry("1.txt", stream, false, stream.Length);
arc.AddEntry("2.txt", stream, false, stream.Length);
arc.SaveTo(scratchPath1, CompressionType.Deflate);
arc.SaveTo(scratchPath2, CompressionType.Deflate);
}
}
Assert.AreEqual(new FileInfo(scratchPath1).Length, new FileInfo(scratchPath2).Length);
}
[TestMethod]
public void Zip_Create_New()
{
base.ResetScratch();
foreach (var file in Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories))
{
var newFileName = file.Substring(ORIGINAL_FILES_PATH.Length);
if (newFileName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
newFileName = newFileName.Substring(1);
}
newFileName = Path.Combine(SCRATCH_FILES_PATH, newFileName);
var newDir = Path.GetDirectoryName(newFileName);
if (!Directory.Exists(newDir))
{
Directory.CreateDirectory(newDir);
}
File.Copy(file, newFileName);
}
string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip");
string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.noEmptyDirs.zip");
string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
base.ResetScratch();
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
archive.AddAllFromDirectory(ORIGINAL_FILES_PATH);
archive.SaveTo(scratchPath, CompressionType.Deflate);
}
CompareArchivesByPath(unmodified, scratchPath);
Directory.Delete(SCRATCH_FILES_PATH, true);
}
[TestMethod]
public void Zip_Create_New_Add_Remove()
{
base.ResetScratch();
foreach (var file in Directory.EnumerateFiles(ORIGINAL_FILES_PATH, "*.*", SearchOption.AllDirectories))
{
var newFileName = file.Substring(ORIGINAL_FILES_PATH.Length);
if (newFileName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
newFileName = newFileName.Substring(1);
}
newFileName = Path.Combine(SCRATCH_FILES_PATH, newFileName);
var newDir = Path.GetDirectoryName(newFileName);
if (!Directory.Exists(newDir))
{
Directory.CreateDirectory(newDir);
}
File.Copy(file, newFileName);
}
string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip");
using (var archive = ZipArchive.Create())
{
archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
archive.RemoveEntry(archive.Entries.Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)));
Assert.IsFalse(archive.Entries.Any(x => x.Key.EndsWith("jpg")));
}
Directory.Delete(SCRATCH_FILES_PATH, true);
}
[TestMethod]
@@ -389,7 +292,7 @@ namespace SharpCompress.Test
using (var zipArchive = ZipArchive.Open(stream))
{
foreach (var entry in zipArchive.Entries)
foreach(var entry in zipArchive.Entries)
{
using (var entryStream = entry.OpenEntryStream())
{

View File

@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}"
EndProject
@@ -22,8 +22,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.PortableTest"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Test.Portable", "SharpCompress.Test\SharpCompress.Test.Portable.csproj", "{E9C3C94B-FB27-4B4F-B225-57513C254D37}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCompress.Unsigned", "SharpCompress\SharpCompress.Unsigned.csproj", "{27D535CB-2FD3-4621-8C9A-46161FC77A5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -54,10 +52,6 @@ Global
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9C3C94B-FB27-4B4F-B225-57513C254D37}.Release|Any CPU.Build.0 = Release|Any CPU
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27D535CB-2FD3-4621-8C9A-46161FC77A5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -66,6 +60,5 @@ Global
{15679D7A-F22C-4943-87FF-BF5C76C4A6FD} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
{EFDCAF57-FD4D-4E5D-A3D5-F26B875817ED} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
{E9C3C94B-FB27-4B4F-B225-57513C254D37} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
{27D535CB-2FD3-4621-8C9A-46161FC77A5D} = {932BBFCC-76E3-45FF-90CA-6BE4FBF4A097}
EndGlobalSection
EndGlobal

View File

@@ -7,7 +7,7 @@ using SharpCompress.Reader;
namespace SharpCompress.Archive
{
public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IArchiveExtractionListener
public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IStreamListener
where TEntry : IArchiveEntry
where TVolume : IVolume
{
@@ -20,13 +20,10 @@ namespace SharpCompress.Archive
public event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
public event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
protected string Password { get; private set; }
#if !PORTABLE && !NETFX_CORE
internal AbstractArchive(ArchiveType type, FileInfo fileInfo, Options options, string password)
internal AbstractArchive(ArchiveType type, FileInfo fileInfo, Options options)
{
Type = type;
Password = password;
this.Type = type;
if (!fileInfo.Exists)
{
throw new ArgumentException("File does not exist: " + fileInfo.FullName);
@@ -40,23 +37,22 @@ namespace SharpCompress.Archive
protected abstract IEnumerable<TVolume> LoadVolumes(FileInfo file, Options options);
#endif
internal AbstractArchive(ArchiveType type, IEnumerable<Stream> streams, Options options, string password)
internal AbstractArchive(ArchiveType type, IEnumerable<Stream> streams, Options options)
{
Type = type;
Password = password;
lazyVolumes = new LazyReadOnlyCollection<TVolume>(LoadVolumes(streams.Select(CheckStreams), options));
this.Type = type;
lazyVolumes =
new LazyReadOnlyCollection<TVolume>(LoadVolumes(streams.Select<Stream, Stream>(CheckStreams), options));
lazyEntries = new LazyReadOnlyCollection<TEntry>(LoadEntries(Volumes));
}
internal AbstractArchive(ArchiveType type)
{
Type = type;
this.Type = type;
lazyVolumes = new LazyReadOnlyCollection<TVolume>(Enumerable.Empty<TVolume>());
lazyEntries = new LazyReadOnlyCollection<TEntry>(Enumerable.Empty<TEntry>());
}
public ArchiveType Type { get; private set; }
void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry)
internal void FireEntryExtractionBegin(IArchiveEntry entry)
{
if (EntryExtractionBegin != null)
{
@@ -64,7 +60,7 @@ namespace SharpCompress.Archive
}
}
void IArchiveExtractionListener.FireEntryExtractionEnd(IArchiveEntry entry)
internal void FireEntryExtractionEnd(IArchiveEntry entry)
{
if (EntryExtractionEnd != null)
{
@@ -112,7 +108,7 @@ namespace SharpCompress.Archive
IEnumerable<IArchiveEntry> IArchive.Entries
{
get { return Entries.Cast<IArchiveEntry>(); }
get { return lazyEntries.Cast<IArchiveEntry>(); }
}
IEnumerable<IVolume> IArchive.Volumes
@@ -122,7 +118,7 @@ namespace SharpCompress.Archive
private bool disposed;
public virtual void Dispose()
public void Dispose()
{
if (!disposed)
{
@@ -132,13 +128,16 @@ namespace SharpCompress.Archive
}
}
void IArchiveExtractionListener.EnsureEntriesLoaded()
internal void EnsureEntriesLoaded()
{
lazyEntries.EnsureFullyLoaded();
lazyVolumes.EnsureFullyLoaded();
}
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
public ArchiveType Type { get; private set; }
void IStreamListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
{
if (CompressedBytesRead != null)
{
@@ -150,7 +149,7 @@ namespace SharpCompress.Archive
}
}
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
void IStreamListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
{
if (FilePartExtractionBegin != null)
{
@@ -176,7 +175,7 @@ namespace SharpCompress.Archive
/// <returns></returns>
public IReader ExtractAllEntries()
{
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
EnsureEntriesLoaded();
return CreateReaderForSolidExtraction();
}
@@ -198,7 +197,7 @@ namespace SharpCompress.Archive
{
get
{
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
EnsureEntriesLoaded();
return Entries.All(x => x.IsComplete);
}
}

View File

@@ -1,84 +1,85 @@
using System;
using System.IO;
using SharpCompress.Common;
namespace SharpCompress.Archive
{
public static class IWritableArchiveExtensions
{
public static void SaveTo(this IWritableArchive writableArchive,
Stream stream, CompressionType compressionType)
{
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
}
#if !PORTABLE && !NETFX_CORE
public static void AddEntry(this IWritableArchive writableArchive,
string entryPath, string filePath)
{
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
{
throw new FileNotFoundException("Could not AddEntry: " + filePath);
}
writableArchive.AddEntry(entryPath, new FileInfo(filePath).OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
}
public static void SaveTo(this IWritableArchive writableArchive,
string filePath, CompressionType compressionType)
{
writableArchive.SaveTo(new FileInfo(filePath), new CompressionInfo {Type = compressionType});
}
public static void SaveTo(this IWritableArchive writableArchive,
FileInfo fileInfo, CompressionType compressionType)
{
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
{
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
}
}
public static void SaveTo(this IWritableArchive writableArchive,
string filePath, CompressionInfo compressionInfo)
{
writableArchive.SaveTo(new FileInfo(filePath), compressionInfo);
}
public static void SaveTo(this IWritableArchive writableArchive,
FileInfo fileInfo, CompressionInfo compressionInfo)
{
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
{
writableArchive.SaveTo(stream, compressionInfo);
}
}
public static void AddAllFromDirectory(
this IWritableArchive writableArchive,
string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
{
#if NET2
foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption))
#else
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
#endif
{
var fileInfo = new FileInfo(path);
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
}
}
public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)
{
if (!fileInfo.Exists)
{
throw new ArgumentException("FileInfo does not exist.");
}
return writableArchive.AddEntry(key, fileInfo.OpenRead(), true, fileInfo.Length, fileInfo.LastWriteTime);
}
#endif
}
using System.IO;
using SharpCompress.Common;
namespace SharpCompress.Archive
{
public static class AbstractWritableArchiveExtensions
{
public static void SaveTo<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
Stream stream, CompressionType compressionType)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
}
#if !PORTABLE && !NETFX_CORE
public static void AddEntry<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
string entryPath, string filePath)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
var fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists)
{
throw new FileNotFoundException("Could not AddEntry: " + filePath);
}
writableArchive.AddEntry(entryPath, new FileInfo(filePath).OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
}
public static void SaveTo<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
string filePath, CompressionType compressionType)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
writableArchive.SaveTo(new FileInfo(filePath), new CompressionInfo {Type = compressionType});
}
public static void SaveTo<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
FileInfo fileInfo, CompressionType compressionType)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
{
writableArchive.SaveTo(stream, new CompressionInfo {Type = compressionType});
}
}
public static void SaveTo<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
string filePath, CompressionInfo compressionInfo)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
writableArchive.SaveTo(new FileInfo(filePath), compressionInfo);
}
public static void SaveTo<TEntry, TVolume>(this AbstractWritableArchive<TEntry, TVolume> writableArchive,
FileInfo fileInfo, CompressionInfo compressionInfo)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
using (var stream = fileInfo.Open(FileMode.Create, FileAccess.Write))
{
writableArchive.SaveTo(stream, compressionInfo);
}
}
public static void AddAllFromDirectory<TEntry, TVolume>(
this AbstractWritableArchive<TEntry, TVolume> writableArchive,
string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
where TEntry : IArchiveEntry
where TVolume : IVolume
{
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
{
var fileInfo = new FileInfo(path);
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
fileInfo.LastWriteTime);
}
}
#endif
}
}

View File

@@ -6,7 +6,7 @@ using SharpCompress.Common;
namespace SharpCompress.Archive
{
public abstract class AbstractWritableArchive<TEntry, TVolume> : AbstractArchive<TEntry, TVolume>, IWritableArchive
public abstract class AbstractWritableArchive<TEntry, TVolume> : AbstractArchive<TEntry, TVolume>
where TEntry : IArchiveEntry
where TVolume : IVolume
{
@@ -15,24 +15,37 @@ namespace SharpCompress.Archive
private readonly List<TEntry> modifiedEntries = new List<TEntry>();
private bool hasModifications;
private readonly bool anyNotWritable;
internal AbstractWritableArchive(ArchiveType type)
: base(type)
{
}
internal AbstractWritableArchive(ArchiveType type, Stream stream, Options options)
: base(type, stream.AsEnumerable(), options, null)
internal AbstractWritableArchive(ArchiveType type, IEnumerable<Stream> streams, Options options)
: base(type, streams, options)
{
if (streams.Any(x => !x.CanWrite))
{
anyNotWritable = true;
}
}
#if !PORTABLE && !NETFX_CORE
internal AbstractWritableArchive(ArchiveType type, FileInfo fileInfo, Options options)
: base(type, fileInfo, options, null)
: base(type, fileInfo, options)
{
}
#endif
private void CheckWritable()
{
if (anyNotWritable)
{
throw new ArchiveException("All Archive streams must be Writable to use Archive writing functionality.");
}
}
public override ICollection<TEntry> Entries
{
get
@@ -48,7 +61,6 @@ namespace SharpCompress.Archive
private void RebuildModifiedCollection()
{
hasModifications = true;
newEntries.RemoveAll(v => removedEntries.Contains(v));
modifiedEntries.Clear();
modifiedEntries.AddRange(OldEntries.Concat(newEntries));
}
@@ -60,90 +72,50 @@ namespace SharpCompress.Archive
public void RemoveEntry(TEntry entry)
{
CheckWritable();
if (!removedEntries.Contains(entry))
{
removedEntries.Add(entry);
RebuildModifiedCollection();
}
}
void IWritableArchive.RemoveEntry(IArchiveEntry entry)
{
RemoveEntry((TEntry)entry);
}
public TEntry AddEntry(string key, Stream source,
public void AddEntry(string filePath, Stream source,
long size = 0, DateTime? modified = null)
{
return AddEntry(key, source, false, size, modified);
}
IArchiveEntry IWritableArchive.AddEntry(string key, Stream source, bool closeStream, long size, DateTime? modified)
{
return AddEntry(key, source, closeStream, size, modified);
}
public TEntry AddEntry(string key, Stream source, bool closeStream,
long size = 0, DateTime? modified = null)
{
if (key.StartsWith("/")
|| key.StartsWith("\\"))
{
key = key.Substring(1);
}
if (DoesKeyMatchExisting(key))
{
throw new ArchiveException("Cannot add entry with duplicate key: " + key);
}
var entry = CreateEntry(key, source, size, modified, closeStream);
newEntries.Add(entry);
CheckWritable();
newEntries.Add(CreateEntry(filePath, source, size, modified, false));
RebuildModifiedCollection();
return entry;
}
private bool DoesKeyMatchExisting(string key)
public void AddEntry(string filePath, Stream source, bool closeStream,
long size = 0, DateTime? modified = null)
{
foreach (var path in Entries.Select(x => x.Key))
{
var p = path.Replace('/','\\');
if (p.StartsWith("\\"))
{
p = p.Substring(1);
}
return string.Equals(p, key, StringComparison.OrdinalIgnoreCase);
}
return false;
CheckWritable();
newEntries.Add(CreateEntry(filePath, source, size, modified, closeStream));
RebuildModifiedCollection();
}
#if !PORTABLE && !NETFX_CORE
public void AddEntry(string filePath, FileInfo fileInfo)
{
if (!fileInfo.Exists)
{
throw new ArgumentException("FileInfo does not exist.");
}
AddEntry(filePath, fileInfo.OpenRead(), true, fileInfo.Length, fileInfo.LastWriteTime);
}
#endif
public void SaveTo(Stream stream, CompressionInfo compressionType)
{
//reset streams of new entries
newEntries.Cast<IWritableArchiveEntry>().ForEach(x => x.Stream.Seek(0, SeekOrigin.Begin));
SaveTo(stream, compressionType, OldEntries, newEntries);
}
protected TEntry CreateEntry(string key, Stream source, long size, DateTime? modified,
bool closeStream)
{
if (!source.CanRead || !source.CanSeek)
{
throw new ArgumentException("Streams must be readable and seekable to use the Writing Archive API");
}
return CreateEntryInternal(key, source, size, modified, closeStream);
}
protected abstract TEntry CreateEntryInternal(string key, Stream source, long size, DateTime? modified,
protected abstract TEntry CreateEntry(string filePath, Stream source, long size, DateTime? modified,
bool closeStream);
protected abstract void SaveTo(Stream stream, CompressionInfo compressionType,
IEnumerable<TEntry> oldEntries, IEnumerable<TEntry> newEntries);
public override void Dispose()
{
base.Dispose();
newEntries.Cast<Entry>().ForEach(x => x.Close());
removedEntries.Cast<Entry>().ForEach(x => x.Close());
modifiedEntries.Cast<Entry>().ForEach(x => x.Close());
}
}
}

View File

@@ -31,6 +31,12 @@ namespace SharpCompress.Archive
return ZipArchive.Open(stream, options, null);
}
stream.Seek(0, SeekOrigin.Begin);
if (RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
{
stream.Seek(0, SeekOrigin.Begin);
return RarArchive.Open(stream, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (TarArchive.IsTarFile(stream))
{
stream.Seek(0, SeekOrigin.Begin);
@@ -48,16 +54,10 @@ namespace SharpCompress.Archive
stream.Seek(0, SeekOrigin.Begin);
return GZipArchive.Open(stream, options);
}
stream.Seek(0, SeekOrigin.Begin);
if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
{
stream.Seek(0, SeekOrigin.Begin);
return RarArchive.Open(stream, options);
}
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
}
public static IWritableArchive Create(ArchiveType type)
public static IArchive Create(ArchiveType type)
{
switch (type)
{
@@ -69,10 +69,6 @@ namespace SharpCompress.Archive
{
return TarArchive.Create();
}
case ArchiveType.GZip:
{
return GZipArchive.Create();
}
default:
{
throw new NotSupportedException("Cannot create Archives of type: " + type);
@@ -126,6 +122,12 @@ namespace SharpCompress.Archive
return ZipArchive.Open(fileInfo, options, null);
}
stream.Seek(0, SeekOrigin.Begin);
if (RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
{
stream.Dispose();
return RarArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (TarArchive.IsTarFile(stream))
{
stream.Dispose();
@@ -143,13 +145,7 @@ namespace SharpCompress.Archive
stream.Dispose();
return GZipArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen))
{
stream.Dispose();
return RarArchive.Open(fileInfo, options);
}
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
throw new InvalidOperationException("Cannot determine compressed stream type.");
}
}

View File

@@ -75,11 +75,6 @@ namespace SharpCompress.Archive.GZip
return new GZipArchive(stream, options);
}
public static GZipArchive Create()
{
return new GZipArchive();
}
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// Constructor with a FileInfo object to an existing file.
@@ -152,7 +147,7 @@ namespace SharpCompress.Archive.GZip
/// <param name="stream"></param>
/// <param name="options"></param>
internal GZipArchive(Stream stream, Options options)
: base(ArchiveType.GZip, stream, options)
: base(ArchiveType.GZip, stream.AsEnumerable(), options)
{
}
@@ -163,10 +158,10 @@ namespace SharpCompress.Archive.GZip
public void SaveTo(Stream stream)
{
SaveTo(stream, CompressionType.GZip);
this.SaveTo(stream, CompressionType.GZip);
}
protected override GZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
protected override GZipArchiveEntry CreateEntry(string filePath, Stream source, long size, DateTime? modified,
bool closeStream)
{
if (Entries.Any())
@@ -191,7 +186,7 @@ namespace SharpCompress.Archive.GZip
{
using (var entryStream = entry.OpenEntryStream())
{
writer.Write(entry.Key, entryStream, entry.LastModifiedTime);
writer.Write(entry.FilePath, entryStream, entry.LastModifiedTime);
}
}
}

View File

@@ -1,16 +1,18 @@
using System.IO;
using System.Linq;
using SharpCompress.Common;
using SharpCompress.Common.GZip;
namespace SharpCompress.Archive.GZip
{
public class GZipArchiveEntry : GZipEntry, IArchiveEntry
{
private GZipArchive archive;
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part)
: base(part)
{
Archive = archive;
this.archive = archive;
}
public virtual Stream OpenEntryStream()
@@ -19,7 +21,15 @@ namespace SharpCompress.Archive.GZip
}
#region IArchiveEntry Members
public IArchive Archive { get; private set; }
public void WriteTo(Stream streamToWriteTo)
{
if (IsEncrypted)
{
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
}
this.Extract(archive, streamToWriteTo);
}
public bool IsComplete
{

View File

@@ -6,31 +6,30 @@ using SharpCompress.IO;
namespace SharpCompress.Archive.GZip
{
internal class GZipWritableArchiveEntry : GZipArchiveEntry, IWritableArchiveEntry
internal class GZipWritableArchiveEntry : GZipArchiveEntry
{
private readonly string path;
private readonly long size;
private readonly DateTime? lastModified;
private readonly bool closeStream;
private readonly Stream stream;
private string path;
private long size;
private DateTime? lastModified;
private bool closeStream;
internal GZipWritableArchiveEntry(GZipArchive archive, Stream stream,
string path, long size, DateTime? lastModified, bool closeStream)
: base(archive, null)
{
this.stream = stream;
this.Stream = stream;
this.path = path;
this.size = size;
this.lastModified = lastModified;
this.closeStream = closeStream;
}
public override long Crc
public override uint Crc
{
get { return 0; }
}
public override string Key
public override string FilePath
{
get { return path; }
}
@@ -85,26 +84,18 @@ namespace SharpCompress.Archive.GZip
get { throw new NotImplementedException(); }
}
Stream IWritableArchiveEntry.Stream
{
get
{
return stream;
}
}
internal Stream Stream { get; private set; }
public override Stream OpenEntryStream()
{
//ensure new stream is at the start, this could be reset
stream.Seek(0, SeekOrigin.Begin);
return new NonDisposingStream(stream);
return new NonDisposingStream(Stream);
}
internal override void Close()
{
if (closeStream)
{
stream.Dispose();
Stream.Dispose();
}
}
}

View File

@@ -1,40 +1,10 @@
using System.IO;
using SharpCompress.Common;
using SharpCompress.IO;
namespace SharpCompress.Archive
{
public static class IArchiveEntryExtensions
{
public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo)
{
if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid)
{
throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files.");
}
if (archiveEntry.IsDirectory)
{
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
}
var streamListener = archiveEntry.Archive as IArchiveExtractionListener;
streamListener.EnsureEntriesLoaded();
streamListener.FireEntryExtractionBegin(archiveEntry);
streamListener.FireFilePartExtractionBegin(archiveEntry.Key, archiveEntry.Size, archiveEntry.CompressedSize);
var entryStream = archiveEntry.OpenEntryStream();
if (entryStream == null)
{
return;
}
using(entryStream)
using (Stream s = new ListeningStream(streamListener, entryStream))
{
s.TransferTo(streamToWriteTo);
}
streamListener.FireEntryExtractionEnd(archiveEntry);
}
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// Extract to specific directory, retaining filename
@@ -42,13 +12,13 @@ namespace SharpCompress.Archive
public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory,
ExtractOptions options = ExtractOptions.Overwrite)
{
string destinationFileName;
string file = Path.GetFileName(entry.Key);
string destinationFileName = string.Empty;
string file = Path.GetFileName(entry.FilePath);
if (options.HasFlag(ExtractOptions.ExtractFullPath))
{
string folder = Path.GetDirectoryName(entry.Key);
string folder = Path.GetDirectoryName(entry.FilePath);
string destdir = Path.Combine(destinationDirectory, folder);
if (!Directory.Exists(destdir))
{
@@ -80,7 +50,9 @@ namespace SharpCompress.Archive
fm = FileMode.CreateNew;
}
using (FileStream fs = File.Open(destinationFileName, fm))
// using (Stream entryStream = entry.OpenEntryStream())
{
//entryStream.TransferTo(fs);
entry.WriteTo(fs);
}
}

View File

@@ -11,14 +11,11 @@ namespace SharpCompress.Archive
/// </summary>
Stream OpenEntryStream();
void WriteTo(Stream stream);
/// <summary>
/// The archive can find all the parts of the archive needed to extract this entry.
/// </summary>
bool IsComplete { get; }
/// <summary>
/// The archive instance this entry belongs to
/// </summary>
IArchive Archive { get; }
}
}

View File

@@ -1,11 +0,0 @@
using SharpCompress.Common;
namespace SharpCompress.Archive
{
internal interface IArchiveExtractionListener : IExtractionListener
{
void EnsureEntriesLoaded();
void FireEntryExtractionBegin(IArchiveEntry entry);
void FireEntryExtractionEnd(IArchiveEntry entry);
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.IO;
using SharpCompress.Common;
namespace SharpCompress.Archive
{
public interface IWritableArchive : IArchive
{
void RemoveEntry(IArchiveEntry entry);
IArchiveEntry AddEntry(string key, Stream source, bool closeStream, long size = 0, DateTime? modified = null);
void SaveTo(Stream stream, CompressionInfo compressionType);
}
}

View File

@@ -1,9 +0,0 @@
using System.IO;
namespace SharpCompress.Archive
{
internal interface IWritableArchiveEntry
{
Stream Stream { get; }
}
}

View File

@@ -12,8 +12,8 @@ namespace SharpCompress.Archive.Rar
/// </summary>
internal class FileInfoRarArchiveVolume : RarVolume
{
internal FileInfoRarArchiveVolume(FileInfo fileInfo, string password, Options options)
: base(StreamingMode.Seekable, fileInfo.OpenRead(), password, FixOptions(options))
internal FileInfoRarArchiveVolume(FileInfo fileInfo, Options options)
: base(StreamingMode.Seekable, fileInfo.OpenRead(), FixOptions(options))
{
FileInfo = fileInfo;
FileParts = base.GetVolumeFileParts().ToReadOnly();
@@ -42,5 +42,10 @@ namespace SharpCompress.Archive.Rar
{
return FileParts;
}
public override FileInfo VolumeFile
{
get { return FileInfo; }
}
}
}

View File

@@ -4,12 +4,12 @@ using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Archive.Rar
{
internal class FileInfoRarFilePart : SeekableFilePart
internal class FileInfoRarFilePart : RarFilePart
{
private readonly FileInfoRarArchiveVolume volume;
private FileInfoRarArchiveVolume volume;
internal FileInfoRarFilePart(FileInfoRarArchiveVolume volume, MarkHeader mh, FileHeader fh, FileInfo fi)
: base(mh, fh, volume.Stream, volume.Password)
: base(mh, fh)
{
this.volume = volume;
FileInfo = fi;
@@ -17,6 +17,13 @@ namespace SharpCompress.Archive.Rar
internal FileInfo FileInfo { get; private set; }
internal override Stream GetCompressedStream()
{
var stream = volume.Stream;
stream.Position = FileHeader.DataStartPosition;
return stream;
}
internal override string FilePartName
{
get

View File

@@ -19,5 +19,13 @@ namespace SharpCompress.Archive.Rar
{
return archive.Volumes.First().IsMultiVolume;
}
/// <summary>
/// RarArchive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
/// </summary>
public static bool IsSolidArchive(this RarArchive archive)
{
return archive.IsSolid;
}
}
}

View File

@@ -27,15 +27,14 @@ namespace SharpCompress.Archive.Rar
/// </summary>
/// <param name="fileInfo"></param>
/// <param name="options"></param>
/// <param name="password"></param>
internal RarArchive(FileInfo fileInfo, Options options, string password)
: base(ArchiveType.Rar, fileInfo, options, password)
internal RarArchive(FileInfo fileInfo, Options options)
: base(ArchiveType.Rar, fileInfo, options)
{
}
protected override IEnumerable<RarVolume> LoadVolumes(FileInfo file, Options options)
{
return RarArchiveVolumeFactory.GetParts(file, Password, options);
return RarArchiveVolumeFactory.GetParts(file, options);
}
#endif
@@ -44,9 +43,8 @@ namespace SharpCompress.Archive.Rar
/// </summary>
/// <param name="streams"></param>
/// <param name="options"></param>
/// <param name="password"></param>
internal RarArchive(IEnumerable<Stream> streams, Options options, string password)
: base(ArchiveType.Rar, streams, options, password)
internal RarArchive(IEnumerable<Stream> streams, Options options)
: base(ArchiveType.Rar, streams, options)
{
}
@@ -57,7 +55,7 @@ namespace SharpCompress.Archive.Rar
protected override IEnumerable<RarVolume> LoadVolumes(IEnumerable<Stream> streams, Options options)
{
return RarArchiveVolumeFactory.GetParts(streams, Password, options);
return RarArchiveVolumeFactory.GetParts(streams, options);
}
protected override IReader CreateReaderForSolidExtraction()
@@ -75,16 +73,33 @@ namespace SharpCompress.Archive.Rar
#region Creation
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// Constructor expects a filepath to an existing file.
/// </summary>
/// <param name="filePath"></param>
public static RarArchive Open(string filePath)
{
return Open(filePath, Options.None);
}
/// <summary>
/// Constructor with a FileInfo object to an existing file.
/// </summary>
/// <param name="fileInfo"></param>
public static RarArchive Open(FileInfo fileInfo)
{
return Open(fileInfo, Options.None);
}
/// <summary>
/// Constructor expects a filepath to an existing file.
/// </summary>
/// <param name="filePath"></param>
/// <param name="options"></param>
/// <param name="password"></param>
public static RarArchive Open(string filePath, Options options = Options.None, string password = null)
public static RarArchive Open(string filePath, Options options)
{
filePath.CheckNotNullOrEmpty("filePath");
return Open(new FileInfo(filePath), options, password);
return Open(new FileInfo(filePath), options);
}
/// <summary>
@@ -92,23 +107,42 @@ namespace SharpCompress.Archive.Rar
/// </summary>
/// <param name="fileInfo"></param>
/// <param name="options"></param>
/// <param name="password"></param>
public static RarArchive Open(FileInfo fileInfo, Options options = Options.None, string password = null)
public static RarArchive Open(FileInfo fileInfo, Options options)
{
fileInfo.CheckNotNull("fileInfo");
return new RarArchive(fileInfo, options, password);
return new RarArchive(fileInfo, options);
}
#endif
/// <summary>
/// Takes a seekable Stream as a source
/// </summary>
/// <param name="stream"></param>
public static RarArchive Open(Stream stream)
{
stream.CheckNotNull("stream");
return Open(stream.AsEnumerable());
}
/// <summary>
/// Takes a seekable Stream as a source
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <param name="password"></param>
public static RarArchive Open(Stream stream, Options options = Options.KeepStreamsOpen, string password = null)
public static RarArchive Open(Stream stream, Options options)
{
stream.CheckNotNull("stream");
return Open(stream.AsEnumerable(), options, password);
return Open(stream.AsEnumerable(), options);
}
/// <summary>
/// Takes multiple seekable Streams for a multi-part archive
/// </summary>
/// <param name="streams"></param>
public static RarArchive Open(IEnumerable<Stream> streams)
{
streams.CheckNotNull("streams");
return new RarArchive(streams, Options.KeepStreamsOpen);
}
/// <summary>
@@ -116,11 +150,10 @@ namespace SharpCompress.Archive.Rar
/// </summary>
/// <param name="streams"></param>
/// <param name="options"></param>
/// <param name="password"></param>
public static RarArchive Open(IEnumerable<Stream> streams, Options options = Options.KeepStreamsOpen, string password = null)
public static RarArchive Open(IEnumerable<Stream> streams, Options options)
{
streams.CheckNotNull("streams");
return new RarArchive(streams, options, password);
return new RarArchive(streams, options);
}
#if !PORTABLE && !NETFX_CORE

View File

@@ -11,12 +11,11 @@ namespace SharpCompress.Archive.Rar
public class RarArchiveEntry : RarEntry, IArchiveEntry
{
private readonly ICollection<RarFilePart> parts;
private readonly RarArchive archive;
internal RarArchiveEntry(RarArchive archive, IEnumerable<RarFilePart> parts)
{
this.parts = parts.ToList();
this.archive = archive;
Archive = archive;
}
public override CompressionType CompressionType
@@ -24,13 +23,7 @@ namespace SharpCompress.Archive.Rar
get { return CompressionType.Rar; }
}
public IArchive Archive
{
get
{
return archive;
}
}
private RarArchive Archive { get; set; }
internal override IEnumerable<FilePart> Parts
{
@@ -42,13 +35,14 @@ namespace SharpCompress.Archive.Rar
get { return parts.First().FileHeader; }
}
public override long Crc
public override uint Crc
{
get
{
CheckIncomplete();
return parts.Select(fp => fp.FileHeader)
.Single(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)).FileCRC;
.Where(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER))
.Single().FileCRC;
}
}
@@ -73,8 +67,22 @@ namespace SharpCompress.Archive.Rar
public Stream OpenEntryStream()
{
return new RarStream(archive.Unpack, FileHeader,
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
return new RarStream(Archive.Unpack, FileHeader,
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), Archive));
}
public void WriteTo(Stream streamToWriteTo)
{
CheckIncomplete();
if (Archive.IsSolidArchive())
{
throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files.");
}
if (IsEncrypted)
{
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
}
this.Extract(Archive, streamToWriteTo);
}
public bool IsComplete
@@ -89,5 +97,9 @@ namespace SharpCompress.Archive.Rar
throw new IncompleteArchiveException("ArchiveEntry is incomplete and cannot perform this operation.");
}
}
internal override void Close()
{
}
}
}

View File

@@ -13,7 +13,7 @@ namespace SharpCompress.Archive.Rar
{
internal static class RarArchiveVolumeFactory
{
internal static IEnumerable<RarVolume> GetParts(IEnumerable<Stream> streams, string password, Options options)
internal static IEnumerable<RarVolume> GetParts(IEnumerable<Stream> streams, Options options)
{
foreach (Stream s in streams)
{
@@ -21,15 +21,15 @@ namespace SharpCompress.Archive.Rar
{
throw new ArgumentException("Stream is not readable and seekable");
}
StreamRarArchiveVolume part = new StreamRarArchiveVolume(s, password, options);
StreamRarArchiveVolume part = new StreamRarArchiveVolume(s, options);
yield return part;
}
}
#if !PORTABLE && !NETFX_CORE
internal static IEnumerable<RarVolume> GetParts(FileInfo fileInfo, string password, Options options)
internal static IEnumerable<RarVolume> GetParts(FileInfo fileInfo, Options options)
{
FileInfoRarArchiveVolume part = new FileInfoRarArchiveVolume(fileInfo, password, options);
FileInfoRarArchiveVolume part = new FileInfoRarArchiveVolume(fileInfo, options);
yield return part;
if (!part.ArchiveHeader.ArchiveHeaderFlags.HasFlag(ArchiveFlags.VOLUME))
@@ -41,7 +41,7 @@ namespace SharpCompress.Archive.Rar
//we use fileinfo because rar is dumb and looks at file names rather than archive info for another volume
while (fileInfo != null && fileInfo.Exists)
{
part = new FileInfoRarArchiveVolume(fileInfo, password, options);
part = new FileInfoRarArchiveVolume(fileInfo, options);
fileInfo = GetNextFileInfo(ah, part.FileParts.FirstOrDefault() as FileInfoRarFilePart);
yield return part;

View File

@@ -1,39 +0,0 @@
using System;
using System.IO;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Archive.Rar
{
internal class SeekableFilePart : RarFilePart
{
private readonly Stream stream;
private readonly string password;
internal SeekableFilePart(MarkHeader mh, FileHeader fh, Stream stream, string password)
: base(mh, fh)
{
this.stream = stream;
this.password = password;
}
internal override Stream GetCompressedStream()
{
stream.Position = FileHeader.DataStartPosition;
if (FileHeader.Salt != null)
{
#if PORTABLE
throw new NotSupportedException("Encrypted Rar files aren't supported in portable distro.");
#else
return new RarCryptoWrapper(stream, password, FileHeader.Salt);
#endif
}
return stream;
}
internal override string FilePartName
{
get { return "Unknown Stream - File Entry: " + FileHeader.FileName; }
}
}
}

View File

@@ -0,0 +1,28 @@
using System.IO;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Archive.Rar
{
internal class SeekableStreamFilePart : RarFilePart
{
internal SeekableStreamFilePart(MarkHeader mh, FileHeader fh, Stream stream)
: base(mh, fh)
{
Stream = stream;
}
internal Stream Stream { get; private set; }
internal override Stream GetCompressedStream()
{
Stream.Position = FileHeader.DataStartPosition;
return Stream;
}
internal override string FilePartName
{
get { return "Unknown Stream - File Entry: " + base.FileHeader.FileName; }
}
}
}

View File

@@ -9,11 +9,18 @@ namespace SharpCompress.Archive.Rar
{
internal class StreamRarArchiveVolume : RarVolume
{
internal StreamRarArchiveVolume(Stream stream, string password, Options options)
: base(StreamingMode.Seekable, stream, password, options)
internal StreamRarArchiveVolume(Stream stream, Options options)
: base(StreamingMode.Seekable, stream, options)
{
}
#if !PORTABLE && !NETFX_CORE
public override FileInfo VolumeFile
{
get { return null; }
}
#endif
internal override IEnumerable<RarFilePart> ReadFileParts()
{
return GetVolumeFileParts();
@@ -21,7 +28,7 @@ namespace SharpCompress.Archive.Rar
internal override RarFilePart CreateFilePart(FileHeader fileHeader, MarkHeader markHeader)
{
return new SeekableFilePart(markHeader, fileHeader, Stream, Password);
return new SeekableStreamFilePart(markHeader, fileHeader, Stream);
}
}
}

View File

@@ -77,17 +77,13 @@ namespace SharpCompress.Archive.SevenZip
#if !PORTABLE && !NETFX_CORE
internal SevenZipArchive(FileInfo fileInfo, Options options)
: base(ArchiveType.SevenZip, fileInfo, options, null)
: base(ArchiveType.SevenZip, fileInfo, options)
{
}
protected override IEnumerable<SevenZipVolume> LoadVolumes(FileInfo file, Options options)
{
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
{
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
}
return new SevenZipVolume(file.OpenRead(), options).AsEnumerable();
return new SevenZipVolume(file, options).AsEnumerable();
}
public static bool IsSevenZipFile(string filePath)
@@ -109,7 +105,7 @@ namespace SharpCompress.Archive.SevenZip
#endif
internal SevenZipArchive(Stream stream, Options options)
: base(ArchiveType.SevenZip, stream.AsEnumerable(), options, null)
: base(ArchiveType.SevenZip, stream.AsEnumerable(), options)
{
}
@@ -236,7 +232,7 @@ namespace SharpCompress.Archive.SevenZip
protected override EntryStream GetEntryStream()
{
return CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size));
return new EntryStream(new ReadOnlySubStream(currentStream, currentItem.Size));
}
}
}

View File

@@ -1,21 +1,32 @@
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.SevenZip;
namespace SharpCompress.Archive.SevenZip
{
public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry
{
private SevenZipArchive archive;
internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part)
: base(part)
{
Archive = archive;
this.archive = archive;
}
public Stream OpenEntryStream()
{
return FilePart.GetCompressedStream();
}
public IArchive Archive { get; private set; }
public void WriteTo(Stream stream)
{
if (IsEncrypted)
{
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
}
this.Extract(archive, stream);
}
public bool IsComplete
{

View File

@@ -100,7 +100,7 @@ namespace SharpCompress.Archive.Tar
{
try
{
TarHeader tar = new TarHeader();
TarHeader tar = new TarHeader(EntryType.File);
tar.Read(new BinaryReader(stream));
return tar.Name.Length > 0 && Enum.IsDefined(typeof (EntryType), tar.EntryType);
}
@@ -123,11 +123,7 @@ namespace SharpCompress.Archive.Tar
protected override IEnumerable<TarVolume> LoadVolumes(FileInfo file, Options options)
{
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
{
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
}
return new TarVolume(file.OpenRead(), options).AsEnumerable();
return new TarVolume(file, options).AsEnumerable();
}
#endif
@@ -137,7 +133,7 @@ namespace SharpCompress.Archive.Tar
/// <param name="stream"></param>
/// <param name="options"></param>
internal TarArchive(Stream stream, Options options)
: base(ArchiveType.Tar, stream, options)
: base(ArchiveType.Tar, stream.AsEnumerable(), options)
{
}
@@ -169,21 +165,11 @@ namespace SharpCompress.Archive.Tar
{
var entry = new TarArchiveEntry(this, new TarFilePart(previousHeader, stream),
CompressionType.None);
var oldStreamPos = stream.Position;
using(var entryStream = entry.OpenEntryStream())
using(var memoryStream = new MemoryStream())
{
entryStream.TransferTo(memoryStream);
memoryStream.Position = 0;
var bytes = memoryStream.ToArray();
header.Name = ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length).TrimNulls();
}
stream.Position = oldStreamPos;
var memoryStream = new MemoryStream();
entry.WriteTo(memoryStream);
memoryStream.Position = 0;
var bytes = memoryStream.ToArray();
header.Name = ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length).TrimNulls();
previousHeader = null;
}
yield return new TarArchiveEntry(this, new TarFilePart(header, stream), CompressionType.None);
@@ -197,7 +183,7 @@ namespace SharpCompress.Archive.Tar
return new TarArchive();
}
protected override TarArchiveEntry CreateEntryInternal(string filePath, Stream source,
protected override TarArchiveEntry CreateEntry(string filePath, Stream source,
long size, DateTime? modified, bool closeStream)
{
return new TarWritableArchiveEntry(this, source, CompressionType.Unknown, filePath, size, modified,
@@ -215,7 +201,7 @@ namespace SharpCompress.Archive.Tar
{
using (var entryStream = entry.OpenEntryStream())
{
writer.Write(entry.Key, entryStream, entry.LastModifiedTime, entry.Size);
writer.Write(entry.FilePath, entryStream, entry.LastModifiedTime, entry.Size);
}
}
}

View File

@@ -7,10 +7,12 @@ namespace SharpCompress.Archive.Tar
{
public class TarArchiveEntry : TarEntry, IArchiveEntry
{
private TarArchive archive;
internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType)
: base(part, compressionType)
{
Archive = archive;
this.archive = archive;
}
public virtual Stream OpenEntryStream()
@@ -19,7 +21,15 @@ namespace SharpCompress.Archive.Tar
}
#region IArchiveEntry Members
public IArchive Archive { get; private set; }
public void WriteTo(Stream streamToWriteTo)
{
if (IsEncrypted)
{
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
}
this.Extract(archive, streamToWriteTo);
}
public bool IsComplete
{

View File

@@ -6,31 +6,30 @@ using SharpCompress.IO;
namespace SharpCompress.Archive.Tar
{
internal class TarWritableArchiveEntry : TarArchiveEntry, IWritableArchiveEntry
internal class TarWritableArchiveEntry : TarArchiveEntry
{
private readonly string path;
private readonly long size;
private readonly DateTime? lastModified;
private readonly bool closeStream;
private readonly Stream stream;
private string path;
private long size;
private DateTime? lastModified;
private bool closeStream;
internal TarWritableArchiveEntry(TarArchive archive, Stream stream, CompressionType compressionType,
string path, long size, DateTime? lastModified, bool closeStream)
: base(archive, null, compressionType)
{
this.stream = stream;
this.Stream = stream;
this.path = path;
this.size = size;
this.lastModified = lastModified;
this.closeStream = closeStream;
}
public override long Crc
public override uint Crc
{
get { return 0; }
}
public override string Key
public override string FilePath
{
get { return path; }
}
@@ -84,26 +83,19 @@ namespace SharpCompress.Archive.Tar
{
get { throw new NotImplementedException(); }
}
Stream IWritableArchiveEntry.Stream
{
get
{
return stream;
}
}
internal Stream Stream { get; private set; }
public override Stream OpenEntryStream()
{
//ensure new stream is at the start, this could be reset
stream.Seek(0, SeekOrigin.Begin);
return new NonDisposingStream(stream);
return new NonDisposingStream(Stream);
}
internal override void Close()
{
if (closeStream)
{
stream.Dispose();
Stream.Dispose();
}
}
}

View File

@@ -14,7 +14,7 @@ namespace SharpCompress.Archive.Zip
{
public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
{
private readonly SeekableZipHeaderFactory headerFactory;
private SeekableZipHeaderFactory headerFactory;
/// <summary>
/// Gets or sets the compression level applied to files added to the archive,
@@ -148,11 +148,7 @@ namespace SharpCompress.Archive.Zip
protected override IEnumerable<ZipVolume> LoadVolumes(FileInfo file, Options options)
{
if (FlagUtility.HasFlag(options, Options.KeepStreamsOpen))
{
options = (Options)FlagUtility.SetFlag(options, Options.KeepStreamsOpen, false);
}
return new ZipVolume(file.OpenRead(), options).AsEnumerable();
return new ZipVolume(file, options).AsEnumerable();
}
#endif
@@ -168,7 +164,7 @@ namespace SharpCompress.Archive.Zip
/// <param name="options"></param>
/// <param name="password"></param>
internal ZipArchive(Stream stream, Options options, string password = null)
: base(ArchiveType.Zip, stream, options)
: base(ArchiveType.Zip, stream.AsEnumerable(), options)
{
headerFactory = new SeekableZipHeaderFactory(password);
}
@@ -181,7 +177,7 @@ namespace SharpCompress.Archive.Zip
protected override IEnumerable<ZipArchiveEntry> LoadEntries(IEnumerable<ZipVolume> volumes)
{
var volume = volumes.Single();
Stream stream = volume.Stream;
Stream stream = volumes.Single().Stream;
foreach (ZipHeader h in headerFactory.ReadSeekableHeader(stream))
{
if (h != null)
@@ -218,13 +214,13 @@ namespace SharpCompress.Archive.Zip
{
using (var entryStream = entry.OpenEntryStream())
{
writer.Write(entry.Key, entryStream, entry.LastModifiedTime, string.Empty);
writer.Write(entry.FilePath, entryStream, entry.LastModifiedTime, string.Empty);
}
}
}
}
protected override ZipArchiveEntry CreateEntryInternal(string filePath, Stream source, long size, DateTime? modified,
protected override ZipArchiveEntry CreateEntry(string filePath, Stream source, long size, DateTime? modified,
bool closeStream)
{
return new ZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream);

View File

@@ -6,10 +6,12 @@ namespace SharpCompress.Archive.Zip
{
public class ZipArchiveEntry : ZipEntry, IArchiveEntry
{
private ZipArchive archive;
internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart part)
: base(part)
{
Archive = archive;
this.archive = archive;
}
public virtual Stream OpenEntryStream()
@@ -19,7 +21,10 @@ namespace SharpCompress.Archive.Zip
#region IArchiveEntry Members
public IArchive Archive { get; private set; }
public void WriteTo(Stream streamToWriteTo)
{
this.Extract(archive, streamToWriteTo);
}
public bool IsComplete
{

View File

@@ -6,32 +6,30 @@ using SharpCompress.IO;
namespace SharpCompress.Archive.Zip
{
internal class ZipWritableArchiveEntry : ZipArchiveEntry, IWritableArchiveEntry
internal class ZipWritableArchiveEntry : ZipArchiveEntry
{
private readonly string path;
private readonly long size;
private readonly DateTime? lastModified;
private readonly bool closeStream;
private readonly Stream stream;
private bool isDisposed;
private string path;
private long size;
private DateTime? lastModified;
private bool closeStream;
internal ZipWritableArchiveEntry(ZipArchive archive, Stream stream, string path, long size,
DateTime? lastModified, bool closeStream)
: base(archive, null)
{
this.stream = stream;
this.Stream = stream;
this.path = path;
this.size = size;
this.lastModified = lastModified;
this.closeStream = closeStream;
}
public override long Crc
public override uint Crc
{
get { return 0; }
}
public override string Key
public override string FilePath
{
get { return path; }
}
@@ -86,27 +84,18 @@ namespace SharpCompress.Archive.Zip
get { throw new NotImplementedException(); }
}
Stream IWritableArchiveEntry.Stream
{
get
{
return stream;
}
}
internal Stream Stream { get; private set; }
public override Stream OpenEntryStream()
{
//ensure new stream is at the start, this could be reset
stream.Seek(0, SeekOrigin.Begin);
return new NonDisposingStream(stream);
return new NonDisposingStream(Stream);
}
internal override void Close()
{
if (closeStream && !isDisposed)
if (closeStream)
{
stream.Dispose();
isDisposed = true;
Stream.Dispose();
}
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Reflection;
using System.Reflection;
using System.Runtime.CompilerServices;
#if PORTABLE
[assembly: AssemblyTitle("SharpCompress.Portable")]
[assembly: AssemblyProduct("SharpCompress.Portable")]
@@ -10,11 +8,12 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("SharpCompress")]
[assembly: AssemblyProduct("SharpCompress")]
#endif
#if UNSIGNED
[assembly: InternalsVisibleTo("SharpCompress.Test")]
[assembly: InternalsVisibleTo("SharpCompress.Test.Portable")]
#endif
[assembly: CLSCompliant(true)]
[assembly:
InternalsVisibleTo(
"SharpCompress.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010005d6ae1b0f6875393da83c920a5b9408f5191aaf4e8b3c2c476ad2a11f5041ecae84ce9298bc4c203637e2fd3a80ad5378a9fa8da1363e98cea45c73969198a4b64510927c910001491cebbadf597b22448ad103b0a4007e339faf8fe8665dcdb70d65b27ac05b1977c0655fad06b372b820ecbdccf10a0f214fee0986dfeded"
)]
[assembly:
InternalsVisibleTo(
"SharpCompress.Test.Portable, PublicKey=002400000480000094000000060200000024000052534131000400000100010005d6ae1b0f6875393da83c920a5b9408f5191aaf4e8b3c2c476ad2a11f5041ecae84ce9298bc4c203637e2fd3a80ad5378a9fa8da1363e98cea45c73969198a4b64510927c910001491cebbadf597b22448ad103b0a4007e339faf8fe8665dcdb70d65b27ac05b1977c0655fad06b372b820ecbdccf10a0f214fee0986dfeded"
)]
#endif

View File

@@ -1,23 +1,29 @@
using System.Text;
using System.Globalization;
using System.Text;
namespace SharpCompress.Common
{
public static class ArchiveEncoding
public class ArchiveEncoding
{
/// <summary>
/// Default encoding to use when archive format doesn't specify one.
/// </summary>
public static Encoding Default { get; set; }
public static Encoding Default;
/// <summary>
/// Encoding used by encryption schemes which don't comply with RFC 2898.
/// </summary>
public static Encoding Password { get; set; }
public static Encoding Password;
static ArchiveEncoding()
{
#if PORTABLE || NETFX_CORE
Default = Encoding.UTF8;
Password = Encoding.UTF8;
#else
Default = Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage);
Password = Encoding.Default;
#endif
}
}
}

View File

@@ -3,17 +3,19 @@ using System.Collections.Generic;
namespace SharpCompress.Common
{
public abstract class Entry : IEntry
public abstract class Entry : SharpCompress.Common.IEntry
{
internal bool IsSolid { get; set; }
/// <summary>
/// The File's 32 bit CRC Hash
/// </summary>
public abstract long Crc { get; }
public abstract uint Crc { get; }
/// <summary>
/// The string key of the file internal to the Archive.
/// The path of the file internal to the Rar Archive.
/// </summary>
public abstract string Key { get; }
public abstract string FilePath { get; }
/// <summary>
/// The compressed file size
@@ -60,17 +62,10 @@ namespace SharpCompress.Common
/// </summary>
public abstract bool IsDirectory { get; }
/// <summary>
/// Entry is split among multiple volumes
/// </summary>
public abstract bool IsSplit { get; }
internal abstract IEnumerable<FilePart> Parts { get; }
internal bool IsSolid { get; set; }
internal virtual void Close()
{
}
internal abstract void Close();
}
}

View File

@@ -1,19 +1,16 @@
using System;
using System.IO;
using SharpCompress.Reader;
namespace SharpCompress.Common
{
public class EntryStream : Stream
{
public IReader Reader { get; private set; }
private Stream stream;
private bool completed;
private bool isDisposed;
internal EntryStream(IReader reader, Stream stream)
internal EntryStream(Stream stream)
{
this.Reader = reader;
this.stream = stream;
}
@@ -31,9 +28,10 @@ namespace SharpCompress.Common
protected override void Dispose(bool disposing)
{
if (!(completed || Reader.Cancelled))
if (!completed)
{
SkipEntry();
throw new InvalidOperationException(
"EntryStream has not been fully consumed. Read the entire stream or use SkipEntry.");
}
if (isDisposed)
{
@@ -61,18 +59,18 @@ namespace SharpCompress.Common
public override void Flush()
{
throw new NotSupportedException();
throw new System.NotImplementedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new System.NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -87,17 +85,17 @@ namespace SharpCompress.Common
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new System.NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new System.NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new System.NotImplementedException();
}
}
}

View File

@@ -18,12 +18,12 @@ namespace SharpCompress.Common.GZip
get { return CompressionType.GZip; }
}
public override long Crc
public override uint Crc
{
get { return 0; }
}
public override string Key
public override string FilePath
{
get { return filePart.FilePartName; }
}
@@ -82,5 +82,9 @@ namespace SharpCompress.Common.GZip
{
yield return new GZipEntry(new GZipFilePart(stream));
}
internal override void Close()
{
}
}
}

View File

@@ -21,6 +21,16 @@ namespace SharpCompress.Common.GZip
}
#endif
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// File that backs this volume, if it not stream based
/// </summary>
public override FileInfo VolumeFile
{
get { return fileInfo; }
}
#endif
public override bool IsFirstVolume
{
get { return true; }

View File

@@ -0,0 +1,44 @@
using System.IO;
namespace SharpCompress.Common
{
public class GenericVolume : Volume
{
#if !PORTABLE && !NETFX_CORE
private FileInfo fileInfo;
#endif
public GenericVolume(Stream stream, Options options)
: base(stream, options)
{
}
#if !PORTABLE && !NETFX_CORE
public GenericVolume(FileInfo fileInfo, Options options)
: base(fileInfo.OpenRead(), options)
{
this.fileInfo = fileInfo;
}
#endif
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// File that backs this volume, if it not stream based
/// </summary>
public override FileInfo VolumeFile
{
get { return fileInfo; }
}
#endif
public override bool IsFirstVolume
{
get { return true; }
}
public override bool IsMultiVolume
{
get { return true; }
}
}
}

View File

@@ -7,9 +7,9 @@ namespace SharpCompress.Common
CompressionType CompressionType { get; }
DateTime? ArchivedTime { get; }
long CompressedSize { get; }
long Crc { get; }
uint Crc { get; }
DateTime? CreatedTime { get; }
string Key { get; }
string FilePath { get; }
bool IsDirectory { get; }
bool IsEncrypted { get; }
bool IsSplit { get; }

View File

@@ -1,6 +1,6 @@
namespace SharpCompress.Common
{
internal interface IExtractionListener
internal interface IStreamListener
{
void FireFilePartExtractionBegin(string name, long size, long compressedSize);
void FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes);

View File

@@ -7,5 +7,11 @@ namespace SharpCompress.Common
{
public interface IVolume : IDisposable
{
#if !PORTABLE && !NETFX_CORE
/// <summary>
/// File that backs this volume, if it not stream based
/// </summary>
FileInfo VolumeFile { get; }
#endif
}
}

View File

@@ -1,22 +0,0 @@
using SharpCompress.IO;
namespace SharpCompress.Common.Rar.Headers
{
// ProtectHeader is part of the Recovery Record feature
internal class ProtectHeader : RarHeader
{
protected override void ReadFromReader(MarkingBinaryReader reader)
{
Version = reader.ReadByte();
RecSectors = reader.ReadUInt16();
TotalBlocks = reader.ReadUInt32();
Mark = reader.ReadBytes(8);
}
internal uint DataSize { get { return AdditionalSize; } }
internal byte Version { get; private set; }
internal ushort RecSectors { get; private set; }
internal uint TotalBlocks { get; private set; }
internal byte[] Mark { get; private set; }
}
}

View File

@@ -93,11 +93,7 @@ namespace SharpCompress.Common.Rar.Headers
{
if (!Options.HasFlag(Options.KeepStreamsOpen))
{
#if NET2
reader.Close();
#else
reader.Dispose();
#endif
}
throw new InvalidFormatException("Error trying to read rar signature.", e);
}
@@ -124,10 +120,6 @@ namespace SharpCompress.Common.Rar.Headers
if (IsEncrypted)
{
if (Password == null)
{
throw new CryptographicException("Encrypted Rar archive has no password specified.");
}
reader.SkipQueue();
byte[] salt = reader.ReadBytes(8);
reader.InitializeAes(salt);
@@ -151,33 +143,6 @@ namespace SharpCompress.Common.Rar.Headers
{
return header.PromoteHeader<MarkHeader>(reader);
}
case HeaderType.ProtectHeader:
{
ProtectHeader ph = header.PromoteHeader<ProtectHeader>(reader);
// skip the recovery record data, we do not use it.
switch (StreamingMode)
{
case StreamingMode.Seekable:
{
reader.BaseStream.Position += ph.DataSize;
}
break;
case StreamingMode.Streaming:
{
reader.BaseStream.Skip(ph.DataSize);
}
break;
default:
{
throw new InvalidFormatException("Invalid StreamingMode");
}
}
return ph;
}
case HeaderType.NewSubHeader:
{
FileHeader fh = header.PromoteHeader<FileHeader>(reader);

View File

@@ -20,17 +20,17 @@ namespace SharpCompress.Common.Rar
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
@@ -70,27 +70,27 @@ namespace SharpCompress.Common.Rar
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override bool CanRead
{
get { return true; }
get { throw new NotImplementedException(); }
}
public override bool CanSeek
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position { get; set; }

View File

@@ -10,7 +10,7 @@ namespace SharpCompress.Common.Rar
/// <summary>
/// The File's 32 bit CRC Hash
/// </summary>
public override long Crc
public override uint Crc
{
get { return FileHeader.FileCRC; }
}
@@ -18,7 +18,7 @@ namespace SharpCompress.Common.Rar
/// <summary>
/// The path of the file internal to the Rar Archive.
/// </summary>
public override string Key
public override string FilePath
{
get { return FileHeader.FileName; }
}
@@ -79,7 +79,7 @@ namespace SharpCompress.Common.Rar
public override string ToString()
{
return string.Format("Entry Path: {0} Compressed Size: {1} Uncompressed Size: {2} CRC: {3}",
Key, CompressedSize, Size, Crc);
FilePath, CompressedSize, Size, Crc);
}
}
}

View File

@@ -28,10 +28,11 @@ namespace SharpCompress.Common.Rar
aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE];
int rawLength = 2 * password.Length;
byte[] rawPassword = new byte[rawLength + 8];
byte[] passwordBytes = Encoding.Unicode.GetBytes(password);
for (int i = 0; i < rawLength; i++)
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
for (int i = 0; i < password.Length; i++)
{
rawPassword[i] = passwordBytes[i];
rawPassword[i * 2] = passwordBytes[i];
rawPassword[i * 2 + 1] = 0;
}
for (int i = 0; i < salt.Length; i++)
{
@@ -105,7 +106,7 @@ namespace SharpCompress.Common.Rar
public void Dispose()
{
((IDisposable)rijndael).Dispose();
rijndael.Dispose();
}
}
}

View File

@@ -13,16 +13,20 @@ namespace SharpCompress.Common.Rar
public abstract class RarVolume : Volume
{
private readonly RarHeaderFactory headerFactory;
public string Password { get; set; }
internal RarVolume(StreamingMode mode, Stream stream, Options options)
: this(mode, stream, null, options)
{
}
internal RarVolume(StreamingMode mode, Stream stream, string password, Options options)
: base(stream, options)
{
headerFactory = new RarHeaderFactory(mode, options, password);
Password = password;
}
internal string Password { get; private set; }
internal StreamingMode Mode
{
get { return headerFactory.StreamingMode; }

View File

@@ -1,13 +0,0 @@
using System;
namespace SharpCompress.Common
{
public class ReaderExtractionEventArgs<T> : EventArgs
{
internal ReaderExtractionEventArgs(T entry)
{
Item = entry;
}
public T Item { get; private set; }
}
}

View File

@@ -159,7 +159,7 @@ namespace SharpCompress.Common.SevenZip
private DateTime TranslateTime(long time)
{
// FILETIME = 100-nanosecond intervals since January 1, 1601 (UTC)
return DateTime.FromFileTimeUtc(time).ToLocalTime();
return DateTime.FromFileTimeUtc(time);
}
private DateTime? TranslateTime(long? time)
@@ -1089,48 +1089,48 @@ namespace SharpCompress.Common.SevenZip
public override bool CanRead
{
get { return true; }
get { throw new NotImplementedException(); }
}
public override bool CanSeek
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
private Stream _stream;
@@ -1192,7 +1192,7 @@ namespace SharpCompress.Common.SevenZip
{
// we support partial extracting
System.Diagnostics.Debugger.Break();
throw new NotSupportedException();
throw new NotImplementedException();
}
OpenFile();
}

View File

@@ -17,12 +17,12 @@ namespace SharpCompress.Common.SevenZip
get { return FilePart.CompressionType; }
}
public override long Crc
public override uint Crc
{
get { return FilePart.Header.Crc ?? 0; }
}
public override string Key
public override string FilePath
{
get { return FilePart.Header.Name; }
}
@@ -39,22 +39,22 @@ namespace SharpCompress.Common.SevenZip
public override DateTime? LastModifiedTime
{
get { return FilePart.Header.MTime; }
get { throw new NotImplementedException(); }
}
public override DateTime? CreatedTime
{
get { return null; }
get { throw new NotImplementedException(); }
}
public override DateTime? LastAccessedTime
{
get { return null; }
get { throw new NotImplementedException(); }
}
public override DateTime? ArchivedTime
{
get { return null; }
get { throw new NotImplementedException(); }
}
public override bool IsEncrypted
@@ -76,5 +76,9 @@ namespace SharpCompress.Common.SevenZip
{
get { return FilePart.AsEnumerable<FilePart>(); }
}
internal override void Close()
{
}
}
}

View File

@@ -2,11 +2,18 @@
namespace SharpCompress.Common.SevenZip
{
public class SevenZipVolume : Volume
public class SevenZipVolume : GenericVolume
{
public SevenZipVolume(Stream stream, Options options)
: base(stream, options)
{
}
#if !PORTABLE && !NETFX_CORE
public SevenZipVolume(FileInfo fileInfo, Options options)
: base(fileInfo, options)
{
}
#endif
}
}

View File

@@ -25,7 +25,12 @@ namespace SharpCompress.Common.Tar.Headers
internal class TarHeader
{
internal static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
internal static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0);
internal TarHeader(EntryType entryType)
{
EntryType = entryType;
}
internal string Name { get; set; }
//internal int Mode { get; set; }
@@ -37,67 +42,74 @@ namespace SharpCompress.Common.Tar.Headers
internal DateTime LastModifiedTime { get; set; }
internal EntryType EntryType { get; set; }
internal Stream PackedStream { get; set; }
internal static bool IsPathSeparator(char ch)
{
return (ch == '\\' || ch == '/' || ch == '|'); // All the path separators I ever met.
}
internal void Write(Stream output)
{
byte[] buffer = new byte[512];
WriteOctalBytes(511, buffer, 100, 8); // file mode
WriteOctalBytes(0, buffer, 108, 8); // owner ID
WriteOctalBytes(0, buffer, 116, 8); // group ID
//Encoding.UTF8.GetBytes("magic").CopyTo(buffer, 257);
if (Name.Length > 100)
if (Name.Length > 255)
{
// Set mock filename and filetype to indicate the next block is the actual name of the file
WriteStringBytes("././@LongLink", buffer, 0, 100);
buffer[156] = (byte)EntryType.LongName;
WriteOctalBytes(Name.Length + 1, buffer, 124, 12);
throw new InvalidFormatException("UsTar fileName can not be longer thatn 255 chars");
}
byte[] buffer = new byte[512];
string name = Name;
string namePrefix = null;
if (name.Length > 100)
{
int position = Name.Length - 100;
// Find first path separator in the remaining 100 chars of the file name
while (!IsPathSeparator(Name[position]))
{
++position;
if (position == Name.Length)
{
break;
}
}
if (position == Name.Length)
{
position = Name.Length - 100;
}
namePrefix = Name.Substring(0, position);
name = Name.Substring(position, Name.Length - position);
}
Encoding.ASCII.GetBytes(name.PadRight(100, '\0')).CopyTo(buffer, 0);
WriteOctalBytes(511, buffer, 100, 8);
WriteOctalBytes(0, buffer, 108, 8);
WriteOctalBytes(0, buffer, 116, 8);
WriteOctalBytes(Size, buffer, 124, 12);
var time = (long) (LastModifiedTime - Epoch).TotalSeconds;
WriteOctalBytes(time, buffer, 136, 12);
if (namePrefix != null)
{
Encoding.ASCII.GetBytes(namePrefix).CopyTo(buffer, 347);
Encoding.ASCII.GetBytes("ustar").CopyTo(buffer, 0x101);
Encoding.ASCII.GetBytes(" ").CopyTo(buffer, 0x106);
}
else
{
WriteStringBytes(Name, buffer, 0, 100);
WriteOctalBytes(Size, buffer, 124, 12);
var time = (long)(LastModifiedTime.ToUniversalTime() - Epoch).TotalSeconds;
WriteOctalBytes(time, buffer, 136, 12);
buffer[156] = (byte)EntryType;
if (Size >= 0x1FFFFFFFF)
{
}
if (Size >= 0x1FFFFFFFF)
{
#if PORTABLE || NETFX_CORE
byte[] bytes = BitConverter.GetBytes(Utility.HostToNetworkOrder(Size));
#else
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Size));
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Size));
#endif
var bytes12 = new byte[12];
bytes.CopyTo(bytes12, 12 - bytes.Length);
bytes12[0] |= 0x80;
bytes12.CopyTo(buffer, 124);
}
var bytes12 = new byte[12];
bytes.CopyTo(bytes12, 12 - bytes.Length);
bytes12[0] |= 0x80;
bytes12.CopyTo(buffer, 124);
}
int crc = RecalculateChecksum(buffer);
WriteOctalBytes(crc, buffer, 148, 8);
output.Write(buffer, 0, buffer.Length);
if (Name.Length > 100)
{
WriteLongFilenameHeader(output);
Name = Name.Substring(0, 100);
Write(output);
}
}
private void WriteLongFilenameHeader(Stream output)
{
byte[] nameBytes = ArchiveEncoding.Default.GetBytes(Name);
output.Write(nameBytes, 0, nameBytes.Length);
// pad to multiple of 512 bytes, and make sure a terminating null is added
int numPaddingBytes = 512 - (nameBytes.Length % 512);
if (numPaddingBytes == 0)
numPaddingBytes = 512;
output.Write(new byte[numPaddingBytes], 0, numPaddingBytes);
}
internal bool Read(BinaryReader reader)
@@ -111,7 +123,7 @@ namespace SharpCompress.Common.Tar.Headers
{
throw new InvalidOperationException();
}
Name = ArchiveEncoding.Default.GetString(buffer, 0, 100).TrimNulls();
Name = Encoding.ASCII.GetString(buffer, 0, 100).TrimNulls();
//Mode = ReadASCIIInt32Base8(buffer, 100, 7);
//UserId = ReadASCIIInt32Base8(buffer, 108, 7);
@@ -131,10 +143,10 @@ namespace SharpCompress.Common.Tar.Headers
Size = ReadASCIIInt64Base8(buffer, 124, 11);
}
long unixTimeStamp = ReadASCIIInt64Base8(buffer, 136, 11);
LastModifiedTime = Epoch.AddSeconds(unixTimeStamp).ToLocalTime();
LastModifiedTime = Epoch.AddSeconds(unixTimeStamp);
Magic = ArchiveEncoding.Default.GetString(buffer, 257, 6).TrimNulls();
Magic = Encoding.ASCII.GetString(buffer, 257, 5).TrimNulls();
if (!string.IsNullOrEmpty(Magic) && "ustar".Equals(Magic))
{
@@ -142,31 +154,12 @@ namespace SharpCompress.Common.Tar.Headers
namePrefix = namePrefix.TrimNulls();
if (!string.IsNullOrEmpty(namePrefix))
{
Name = namePrefix + "/" + Name;
Name = namePrefix + Name;
}
}
if (EntryType != EntryType.LongName && Name.Length == 0)
{
return false;
}
return true;
}
private static void WriteStringBytes(string name, byte[] buffer, int offset, int length)
{
int i;
for (i = 0; i < length - 1 && i < name.Length; ++i)
{
buffer[offset + i] = (byte) name[i];
}
for (; i < length; ++i)
{
buffer[offset + i] = 0;
}
}
private static void WriteOctalBytes(long value, byte[] buffer, int offset, int length)
{
string val = Convert.ToString(value, 8);
@@ -179,16 +172,7 @@ namespace SharpCompress.Common.Tar.Headers
{
buffer[offset + i + shift] = (byte) val[i];
}
}
private static int ReadASCIIInt32Base8(byte[] buffer, int offset, int count)
{
string s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();
if (string.IsNullOrEmpty(s))
{
return 0;
}
return Convert.ToInt32(s, 8);
buffer[offset + length] = 0;
}
private static long ReadASCIIInt64Base8(byte[] buffer, int offset, int count)
@@ -201,16 +185,6 @@ namespace SharpCompress.Common.Tar.Headers
return Convert.ToInt64(s, 8);
}
private static long ReadASCIIInt64(byte[] buffer, int offset, int count)
{
string s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();
if (string.IsNullOrEmpty(s))
{
return 0;
}
return Convert.ToInt64(s);
}
internal static int RecalculateChecksum(byte[] buf)
{
// Set default value for checksum. That is 8 spaces.

View File

@@ -22,12 +22,12 @@ namespace SharpCompress.Common.Tar
get { return type; }
}
public override long Crc
public override uint Crc
{
get { return 0; }
}
public override string Key
public override string FilePath
{
get { return filePart.Header.Name; }
}
@@ -85,20 +85,41 @@ namespace SharpCompress.Common.Tar
internal static IEnumerable<TarEntry> GetEntries(StreamingMode mode, Stream stream,
CompressionType compressionType)
{
string nextHeaderName = null;
foreach (TarHeader h in TarHeaderFactory.ReadHeader(mode, stream))
{
if (h != null)
{
if (mode == StreamingMode.Seekable)
if (h.EntryType == EntryType.LongName)
{
yield return new TarEntry(new TarFilePart(h, stream), compressionType);
var memoryStream = new MemoryStream();
h.PackedStream.CopyTo(memoryStream);
memoryStream.Position = 0;
var bytes = memoryStream.ToArray();
nextHeaderName = ArchiveEncoding.Default.GetString(bytes, 0, bytes.Length).TrimNulls();
}
else
{
yield return new TarEntry(new TarFilePart(h, null), compressionType);
if (nextHeaderName != null)
{
h.Name = nextHeaderName;
nextHeaderName = null;
}
if (mode == StreamingMode.Seekable)
{
yield return new TarEntry(new TarFilePart(h, stream), compressionType);
}
else
{
yield return new TarEntry(new TarFilePart(h, null), compressionType);
}
}
}
}
}
internal override void Close()
{
}
}
}

View File

@@ -6,12 +6,12 @@ namespace SharpCompress.Common.Tar
{
internal class TarFilePart : FilePart
{
private readonly Stream seekableStream;
private Stream seekableStream;
internal TarFilePart(TarHeader header, Stream seekableStream)
{
this.seekableStream = seekableStream;
Header = header;
this.Header = header;
}
internal TarHeader Header { get; private set; }

View File

@@ -15,7 +15,7 @@ namespace SharpCompress.Common.Tar
try
{
BinaryReader reader = new BinaryReader(stream);
header = new TarHeader();
header = new TarHeader(EntryType.File);
if (!header.Read(reader))
{
yield break;

View File

@@ -5,7 +5,7 @@ namespace SharpCompress.Common.Tar
internal class TarReadOnlySubStream : Stream
{
private bool isDisposed;
private long amountRead;
private int amountRead;
public TarReadOnlySubStream(Stream stream, long bytesToRead)
{
@@ -22,7 +22,7 @@ namespace SharpCompress.Common.Tar
isDisposed = true;
if (disposing)
{
long skipBytes = amountRead % 512;
int skipBytes = this.amountRead % 512;
if (skipBytes == 0)
{
return;
@@ -33,7 +33,7 @@ namespace SharpCompress.Common.Tar
return;
}
var buffer = new byte[skipBytes];
Stream.ReadFully(buffer);
this.Stream.ReadFully(buffer);
}
}
@@ -58,48 +58,48 @@ namespace SharpCompress.Common.Tar
public override void Flush()
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override long Length
{
get { throw new System.NotSupportedException(); }
get { throw new System.NotImplementedException(); }
}
public override long Position
{
get { throw new System.NotSupportedException(); }
set { throw new System.NotSupportedException(); }
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
if (BytesLeftToRead < count)
if (this.BytesLeftToRead < count)
{
count = (int)BytesLeftToRead;
count = (int)this.BytesLeftToRead;
}
int read = Stream.Read(buffer, offset, count);
int read = this.Stream.Read(buffer, offset, count);
if (read > 0)
{
BytesLeftToRead -= read;
amountRead += read;
this.BytesLeftToRead -= read;
this.amountRead += read;
}
return read;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void SetLength(long value)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
}
}

View File

@@ -2,11 +2,18 @@
namespace SharpCompress.Common.Tar
{
public class TarVolume : Volume
public class TarVolume : GenericVolume
{
public TarVolume(Stream stream, Options options)
: base(stream, options)
{
}
#if !PORTABLE && !NETFX_CORE
public TarVolume(FileInfo fileInfo, Options options)
: base(fileInfo, options)
{
}
#endif
}
}

View File

@@ -24,18 +24,16 @@ namespace SharpCompress.Common
/// RarArchive is the first volume of a multi-part archive.
/// Only Rar 3.0 format and higher
/// </summary>
public virtual bool IsFirstVolume
{
get { return true; }
}
public abstract bool IsFirstVolume { get; }
/// <summary>
/// RarArchive is part of a multi-part archive.
/// </summary>
public virtual bool IsMultiVolume
{
get { return true; }
}
public abstract bool IsMultiVolume { get; }
#if !PORTABLE && !NETFX_CORE
public abstract FileInfo VolumeFile { get; }
#endif
private bool disposed;

View File

@@ -1,5 +1,4 @@
using System.IO;
using System.Linq;
namespace SharpCompress.Common.Zip.Headers
{
@@ -35,12 +34,6 @@ namespace SharpCompress.Common.Zip.Headers
byte[] comment = reader.ReadBytes(commentLength);
Comment = DecodeString(comment);
LoadExtra(extra);
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
if (unicodePathExtra != null)
{
Name = ((ExtraUnicodePathExtraField)unicodePathExtra).UnicodeName;
}
}
internal override void Write(BinaryWriter writer)

View File

@@ -1,8 +1,19 @@
using System.IO;
using System.Linq;
namespace SharpCompress.Common.Zip.Headers
{
internal enum ExtraDataType : ushort
{
WinZipAes = 0x9901,
}
internal class ExtraData
{
internal ExtraDataType Type { get; set; }
internal ushort Length { get; set; }
internal byte[] DataBytes { get; set; }
}
internal class LocalEntryHeader : ZipFileEntry
{
public LocalEntryHeader()
@@ -26,12 +37,6 @@ namespace SharpCompress.Common.Zip.Headers
byte[] extra = reader.ReadBytes(extraLength);
Name = DecodeString(name);
LoadExtra(extra);
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
if (unicodePathExtra!=null)
{
Name = ((ExtraUnicodePathExtraField) unicodePathExtra).UnicodeName;
}
}
internal override void Write(BinaryWriter writer)

View File

@@ -1,75 +0,0 @@
using System;
using System.Text;
namespace SharpCompress.Common.Zip.Headers
{
internal enum ExtraDataType : ushort
{
WinZipAes = 0x9901,
NotImplementedExtraData = 0xFFFF,
// Third Party Mappings
// -Info-ZIP Unicode Path Extra Field
UnicodePathExtraField = 0x7075
}
internal class ExtraData
{
internal ExtraDataType Type { get; set; }
internal ushort Length { get; set; }
internal byte[] DataBytes { get; set; }
}
internal class ExtraUnicodePathExtraField : ExtraData
{
internal byte Version
{
get { return this.DataBytes[0]; }
}
internal byte[] NameCRC32
{
get
{
var crc = new byte[4];
Buffer.BlockCopy(this.DataBytes, 1, crc, 0, 4);
return crc;
}
}
internal string UnicodeName
{
get
{
// PathNamelength = dataLength - Version(1 byte) - NameCRC32(4 bytes)
var length = this.Length - 5;
var nameStr = Encoding.UTF8.GetString(this.DataBytes, 5, length);
return nameStr;
}
}
}
internal static class LocalEntryHeaderExtraFactory
{
internal static ExtraData Create(ExtraDataType type,ushort length, byte[] extraData)
{
switch (type)
{
case ExtraDataType.UnicodePathExtraField:
return new ExtraUnicodePathExtraField()
{
Type = type,
Length = length,
DataBytes = extraData
};
default:
return new ExtraData
{
Type = type,
Length = length,
DataBytes = extraData
};
}
}
}
}

View File

@@ -13,6 +13,7 @@ namespace SharpCompress.Common.Zip.Headers
Extra = new List<ExtraData>();
}
internal bool IsDirectory
{
get { return Name.EndsWith("/"); }
@@ -24,7 +25,6 @@ namespace SharpCompress.Common.Zip.Headers
{
return Encoding.UTF8.GetString(str, 0, str.Length);
}
return ArchiveEncoding.Default.GetString(str, 0, str.Length);
}
@@ -66,19 +66,22 @@ namespace SharpCompress.Common.Zip.Headers
protected void LoadExtra(byte[] extra)
{
for (int i = 0; i < extra.Length-4;)
for (int i = 0; i < extra.Length;)
{
ExtraDataType type = (ExtraDataType) BitConverter.ToUInt16(extra, i);
if (!Enum.IsDefined(typeof (ExtraDataType), type))
{
type = ExtraDataType.NotImplementedExtraData;
return;
}
ushort length = BitConverter.ToUInt16(extra, i + 2);
byte[] data = new byte[length];
Buffer.BlockCopy(extra, i + 4, data, 0, length);
Extra.Add(LocalEntryHeaderExtraFactory.Create(type,length,data));
Extra.Add(new ExtraData
{
Type = type,
Length = length,
DataBytes = data
});
i += length + 4;
}
}

View File

@@ -55,13 +55,13 @@ namespace SharpCompress.Common.Zip
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
protected override void Dispose(bool disposing)
@@ -82,7 +82,7 @@ namespace SharpCompress.Common.Zip
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
@@ -164,17 +164,17 @@ namespace SharpCompress.Common.Zip
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}
}

View File

@@ -53,12 +53,12 @@ namespace SharpCompress.Common.Zip
}
}
public override long Crc
public override uint Crc
{
get { return filePart.Header.Crc; }
}
public override string Key
public override string FilePath
{
get { return filePart.Header.Name; }
}
@@ -112,5 +112,9 @@ namespace SharpCompress.Common.Zip
{
get { return filePart.AsEnumerable<FilePart>(); }
}
internal override void Close()
{
}
}
}

View File

@@ -2,13 +2,20 @@
namespace SharpCompress.Common.Zip
{
public class ZipVolume : Volume
public class ZipVolume : GenericVolume
{
public ZipVolume(Stream stream, Options options)
: base(stream, options)
{
}
#if !PORTABLE && !NETFX_CORE
public ZipVolume(FileInfo fileInfo, Options options)
: base(fileInfo, options)
{
}
#endif
public string Comment { get; internal set; }
}
}

View File

@@ -174,7 +174,7 @@ namespace SharpCompress.Compressor.Deflate
/// </summary>
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
/// <summary>
@@ -198,7 +198,7 @@ namespace SharpCompress.Compressor.Deflate
return _baseStream._z.TotalBytesIn;
return 0;
}
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
@@ -275,7 +275,7 @@ namespace SharpCompress.Compressor.Deflate
/// <returns>irrelevant!</returns>
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>
@@ -284,7 +284,7 @@ namespace SharpCompress.Compressor.Deflate
/// <param name="value">this is irrelevant, since it will always throw!</param>
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>

View File

@@ -163,7 +163,7 @@ namespace SharpCompress.Compressor.Deflate
/// </summary>
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
/// <summary>
@@ -188,7 +188,7 @@ namespace SharpCompress.Compressor.Deflate
return 0;
}
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
@@ -286,7 +286,7 @@ namespace SharpCompress.Compressor.Deflate
/// <returns>irrelevant!</returns>
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>
@@ -295,7 +295,7 @@ namespace SharpCompress.Compressor.Deflate
/// <param name="value">irrelevant; this method will always throw!</param>
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>

View File

@@ -339,7 +339,7 @@ namespace SharpCompress.Compressor.Deflate
public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
//_outStream.Seek(offset, origin);
}
@@ -573,8 +573,8 @@ namespace SharpCompress.Compressor.Deflate
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
internal enum StreamMode

View File

@@ -166,7 +166,7 @@ namespace SharpCompress.Compressor.Deflate
/// </summary>
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
/// <summary>
@@ -191,7 +191,7 @@ namespace SharpCompress.Compressor.Deflate
return 0;
}
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
@@ -264,7 +264,7 @@ namespace SharpCompress.Compressor.Deflate
/// </summary>
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>
@@ -272,7 +272,7 @@ namespace SharpCompress.Compressor.Deflate
/// </summary>
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
/// <summary>

View File

@@ -91,7 +91,7 @@ namespace SharpCompress.Compressor.Filters
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
@@ -102,7 +102,7 @@ namespace SharpCompress.Compressor.Filters
public override long Position
{
get { return position; }
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -203,17 +203,17 @@ namespace SharpCompress.Compressor.Filters
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}
}

View File

@@ -51,7 +51,7 @@ namespace SharpCompress.Compressor.Filters
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
@@ -62,7 +62,7 @@ namespace SharpCompress.Compressor.Filters
public override long Position
{
get { return baseStream.Position; }
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -135,12 +135,12 @@ namespace SharpCompress.Compressor.Filters
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)

View File

@@ -39,7 +39,7 @@ namespace SharpCompress.Compressor.LZMA
byte[] password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword());
byte[] key = InitKey(numCyclesPower, salt, password);
using (var aes = Rijndael.Create())
using (var aes = Aes.Create())
{
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;

View File

@@ -25,33 +25,33 @@ namespace SharpCompress.Compressor.LZMA
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}

View File

@@ -160,7 +160,7 @@ namespace SharpCompress.Compressor.LZMA
public override long Position
{
get { return position; }
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -286,12 +286,12 @@ namespace SharpCompress.Compressor.LZMA
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)

View File

@@ -159,18 +159,18 @@ namespace SharpCompress.Compressor.LZMA.Utilites
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -193,17 +193,17 @@ namespace SharpCompress.Compressor.LZMA.Utilites
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}
}

View File

@@ -85,13 +85,13 @@ namespace SharpCompress.Compressor.PPMd
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { return position; }
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -125,12 +125,12 @@ namespace SharpCompress.Compressor.PPMd
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)

View File

@@ -15,12 +15,12 @@ namespace SharpCompress.Compressor.Rar
private IEnumerator<RarFilePart> filePartEnumerator;
private Stream currentStream;
private readonly IExtractionListener streamListener;
private readonly IStreamListener streamListener;
private long currentPartTotalReadBytes;
private long currentEntryTotalReadBytes;
internal MultiVolumeReadOnlyStream(IEnumerable<RarFilePart> parts, IExtractionListener streamListener)
internal MultiVolumeReadOnlyStream(IEnumerable<RarFilePart> parts, IStreamListener streamListener)
{
this.streamListener = streamListener;
@@ -67,33 +67,27 @@ namespace SharpCompress.Compressor.Rar
public override int Read(byte[] buffer, int offset, int count)
{
int totalRead = 0;
int currentOffset = offset;
int currentCount = count;
while (currentCount > 0)
while (count > 0)
{
int readSize = currentCount;
if (currentCount > maxPosition - currentPosition)
int readSize = count;
if (count > maxPosition - currentPosition)
{
readSize = (int) (maxPosition - currentPosition);
}
int read = currentStream.Read(buffer, currentOffset, readSize);
int read = currentStream.Read(buffer, offset, readSize);
if (read < 0)
{
throw new EndOfStreamException();
}
currentPosition += read;
currentOffset += read;
currentCount -= read;
offset += read;
count -= read;
totalRead += read;
if (((maxPosition - currentPosition) == 0)
&& filePartEnumerator.Current.FileHeader.FileFlags.HasFlag(FileFlags.SPLIT_AFTER))
{
if (filePartEnumerator.Current.FileHeader.Salt != null)
{
throw new InvalidFormatException("Sharpcompress currently does not support multi-volume decryption.");
}
string fileName = filePartEnumerator.Current.FileHeader.FileName;
if (!filePartEnumerator.MoveNext())
{
@@ -130,33 +124,33 @@ namespace SharpCompress.Compressor.Rar
public override void Flush()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}
}

View File

@@ -8,7 +8,7 @@ namespace SharpCompress.Compressor.Rar
{
private readonly Unpack unpack;
private readonly FileHeader fileHeader;
private readonly Stream readStream;
private Stream readStream;
private bool fetch = false;
@@ -45,30 +45,22 @@ namespace SharpCompress.Compressor.Rar
public override bool CanRead
{
get
{
return true;
}
get { throw new NotImplementedException(); }
}
public override bool CanSeek
{
get
{
return false;
}
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get
{
return false;
}
get { throw new NotImplementedException(); }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
@@ -79,7 +71,7 @@ namespace SharpCompress.Compressor.Rar
public override long Position
{
get { return fileHeader.UncompressedSize - unpack.DestSize; }
set { throw new NotSupportedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -109,20 +101,18 @@ namespace SharpCompress.Compressor.Rar
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
if (!fetch)
{
throw new NotSupportedException();
}
throw new NotImplementedException();
if (outCount > 0)
{
int toCopy = outCount < count ? outCount : count;

View File

@@ -1,15 +0,0 @@
using System;
namespace SharpCompress
{
internal static class EnumExtensions
{
public static bool HasFlag(this Enum enumRef, Enum flag)
{
long value = Convert.ToInt64(enumRef);
long flagVal = Convert.ToInt64(flag);
return (value & flagVal) == flagVal;
}
}
}

View File

@@ -6,7 +6,7 @@ namespace SharpCompress.IO
{
public class ReadOnlyAppendingStream : Stream
{
private readonly Queue<Stream> streams;
private Queue<Stream> streams;
private Stream current;
public ReadOnlyAppendingStream(IEnumerable<Stream> streams)
@@ -21,12 +21,12 @@ namespace SharpCompress.IO
public override bool CanSeek
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { return false; }
get { throw new NotImplementedException(); }
}
public override void Flush()

View File

@@ -35,28 +35,28 @@ namespace SharpCompress.IO
public override long Length
{
get { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)

View File

@@ -6,9 +6,9 @@ namespace SharpCompress.IO
internal class ListeningStream : Stream
{
private long currentEntryTotalReadBytes;
private IExtractionListener listener;
private IStreamListener listener;
public ListeningStream(IExtractionListener listener, Stream stream)
public ListeningStream(IStreamListener listener, Stream stream)
{
Stream = stream;
this.listener = listener;

View File

@@ -21,22 +21,25 @@ namespace SharpCompress.IO
public override int Read()
{
throw new NotSupportedException();
CurrentReadByteCount += 4;
return base.Read();
}
public override int Read(byte[] buffer, int index, int count)
{
throw new NotSupportedException();
CurrentReadByteCount += count;
return base.Read(buffer, index, count);
}
public override int Read(char[] buffer, int index, int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override bool ReadBoolean()
{
return BitConverter.ToBoolean(ReadBytes(1), 0);
CurrentReadByteCount++;
return base.ReadBoolean();
}
public override byte ReadByte()
@@ -47,22 +50,17 @@ namespace SharpCompress.IO
public override byte[] ReadBytes(int count)
{
CurrentReadByteCount += count;
var bytes = base.ReadBytes(count);
if (bytes.Length != count)
{
throw new EndOfStreamException(string.Format("Could not read the requested amount of bytes. End of stream reached. Requested: {0} Read: {1}", count, bytes.Length));
}
return bytes;
return base.ReadBytes(count);
}
public override char ReadChar()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override char[] ReadChars(int count)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
#if !PORTABLE
@@ -115,7 +113,7 @@ namespace SharpCompress.IO
public override string ReadString()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public override ushort ReadUInt16()

View File

@@ -48,18 +48,18 @@ namespace SharpCompress.IO
public override void Flush()
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override long Length
{
get { throw new System.NotSupportedException(); }
get { throw new System.NotImplementedException(); }
}
public override long Position
{
get { throw new System.NotSupportedException(); }
set { throw new System.NotSupportedException(); }
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
@@ -78,17 +78,17 @@ namespace SharpCompress.IO
public override long Seek(long offset, SeekOrigin origin)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void SetLength(long value)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
}
}

View File

@@ -84,12 +84,12 @@ namespace SharpCompress.IO
public override void Flush()
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override long Length
{
get { throw new System.NotSupportedException(); }
get { throw new System.NotImplementedException(); }
}
public override long Position
@@ -147,17 +147,17 @@ namespace SharpCompress.IO
public override long Seek(long offset, SeekOrigin origin)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void SetLength(long value)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new System.NotSupportedException();
throw new System.NotImplementedException();
}
}
}

View File

@@ -72,7 +72,7 @@ namespace SharpCompress
public void Reset()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
#endregion
@@ -96,12 +96,12 @@ namespace SharpCompress
public void Add(T item)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public void Clear()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public bool Contains(T item)
@@ -132,7 +132,7 @@ namespace SharpCompress
public bool Remove(T item)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
#endregion

View File

@@ -14,12 +14,12 @@ namespace SharpCompress
public void Add(T item)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public void Clear()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public bool Contains(T item)
@@ -44,7 +44,7 @@ namespace SharpCompress
public bool Remove(T item)
{
throw new NotSupportedException();
throw new NotImplementedException();
}
public IEnumerator<T> GetEnumerator()
@@ -54,7 +54,7 @@ namespace SharpCompress
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotSupportedException();
throw new NotImplementedException();
}
}
}

Some files were not shown because too many files have changed in this diff Show More