Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-02-22 18:57:51 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-02-22 18:57:51 +0300
commit7e377a24fa91a08c0230d3883e1e4028a7d64381 (patch)
treed9ecad9a9aba694fcfd37aaff9ba8c3646554964 /SevenZip
parent34a4ceaa2b4a00c4dd6269bf3012abb77dcf25e4 (diff)
Compression
Diffstat (limited to 'SevenZip')
-rw-r--r--SevenZip/ArchiveEmulationStreamProxy.cs6
-rw-r--r--SevenZip/ArchiveExtractCallback.cs1
-rw-r--r--SevenZip/ArchiveOpenCallback.cs1
-rw-r--r--SevenZip/ArchiveUpdateCallback.cs4
-rw-r--r--SevenZip/COM.cs1
-rw-r--r--SevenZip/Common.cs1
-rw-r--r--SevenZip/EventArgs.cs1
-rw-r--r--SevenZip/Exceptions.cs1
-rw-r--r--SevenZip/FileSignatureChecker.cs1
-rw-r--r--SevenZip/Formats.cs1
-rw-r--r--SevenZip/LibraryFeature.cs4
-rw-r--r--SevenZip/LibraryManager.cs1
-rw-r--r--SevenZip/LzmaDecodeStream.cs4
-rw-r--r--SevenZip/LzmaEncodeStream.cs308
-rw-r--r--SevenZip/LzmaProgressCallback.cs4
-rw-r--r--SevenZip/NativeMethods.cs1
-rw-r--r--SevenZip/SevenZipCompressor.cs2058
-rw-r--r--SevenZip/SevenZipCompressorAsynchronous.cs709
-rw-r--r--SevenZip/SevenZipExtractor.cs1
-rw-r--r--SevenZip/SevenZipExtractorAsynchronous.cs2
-rw-r--r--SevenZip/SevenZipSfx.cs502
-rw-r--r--SevenZip/StreamWrappers.cs1
22 files changed, 3612 insertions, 1 deletions
diff --git a/SevenZip/ArchiveEmulationStreamProxy.cs b/SevenZip/ArchiveEmulationStreamProxy.cs
index c0bdaed2..871a76f7 100644
--- a/SevenZip/ArchiveEmulationStreamProxy.cs
+++ b/SevenZip/ArchiveEmulationStreamProxy.cs
@@ -1,4 +1,8 @@
-using System.IO;
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
+using System.IO;
using System;
namespace SevenZip
diff --git a/SevenZip/ArchiveExtractCallback.cs b/SevenZip/ArchiveExtractCallback.cs
index e7aced62..ed942f31 100644
--- a/SevenZip/ArchiveExtractCallback.cs
+++ b/SevenZip/ArchiveExtractCallback.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/ArchiveOpenCallback.cs b/SevenZip/ArchiveOpenCallback.cs
index dc24a6d2..415eace2 100644
--- a/SevenZip/ArchiveOpenCallback.cs
+++ b/SevenZip/ArchiveOpenCallback.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/ArchiveUpdateCallback.cs b/SevenZip/ArchiveUpdateCallback.cs
index a9f838e7..d9872a57 100644
--- a/SevenZip/ArchiveUpdateCallback.cs
+++ b/SevenZip/ArchiveUpdateCallback.cs
@@ -14,6 +14,10 @@
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/SevenZip/COM.cs b/SevenZip/COM.cs
index d4846959..94fa4b61 100644
--- a/SevenZip/COM.cs
+++ b/SevenZip/COM.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/Common.cs b/SevenZip/Common.cs
index 6a629868..923a3e37 100644
--- a/SevenZip/Common.cs
+++ b/SevenZip/Common.cs
@@ -17,6 +17,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/EventArgs.cs b/SevenZip/EventArgs.cs
index d31fd24f..cadfbea7 100644
--- a/SevenZip/EventArgs.cs
+++ b/SevenZip/EventArgs.cs
@@ -17,6 +17,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.IO;
diff --git a/SevenZip/Exceptions.cs b/SevenZip/Exceptions.cs
index 3bbfb443..082fcbd9 100644
--- a/SevenZip/Exceptions.cs
+++ b/SevenZip/Exceptions.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
#if !WINCE
diff --git a/SevenZip/FileSignatureChecker.cs b/SevenZip/FileSignatureChecker.cs
index 0251a3b0..e2fec0b3 100644
--- a/SevenZip/FileSignatureChecker.cs
+++ b/SevenZip/FileSignatureChecker.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.IO;
diff --git a/SevenZip/Formats.cs b/SevenZip/Formats.cs
index 9aff7eda..94cfc978 100644
--- a/SevenZip/Formats.cs
+++ b/SevenZip/Formats.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/LibraryFeature.cs b/SevenZip/LibraryFeature.cs
index d59c19d0..f3a78970 100644
--- a/SevenZip/LibraryFeature.cs
+++ b/SevenZip/LibraryFeature.cs
@@ -15,6 +15,10 @@
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
using System;
namespace SevenZip
diff --git a/SevenZip/LibraryManager.cs b/SevenZip/LibraryManager.cs
index efee920f..035d732c 100644
--- a/SevenZip/LibraryManager.cs
+++ b/SevenZip/LibraryManager.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/LzmaDecodeStream.cs b/SevenZip/LzmaDecodeStream.cs
index 16946d5a..506811aa 100644
--- a/SevenZip/LzmaDecodeStream.cs
+++ b/SevenZip/LzmaDecodeStream.cs
@@ -14,6 +14,10 @@
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
using System;
using System.IO;
using SevenZip.Sdk.Compression.Lzma;
diff --git a/SevenZip/LzmaEncodeStream.cs b/SevenZip/LzmaEncodeStream.cs
new file mode 100644
index 00000000..770585c7
--- /dev/null
+++ b/SevenZip/LzmaEncodeStream.cs
@@ -0,0 +1,308 @@
+/* This file is part of SevenZipSharp.
+
+ SevenZipSharp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SevenZipSharp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
+using System;
+using System.IO;
+using SevenZip.Sdk.Compression.Lzma;
+
+namespace SevenZip
+{
+#if LZMA_STREAM
+#if COMPRESS
+ /// <summary>
+ /// The stream which compresses data with LZMA on the fly.
+ /// </summary>
+ public class LzmaEncodeStream : Stream
+ {
+ private const int MAX_BUFFER_CAPACITY = 1 << 30; //1 Gb
+ private readonly MemoryStream _buffer = new MemoryStream();
+ private readonly int _bufferCapacity = 1 << 18; //256 kb
+ private readonly bool _ownOutput;
+ private bool _disposed;
+ private Encoder _lzmaEncoder;
+ private Stream _output;
+
+ /// <summary>
+ /// Initializes a new instance of the LzmaEncodeStream class.
+ /// </summary>
+ public LzmaEncodeStream()
+ {
+ _output = new MemoryStream();
+ _ownOutput = true;
+ Init();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the LzmaEncodeStream class.
+ /// </summary>
+ /// <param name="bufferCapacity">The buffer size. The bigger size, the better compression.</param>
+ public LzmaEncodeStream(int bufferCapacity)
+ {
+ _output = new MemoryStream();
+ _ownOutput = true;
+ if (bufferCapacity > MAX_BUFFER_CAPACITY)
+ {
+ throw new ArgumentException("Too large capacity.", "bufferCapacity");
+ }
+ _bufferCapacity = bufferCapacity;
+ Init();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the LzmaEncodeStream class.
+ /// </summary>
+ /// <param name="outputStream">An output stream which supports writing.</param>
+ public LzmaEncodeStream(Stream outputStream)
+ {
+ if (!outputStream.CanWrite)
+ {
+ throw new ArgumentException("The specified stream can not write.", "outputStream");
+ }
+ _output = outputStream;
+ Init();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the LzmaEncodeStream class.
+ /// </summary>
+ /// <param name="outputStream">An output stream which supports writing.</param>
+ /// <param name="bufferCapacity">A buffer size. The bigger size, the better compression.</param>
+ public LzmaEncodeStream(Stream outputStream, int bufferCapacity)
+ {
+ if (!outputStream.CanWrite)
+ {
+ throw new ArgumentException("The specified stream can not write.", "outputStream");
+ }
+ _output = outputStream;
+ if (bufferCapacity > 1 << 30)
+ {
+ throw new ArgumentException("Too large capacity.", "bufferCapacity");
+ }
+ _bufferCapacity = bufferCapacity;
+ Init();
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports reading.
+ /// </summary>
+ public override bool CanRead
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports seeking.
+ /// </summary>
+ public override bool CanSeek
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports writing.
+ /// </summary>
+ public override bool CanWrite
+ {
+ get
+ {
+ DisposedCheck();
+ return _buffer.CanWrite;
+ }
+ }
+
+ /// <summary>
+ /// Gets the length in bytes of the output stream.
+ /// </summary>
+ public override long Length
+ {
+ get
+ {
+ DisposedCheck();
+ if (_output.CanSeek)
+ {
+ return _output.Length;
+ }
+ return _buffer.Position;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the position within the output stream.
+ /// </summary>
+ public override long Position
+ {
+ get
+ {
+ DisposedCheck();
+ if (_output.CanSeek)
+ {
+ return _output.Position;
+ }
+ return _buffer.Position;
+ }
+ set
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ private void Init()
+ {
+ _buffer.Capacity = _bufferCapacity;
+ SevenZipCompressor.LzmaDictionarySize = _bufferCapacity;
+ _lzmaEncoder = new Encoder();
+ SevenZipCompressor.WriteLzmaProperties(_lzmaEncoder);
+ }
+
+ /// <summary>
+ /// Checked whether the class was disposed.
+ /// </summary>
+ /// <exception cref="System.ObjectDisposedException" />
+ private void DisposedCheck()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException("SevenZipExtractor");
+ }
+ }
+
+ private void WriteChunk()
+ {
+ _lzmaEncoder.WriteCoderProperties(_output);
+ long streamSize = _buffer.Position;
+ if (_buffer.Length != _buffer.Position)
+ {
+ _buffer.SetLength(_buffer.Position);
+ }
+ _buffer.Position = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ _output.WriteByte((byte) (streamSize >> (8*i)));
+ }
+ _lzmaEncoder.Code(_buffer, _output, -1, -1, null);
+ _buffer.Position = 0;
+ }
+
+ /// <summary>
+ /// Converts the LzmaEncodeStream to the LzmaDecodeStream to read data.
+ /// </summary>
+ /// <returns></returns>
+ public LzmaDecodeStream ToDecodeStream()
+ {
+ DisposedCheck();
+ Flush();
+ return new LzmaDecodeStream(_output);
+ }
+
+ /// <summary>
+ /// Clears all buffers for this stream and causes any buffered data to be compressed and written.
+ /// </summary>
+ public override void Flush()
+ {
+ DisposedCheck();
+ WriteChunk();
+ }
+
+ /// <summary>
+ /// Releases all unmanaged resources used by LzmaEncodeStream.
+ /// </summary>
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing)
+ {
+ Flush();
+ _buffer.Close();
+ if (_ownOutput)
+ {
+ _output.Dispose();
+ }
+ _output = null;
+ }
+ _disposed = true;
+ }
+ }
+
+ /// <summary>
+ /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+ /// </summary>
+ /// <param name="buffer">An array of bytes.</param>
+ /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+ /// <param name="count">The maximum number of bytes to be read from the current stream.</param>
+ /// <returns>The total number of bytes read into the buffer.</returns>
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ DisposedCheck();
+ throw new NotSupportedException();
+ }
+
+ /// <summary>
+ /// Sets the position within the current stream.
+ /// </summary>
+ /// <param name="offset">A byte offset relative to the origin parameter.</param>
+ /// <param name="origin">A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position.</param>
+ /// <returns>The new position within the current stream.</returns>
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ DisposedCheck();
+ throw new NotSupportedException();
+ }
+
+ /// <summary>
+ /// Sets the length of the current stream.
+ /// </summary>
+ /// <param name="value">The desired length of the current stream in bytes.</param>
+ public override void SetLength(long value)
+ {
+ DisposedCheck();
+ throw new NotSupportedException();
+ }
+
+ /// <summary>
+ /// Writes a sequence of bytes to the current stream and compresses it if necessary.
+ /// </summary>
+ /// <param name="buffer">An array of bytes.</param>
+ /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+ /// <param name="count">The maximum number of bytes to be read from the current stream.</param>
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ DisposedCheck();
+ int dataLength = Math.Min(buffer.Length - offset, count);
+ while (_buffer.Position + dataLength >= _bufferCapacity)
+ {
+ int length = _bufferCapacity - (int) _buffer.Position;
+ _buffer.Write(buffer, offset, length);
+ offset = length + offset;
+ dataLength -= length;
+ WriteChunk();
+ }
+ _buffer.Write(buffer, offset, dataLength);
+ }
+ }
+#endif
+#endif
+} \ No newline at end of file
diff --git a/SevenZip/LzmaProgressCallback.cs b/SevenZip/LzmaProgressCallback.cs
index fee8c7ab..940876ab 100644
--- a/SevenZip/LzmaProgressCallback.cs
+++ b/SevenZip/LzmaProgressCallback.cs
@@ -14,6 +14,10 @@
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
using System;
using SevenZip.Sdk;
diff --git a/SevenZip/NativeMethods.cs b/SevenZip/NativeMethods.cs
index 70c794a6..e5c75d50 100644
--- a/SevenZip/NativeMethods.cs
+++ b/SevenZip/NativeMethods.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Runtime.InteropServices;
diff --git a/SevenZip/SevenZipCompressor.cs b/SevenZip/SevenZipCompressor.cs
new file mode 100644
index 00000000..fba10be7
--- /dev/null
+++ b/SevenZip/SevenZipCompressor.cs
@@ -0,0 +1,2058 @@
+/* This file is part of SevenZipSharp.
+
+ SevenZipSharp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SevenZipSharp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+#if DOTNET20
+using System.Threading;
+#else
+using System.Linq;
+#endif
+using System.Runtime.InteropServices;
+#if !WINCE
+using System.Security.Permissions;
+#endif
+using SevenZip.Sdk;
+using SevenZip.Sdk.Compression.Lzma;
+#if MONO
+using SevenZip.Mono.COM;
+#endif
+
+namespace SevenZip
+{
+#if COMPRESS
+ /// <summary>
+ /// Class to pack data into archives supported by 7-Zip.
+ /// </summary>
+ /// <example>
+ /// var compr = new SevenZipCompressor();
+ /// compr.CompressDirectory(@"C:\Dir", @"C:\Archive.7z");
+ /// </example>
+ public sealed partial class SevenZipCompressor
+#if UNMANAGED
+ : SevenZipBase
+#endif
+ {
+#if UNMANAGED
+ #region Fields
+ private bool _compressingFilesOnDisk;
+ /// <summary>
+ /// Gets or sets the archiving compression level.
+ /// </summary>
+ public CompressionLevel CompressionLevel { get; set; }
+ private OutArchiveFormat _archiveFormat = OutArchiveFormat.SevenZip;
+ private CompressionMethod _compressionMethod = CompressionMethod.Default;
+ /// <summary>
+ /// Gets the custom compression parameters - for advanced users only.
+ /// </summary>
+ public Dictionary<string, string> CustomParameters { get; private set; }
+ private int _volumeSize;
+ private string _archiveName;
+ /// <summary>
+ /// Gets or sets the value indicating whether to include empty directories to archives. Default is true.
+ /// </summary>
+ public bool IncludeEmptyDirectories { get; set; }
+ /// <summary>
+ /// Gets or sets the value indicating whether to preserve the directory root for CompressDirectory.
+ /// </summary>
+ public bool PreserveDirectoryRoot { get; set; }
+ /// <summary>
+ /// Gets or sets the value indicating whether to preserve the directory structure.
+ /// </summary>
+ public bool DirectoryStructure { get; set; }
+ private bool _directoryCompress;
+ /// <summary>
+ /// Gets or sets the compression mode.
+ /// </summary>
+ public CompressionMode CompressionMode { get; set; }
+ private UpdateData _updateData;
+ private uint _oldFilesCount;
+ /// <summary>
+ /// Gets or sets the value indicating whether to encrypt 7-Zip archive headers.
+ /// </summary>
+ public bool EncryptHeaders { get; set; }
+ /// <summary>
+ /// Gets or sets the value indicating whether to compress files only open for writing.
+ /// </summary>
+ public bool ScanOnlyWritable { get; set; }
+ /// <summary>
+ /// Gets or sets the encryption method for zip archives.
+ /// </summary>
+ public ZipEncryptionMethod ZipEncryptionMethod { get; set; }
+ /// <summary>
+ /// Gets or sets the temporary folder path.
+ /// </summary>
+ public string TempFolderPath { get; set; }
+ /// <summary>
+ /// Gets or sets the default archive item name used when an item to be compressed has no name,
+ /// for example, when you compress a MemoryStream instance.
+ /// </summary>
+ public string DefaultItemName { get; set; }
+ /// <summary>
+ /// Gets or sets the value indicating whether to compress as fast as possible, without calling events.
+ /// </summary>
+ public bool FastCompression { get; set; }
+ #endregion
+#endif
+ private static volatile int _lzmaDictionarySize = 1 << 22;
+
+#if UNMANAGED
+
+ private void CommonInit()
+ {
+ DirectoryStructure = true;
+ IncludeEmptyDirectories = true;
+ CompressionLevel = CompressionLevel.Normal;
+ CompressionMode = CompressionMode.Create;
+ ZipEncryptionMethod = ZipEncryptionMethod.ZipCrypto;
+ CustomParameters = new Dictionary<string, string>();
+ _updateData = new UpdateData();
+ DefaultItemName = "default";
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the SevenZipCompressor class.
+ /// </summary>
+ public SevenZipCompressor()
+ {
+ try
+ {
+#if !WINCE
+ TempFolderPath = Path.GetTempPath();
+ //TempFolderPath = Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.User);
+#else
+ TempFolderPath = "Temp";
+#endif
+ }
+ catch (System.Security.SecurityException) // Registry access is not allowed, etc.
+ {
+ /*throw new SevenZipCompressionFailedException(
+ "Attempted to get TEMP environment variable but registry access was not allowed (security settings on your machine). You must call SevenZipCompressor constructor overload with your own temporary path.");
+ */
+ throw new SevenZipCompressionFailedException(
+ "Path.GetTempPath() threw a System.Security.SecurityException. You must call SevenZipCompressor constructor overload with your own temporary path.");
+ }
+ CommonInit();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the SevenZipCompressor class.
+ /// </summary>
+ /// <param name="temporaryPath">Your own temporary path (default is set in the parameterless constructor overload.)</param>
+ public SevenZipCompressor(string temporaryPath)
+ {
+ TempFolderPath = temporaryPath;
+ if (!Directory.Exists(TempFolderPath))
+ {
+ try
+ {
+ Directory.CreateDirectory(TempFolderPath);
+ }
+ catch (Exception)
+ {
+ throw new SevenZipCompressionFailedException("The specified temporary path is invalid.");
+ }
+ }
+ CommonInit();
+ }
+#endif
+
+ /// <summary>
+ /// Checks if the specified stream supports compression.
+ /// </summary>
+ /// <param name="stream">The stream to check.</param>
+ private static void ValidateStream(Stream stream)
+ {
+ if (!stream.CanWrite || !stream.CanSeek)
+ {
+ throw new ArgumentException("The specified stream can not seek or is not writable.", "stream");
+ }
+ }
+
+#if UNMANAGED
+
+ #region Private functions
+
+ private IOutArchive MakeOutArchive(IInStream inArchiveStream)
+ {
+ IInArchive inArchive = SevenZipLibraryManager.InArchive(
+ Formats.InForOutFormats[_archiveFormat], this);
+ using (ArchiveOpenCallback openCallback = GetArchiveOpenCallback())
+ {
+ ulong checkPos = 1 << 15;
+ if (inArchive.Open(inArchiveStream, ref checkPos, openCallback) != (int)OperationResult.Ok)
+ {
+ if (
+ !ThrowException(null, new SevenZipArchiveException("Can not update the archive: Open() failed.")))
+ {
+ return null;
+ }
+ }
+ _oldFilesCount = inArchive.GetNumberOfItems();
+ }
+ return (IOutArchive)inArchive;
+ }
+
+ /// <summary>
+ /// Guaranties the correct work of the SetCompressionProperties function
+ /// </summary>
+ /// <param name="method">The compression method to check</param>
+ /// <returns>The value indicating whether the specified method is valid for the current ArchiveFormat</returns>
+ private bool MethodIsValid(CompressionMethod method)
+ {
+ if (method == CompressionMethod.Default)
+ {
+ return true;
+ }
+ switch (_archiveFormat)
+ {
+ case OutArchiveFormat.Zip:
+ return method != CompressionMethod.Ppmd;
+ case OutArchiveFormat.GZip:
+ return method == CompressionMethod.Deflate;
+ case OutArchiveFormat.BZip2:
+ return method == CompressionMethod.BZip2;
+ case OutArchiveFormat.SevenZip:
+ return method != CompressionMethod.Deflate && method != CompressionMethod.Deflate64;
+ case OutArchiveFormat.Tar:
+ return method == CompressionMethod.Copy;
+ default:
+ return true;
+ }
+ }
+
+ private bool SwitchIsInCustomParameters(string name)
+ {
+ return CustomParameters.ContainsKey(name);
+ }
+
+ /// <summary>
+ /// Sets the compression properties
+ /// </summary>
+ private void SetCompressionProperties()
+ {
+ switch (_archiveFormat)
+ {
+ case OutArchiveFormat.Tar:
+ break;
+ default:
+ ISetProperties setter = CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null
+ ? (ISetProperties)SevenZipLibraryManager.OutArchive(
+ _archiveFormat, this)
+ : (ISetProperties)SevenZipLibraryManager.InArchive(
+ Formats.InForOutFormats[_archiveFormat], this);
+ if (setter == null)
+ {
+ if (!ThrowException(null,
+ new CompressionFailedException(
+ "The specified archive format is unsupported.")))
+ {
+ return;
+ }
+ }
+ if (_volumeSize > 0 && ArchiveFormat != OutArchiveFormat.SevenZip)
+ {
+ throw new CompressionFailedException("Unfortunately, the creation of multivolume non-7Zip archives is not implemented. It will be one day, though.");
+ }
+ if (CustomParameters.ContainsKey("x") || CustomParameters.ContainsKey("m"))
+ {
+ if (
+ !ThrowException(null,
+ new CompressionFailedException(
+ "The specified compression parameters are invalid.")))
+ {
+ return;
+ }
+ }
+ var names = new List<IntPtr>(2 + CustomParameters.Count);
+ var values = new List<PropVariant>(2 + CustomParameters.Count);
+#if !WINCE
+ var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
+ sp.Demand();
+#endif
+ #region Initialize compression properties
+
+ if (_compressionMethod == CompressionMethod.Default)
+ {
+ names.Add(Marshal.StringToBSTR("x"));
+ values.Add(new PropVariant());
+ foreach (var pair in CustomParameters)
+ {
+ names.Add(Marshal.StringToBSTR(pair.Key));
+ var pv = new PropVariant();
+ if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d")
+ {
+ pv.VarType = VarEnum.VT_UI4;
+ pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ pv.VarType = VarEnum.VT_BSTR;
+ pv.Value = Marshal.StringToBSTR(pair.Value);
+ }
+ values.Add(pv);
+ }
+ }
+ else
+ {
+ names.Add(Marshal.StringToBSTR("x"));
+ names.Add(_archiveFormat == OutArchiveFormat.Zip
+ ? Marshal.StringToBSTR("m")
+ : Marshal.StringToBSTR("0"));
+ values.Add(new PropVariant());
+ var pv = new PropVariant
+ {
+ VarType = VarEnum.VT_BSTR,
+ Value = Marshal.StringToBSTR(Formats.MethodNames[_compressionMethod])
+ };
+ values.Add(pv);
+ foreach (var pair in CustomParameters)
+ {
+ names.Add(Marshal.StringToBSTR(pair.Key));
+ pv = new PropVariant();
+ if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d")
+ {
+ pv.VarType = VarEnum.VT_UI4;
+ pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ pv.VarType = VarEnum.VT_BSTR;
+ pv.Value = Marshal.StringToBSTR(pair.Value);
+ }
+ values.Add(pv);
+ }
+ }
+
+ #endregion
+
+ #region Set compression level
+
+ PropVariant clpv = values[0];
+ clpv.VarType = VarEnum.VT_UI4;
+ switch (CompressionLevel)
+ {
+ case CompressionLevel.None:
+ clpv.UInt32Value = 0;
+ break;
+ case CompressionLevel.Fast:
+ clpv.UInt32Value = 1;
+ break;
+ case CompressionLevel.Low:
+ clpv.UInt32Value = 3;
+ break;
+ case CompressionLevel.Normal:
+ clpv.UInt32Value = 5;
+ break;
+ case CompressionLevel.High:
+ clpv.UInt32Value = 7;
+ break;
+ case CompressionLevel.Ultra:
+ clpv.UInt32Value = 9;
+ break;
+ }
+ values[0] = clpv;
+
+ #endregion
+
+ #region Encrypt headers
+
+ if (EncryptHeaders && _archiveFormat == OutArchiveFormat.SevenZip &&
+ !SwitchIsInCustomParameters("he"))
+ {
+ names.Add(Marshal.StringToBSTR("he"));
+ var tmp = new PropVariant { VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR("on") };
+ values.Add(tmp);
+ }
+
+ #endregion
+
+ #region Zip Encryption
+
+ if (_archiveFormat == OutArchiveFormat.Zip && ZipEncryptionMethod != ZipEncryptionMethod.ZipCrypto &&
+ !SwitchIsInCustomParameters("em"))
+ {
+ names.Add(Marshal.StringToBSTR("em"));
+ var tmp = new PropVariant
+ {
+ VarType = VarEnum.VT_BSTR,
+ Value = Marshal.StringToBSTR(
+#if !WINCE
+Enum.GetName(typeof(ZipEncryptionMethod), ZipEncryptionMethod))
+#else
+ OpenNETCF.Enum2.GetName(typeof (ZipEncryptionMethod), ZipEncryptionMethod))
+#endif
+ };
+ values.Add(tmp);
+ }
+
+ #endregion
+
+ var namesHandle = GCHandle.Alloc(names.ToArray(), GCHandleType.Pinned);
+ var valuesHandle = GCHandle.Alloc(values.ToArray(), GCHandleType.Pinned);
+ try
+ {
+ if (setter != null) //ReSharper
+ setter.SetProperties(namesHandle.AddrOfPinnedObject(), valuesHandle.AddrOfPinnedObject(),
+ names.Count);
+ }
+ finally
+ {
+ namesHandle.Free();
+ valuesHandle.Free();
+ }
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Finds the common root of file names
+ /// </summary>
+ /// <param name="files">Array of file names</param>
+ /// <returns>Common root</returns>
+ private static int CommonRoot(ICollection<string> files)
+ {
+ var splittedFileNames = new List<string[]>(files.Count);
+#if CS4
+ splittedFileNames.AddRange(files.Select(fn => fn.Split(Path.DirectorySeparatorChar)));
+#else
+ foreach (string fn in files)
+ {
+ splittedFileNames.Add(fn.Split(Path.DirectorySeparatorChar));
+ }
+#endif
+ int minSplitLength = splittedFileNames[0].Length - 1;
+ if (files.Count > 1)
+ {
+ for (int i = 1; i < files.Count; i++)
+ {
+ if (minSplitLength > splittedFileNames[i].Length)
+ {
+ minSplitLength = splittedFileNames[i].Length;
+ }
+ }
+ }
+ string res = "";
+ for (int i = 0; i < minSplitLength; i++)
+ {
+ bool common = true;
+ for (int j = 1; j < files.Count; j++)
+ {
+ if (!(common &= splittedFileNames[j - 1][i] == splittedFileNames[j][i]))
+ {
+ break;
+ }
+ }
+ if (common)
+ {
+ res += splittedFileNames[0][i] + Path.DirectorySeparatorChar;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return res.Length;
+ }
+
+ /// <summary>
+ /// Validates the common root
+ /// </summary>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="files">Array of file names</param>
+ private static void CheckCommonRoot(string[] files, ref int commonRootLength)
+ {
+ string commonRoot;
+ try
+ {
+ commonRoot = files[0].Substring(0, commonRootLength);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ throw new SevenZipInvalidFileNamesException("invalid common root.");
+ }
+ if (commonRoot.EndsWith(new string(Path.DirectorySeparatorChar, 1), StringComparison.CurrentCulture))
+ {
+ commonRoot = commonRoot.Substring(0, commonRootLength - 1);
+ commonRootLength--;
+ }
+#if CS4
+ if (files.Any(fn => !fn.StartsWith(commonRoot, StringComparison.CurrentCulture)))
+ {
+ throw new SevenZipInvalidFileNamesException("invalid common root.");
+ }
+#else
+ foreach (string fn in files)
+ {
+ if (!fn.StartsWith(commonRoot, StringComparison.CurrentCulture))
+ {
+ throw new SevenZipInvalidFileNamesException("invalid common root.");
+ }
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Ensures that directory directory is not empty
+ /// </summary>
+ /// <param name="directory">Directory name</param>
+ /// <returns>False if is not empty</returns>
+ private static bool RecursiveDirectoryEmptyCheck(string directory)
+ {
+ var di = new DirectoryInfo(directory);
+ if (di.GetFiles().Length > 0)
+ {
+ return false;
+ }
+ bool empty = true;
+ foreach (DirectoryInfo cdi in di.GetDirectories())
+ {
+ empty &= RecursiveDirectoryEmptyCheck(cdi.FullName);
+ if (!empty)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Makes special FileInfo array for the archive file table.
+ /// </summary>
+ /// <param name="files">Array of files to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of file names</param>
+ /// <param name="directoryCompress">The value indicating whether to produce the array for files in a particular directory or just for an array of files.</param>
+ /// <param name="directoryStructure">Preserve directory structure.</param>
+ /// <returns>Special FileInfo array for the archive file table.</returns>
+ private static FileInfo[] ProduceFileInfoArray(
+ string[] files, int commonRootLength,
+ bool directoryCompress, bool directoryStructure)
+ {
+ var fis = new List<FileInfo>(files.Length);
+ string commonRoot = files[0].Substring(0, commonRootLength);
+ if (directoryCompress)
+ {
+#if CS4
+ fis.AddRange(files.Select(fn => new FileInfo(fn)));
+#else
+ foreach (string fn in files)
+ {
+ fis.Add(new FileInfo(fn));
+ }
+#endif
+ }
+ else
+ {
+ if (!directoryStructure)
+ {
+#if CS4
+ fis.AddRange(from fn in files where !Directory.Exists(fn) select new FileInfo(fn));
+#else
+ foreach (string fn in files)
+ {
+ if (!Directory.Exists(fn))
+ {
+ fis.Add(new FileInfo(fn));
+ }
+ }
+#endif
+ }
+ else
+ {
+ var fns = new List<string>(files.Length);
+ CheckCommonRoot(files, ref commonRootLength);
+ if (commonRootLength > 0)
+ {
+ commonRootLength++;
+ foreach (string f in files)
+ {
+ string[] splittedAfn = f.Substring(commonRootLength).Split(Path.DirectorySeparatorChar);
+ string cfn = commonRoot;
+ foreach (string t in splittedAfn)
+ {
+ cfn += Path.DirectorySeparatorChar + t;
+ if (!fns.Contains(cfn))
+ {
+ fis.Add(new FileInfo(cfn));
+ fns.Add(cfn);
+ }
+ }
+ }
+ }
+ else
+ {
+ foreach (string f in files)
+ {
+ string[] splittedAfn = f.Substring(commonRootLength).Split(Path.DirectorySeparatorChar);
+ string cfn = splittedAfn[0];
+ for (int i = 1; i < splittedAfn.Length; i++)
+ {
+ cfn += Path.DirectorySeparatorChar + splittedAfn[i];
+ if (!fns.Contains(cfn))
+ {
+ fis.Add(new FileInfo(cfn));
+ fns.Add(cfn);
+ }
+ }
+ }
+ }
+ }
+ }
+ return fis.ToArray();
+ }
+
+ /// <summary>
+ /// Recursive function for adding files in directory
+ /// </summary>
+ /// <param name="directory">Directory directory</param>
+ /// <param name="files">List of files</param>
+ /// <param name="searchPattern">Search string, such as "*.txt"</param>
+ private void AddFilesFromDirectory(string directory, ICollection<string> files, string searchPattern)
+ {
+ var di = new DirectoryInfo(directory);
+ foreach (FileInfo fi in di.GetFiles(searchPattern))
+ {
+ if (!ScanOnlyWritable)
+ {
+ files.Add(fi.FullName);
+ }
+ else
+ {
+ try
+ {
+ using (fi.OpenWrite()) { }
+ files.Add(fi.FullName);
+ }
+ catch (IOException) { }
+ }
+ }
+ foreach (DirectoryInfo cdi in di.GetDirectories())
+ {
+ if (IncludeEmptyDirectories)
+ {
+ files.Add(cdi.FullName);
+ }
+ AddFilesFromDirectory(cdi.FullName, files, searchPattern);
+ }
+ }
+
+ #endregion
+
+ #region GetArchiveUpdateCallback overloads
+
+ /// <summary>
+ /// Performs the common ArchiveUpdateCallback initialization.
+ /// </summary>
+ /// <param name="auc">The ArchiveUpdateCallback instance to initialize.</param>
+ private void CommonUpdateCallbackInit(ArchiveUpdateCallback auc)
+ {
+ auc.FileCompressionStarted += FileCompressionStartedEventProxy;
+ auc.Compressing += CompressingEventProxy;
+ auc.FileCompressionFinished += FileCompressionFinishedEventProxy;
+ auc.DefaultItemName = DefaultItemName;
+ auc.FastCompression = FastCompression;
+ }
+
+ private float GetDictionarySize()
+ {
+ float dictionarySize = 0.001f;
+ switch (_compressionMethod)
+ {
+ case CompressionMethod.Default:
+ case CompressionMethod.Lzma:
+ case CompressionMethod.Lzma2:
+ switch (CompressionLevel)
+ {
+ case CompressionLevel.None:
+ dictionarySize = 0.001f;
+ break;
+ case CompressionLevel.Fast:
+ dictionarySize = 1.0f / 16 * 7.5f + 4;
+ break;
+ case CompressionLevel.Low:
+ dictionarySize = 7.5f * 11.5f + 4;
+ break;
+ case CompressionLevel.Normal:
+ dictionarySize = 16 * 11.5f + 4;
+ break;
+ case CompressionLevel.High:
+ dictionarySize = 32 * 11.5f + 4;
+ break;
+ case CompressionLevel.Ultra:
+ dictionarySize = 64 * 11.5f + 4;
+ break;
+ }
+ break;
+ case CompressionMethod.BZip2:
+ switch (CompressionLevel)
+ {
+ case CompressionLevel.None:
+ dictionarySize = 0;
+ break;
+ case CompressionLevel.Fast:
+ dictionarySize = 0.095f;
+ break;
+ case CompressionLevel.Low:
+ dictionarySize = 0.477f;
+ break;
+ case CompressionLevel.Normal:
+ case CompressionLevel.High:
+ case CompressionLevel.Ultra:
+ dictionarySize = 0.858f;
+ break;
+ }
+ break;
+ case CompressionMethod.Deflate:
+ case CompressionMethod.Deflate64:
+ dictionarySize = 32;
+ break;
+ case CompressionMethod.Ppmd:
+ dictionarySize = 16;
+ break;
+ }
+ return dictionarySize;
+ }
+
+ /// <summary>
+ /// Produces a new instance of ArchiveUpdateCallback class.
+ /// </summary>
+ /// <param name="files">Array of FileInfo - files to pack</param>
+ /// <param name="rootLength">Length of the common root of file names</param>
+ /// <param name="password">The archive password</param>
+ /// <returns></returns>
+ private ArchiveUpdateCallback GetArchiveUpdateCallback(
+ FileInfo[] files, int rootLength, string password)
+ {
+ SetCompressionProperties();
+ var auc = (String.IsNullOrEmpty(password))
+ ? new ArchiveUpdateCallback(files, rootLength, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() }
+ : new ArchiveUpdateCallback(files, rootLength, password, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() };
+ CommonUpdateCallbackInit(auc);
+ return auc;
+ }
+
+ /// <summary>
+ /// Produces a new instance of ArchiveUpdateCallback class.
+ /// </summary>
+ /// <param name="inStream">The archive input stream.</param>
+ /// <param name="password">The archive password.</param>
+ /// <returns></returns>
+ private ArchiveUpdateCallback GetArchiveUpdateCallback(Stream inStream, string password)
+ {
+ SetCompressionProperties();
+ var auc = (String.IsNullOrEmpty(password))
+ ? new ArchiveUpdateCallback(inStream, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() }
+ : new ArchiveUpdateCallback(inStream, password, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() };
+ CommonUpdateCallbackInit(auc);
+ return auc;
+ }
+
+ /// <summary>
+ /// Produces a new instance of ArchiveUpdateCallback class.
+ /// </summary>
+ /// <param name="streamDict">Dictionary&lt;name of the archive entry, stream&gt;.</param>
+ /// <param name="password">The archive password</param>
+ /// <returns></returns>
+ private ArchiveUpdateCallback GetArchiveUpdateCallback(
+ Dictionary<string, Stream> streamDict, string password)
+ {
+ SetCompressionProperties();
+ var auc = (String.IsNullOrEmpty(password))
+ ? new ArchiveUpdateCallback(streamDict, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() }
+ : new ArchiveUpdateCallback(streamDict, password, this, GetUpdateData(), DirectoryStructure)
+ { DictionarySize = GetDictionarySize() };
+ CommonUpdateCallbackInit(auc);
+ return auc;
+ }
+
+ #endregion
+
+ #region Service "Get" functions
+
+ private void FreeCompressionCallback(ArchiveUpdateCallback callback)
+ {
+ callback.FileCompressionStarted -= FileCompressionStartedEventProxy;
+ callback.Compressing -= CompressingEventProxy;
+ callback.FileCompressionFinished -= FileCompressionFinishedEventProxy;
+ }
+
+ private string GetTempArchiveFileName(string archiveName)
+ {
+ return Path.Combine(TempFolderPath, Path.GetFileName(archiveName) + ".~");
+ }
+
+ private FileStream GetArchiveFileStream(string archiveName)
+ {
+ if ((CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null) && !File.Exists(archiveName))
+ {
+ if (
+ !ThrowException(null, new CompressionFailedException("file \"" + archiveName + "\" does not exist.")))
+ {
+ return null;
+ }
+ }
+ return _volumeSize == 0
+ ? CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null
+ ? File.Create(archiveName)
+ : File.Create(GetTempArchiveFileName(archiveName))
+ : null;
+ }
+
+ private void FinalizeUpdate()
+ {
+ if (_volumeSize == 0 && (CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null))
+ {
+ File.Move(GetTempArchiveFileName(_archiveName), _archiveName);
+ }
+ }
+
+ private UpdateData GetUpdateData()
+ {
+ if (_updateData.FileNamesToModify == null)
+ {
+ var updateData = new UpdateData { Mode = (InternalCompressionMode)((int)CompressionMode) };
+ switch (CompressionMode)
+ {
+ case CompressionMode.Create:
+ updateData.FilesCount = UInt32.MaxValue;
+ break;
+ case CompressionMode.Append:
+ updateData.FilesCount = _oldFilesCount;
+ break;
+ }
+ return updateData;
+ }
+ return _updateData;
+ }
+
+ private ISequentialOutStream GetOutStream(Stream outStream)
+ {
+ if (!_compressingFilesOnDisk)
+ {
+ return new OutStreamWrapper(outStream, false);
+ }
+ if (_volumeSize == 0 || CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null)
+ {
+ return new OutStreamWrapper(outStream, true);
+ }
+ return new OutMultiStreamWrapper(_archiveName, _volumeSize);
+ }
+
+ private IInStream GetInStream()
+ {
+ return File.Exists(_archiveName) &&
+ (CompressionMode != CompressionMode.Create && _compressingFilesOnDisk || _updateData.FileNamesToModify != null)
+ ?
+ new InStreamWrapper(
+ new FileStream(_archiveName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite),
+ true)
+ : null;
+ }
+
+ private ArchiveOpenCallback GetArchiveOpenCallback()
+ {
+ return String.IsNullOrEmpty(Password)
+ ?
+ new ArchiveOpenCallback(_archiveName)
+ :
+ new ArchiveOpenCallback(_archiveName, Password);
+ }
+
+ #endregion
+
+ #region Core public Members
+
+ #region Events
+
+ /// <summary>
+ /// Occurs when the next file is going to be packed.
+ /// </summary>
+ /// <remarks>Occurs when 7-zip engine requests for an input stream for the next file to pack it</remarks>
+ public event EventHandler<FileNameEventArgs> FileCompressionStarted;
+
+ /// <summary>
+ /// Occurs when the current file was compressed.
+ /// </summary>
+ public event EventHandler<EventArgs> FileCompressionFinished;
+
+ /// <summary>
+ /// Occurs when data are being compressed
+ /// </summary>
+ /// <remarks>Use this event for accurate progress handling and various ProgressBar.StepBy(e.PercentDelta) routines</remarks>
+ public event EventHandler<ProgressEventArgs> Compressing;
+
+ /// <summary>
+ /// Occurs when all files information was determined and SevenZipCompressor is about to start to compress them.
+ /// </summary>
+ /// <remarks>The incoming int value indicates the number of scanned files.</remarks>
+ public event EventHandler<IntEventArgs> FilesFound;
+
+ /// <summary>
+ /// Occurs when the compression procedure is finished
+ /// </summary>
+ public event EventHandler<EventArgs> CompressionFinished;
+
+ #region Event proxies
+ /// <summary>
+ /// Event proxy for FileCompressionStarted.
+ /// </summary>
+ /// <param name="sender">The sender of the event.</param>
+ /// <param name="e">The event arguments.</param>
+ private void FileCompressionStartedEventProxy(object sender, FileNameEventArgs e)
+ {
+ OnEvent(FileCompressionStarted, e, false);
+ }
+
+ /// <summary>
+ /// Event proxy for FileCompressionFinished.
+ /// </summary>
+ /// <param name="sender">The sender of the event.</param>
+ /// <param name="e">The event arguments.</param>
+ private void FileCompressionFinishedEventProxy(object sender, EventArgs e)
+ {
+ OnEvent(FileCompressionFinished, e, false);
+ }
+
+ /// <summary>
+ /// Event proxy for Compressing.
+ /// </summary>
+ /// <param name="sender">The sender of the event.</param>
+ /// <param name="e">The event arguments.</param>
+ private void CompressingEventProxy(object sender, ProgressEventArgs e)
+ {
+ OnEvent(Compressing, e, false);
+ }
+
+ /// <summary>
+ /// Event proxy for FilesFound.
+ /// </summary>
+ /// <param name="sender">The sender of the event.</param>
+ /// <param name="e">The event arguments.</param>
+ private void FilesFoundEventProxy(object sender, IntEventArgs e)
+ {
+ OnEvent(FilesFound, e, false);
+ }
+ #endregion
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the archive format
+ /// </summary>
+ public OutArchiveFormat ArchiveFormat
+ {
+ get
+ {
+ return _archiveFormat;
+ }
+
+ set
+ {
+ _archiveFormat = value;
+ if (!MethodIsValid(_compressionMethod))
+ {
+ _compressionMethod = CompressionMethod.Default;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the compression method
+ /// </summary>
+ public CompressionMethod CompressionMethod
+ {
+ get
+ {
+ return _compressionMethod;
+ }
+
+ set
+ {
+ _compressionMethod = !MethodIsValid(value) ? CompressionMethod.Default : value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the size in bytes of an archive volume (0 for no volumes).
+ /// </summary>
+ public int VolumeSize
+ {
+ get
+ {
+ return _volumeSize;
+ }
+
+ set
+ {
+ _volumeSize = value > 0 ? value : 0;
+ }
+ }
+ #endregion
+
+ #region CompressFiles overloads
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ public void CompressFiles(
+ string archiveName, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveName, "", fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk.</param>
+ public void CompressFiles(
+ Stream archiveStream, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveStream, "", fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ public void CompressFiles(
+ string archiveName, int commonRootLength, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveName, commonRootLength, "", fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk.</param>
+ public void CompressFiles(
+ Stream archiveStream, int commonRootLength, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveStream, commonRootLength, "", fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFilesEncrypted(
+ string archiveName, string password, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveName, CommonRoot(fileFullNames), password, fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFilesEncrypted(
+ Stream archiveStream, string password, params string[] fileFullNames)
+ {
+ CompressFilesEncrypted(archiveStream, CommonRoot(fileFullNames), password, fileFullNames);
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFilesEncrypted(
+ string archiveName, int commonRootLength, string password, params string[] fileFullNames)
+ {
+ _compressingFilesOnDisk = true;
+ _archiveName = archiveName;
+ using (FileStream fs = GetArchiveFileStream(archiveName))
+ {
+ if (fs == null && _volumeSize == 0)
+ {
+ return;
+ }
+ CompressFilesEncrypted(fs, commonRootLength, password, fileFullNames);
+ }
+ FinalizeUpdate();
+ }
+
+ /// <summary>
+ /// Packs files into the archive.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFilesEncrypted(
+ Stream archiveStream, int commonRootLength, string password, params string[] fileFullNames)
+ {
+ ClearExceptions();
+ if (fileFullNames.Length > 1 &&
+ (_archiveFormat == OutArchiveFormat.BZip2 || _archiveFormat == OutArchiveFormat.GZip ||
+ _archiveFormat == OutArchiveFormat.XZ))
+ {
+ if (!ThrowException(null,
+ new CompressionFailedException("Can not compress more than one file in this format.")))
+ {
+ return;
+ }
+ }
+ if (_volumeSize == 0 || !_compressingFilesOnDisk)
+ {
+ ValidateStream(archiveStream);
+ }
+ FileInfo[] files = null;
+ try
+ {
+ files = ProduceFileInfoArray(fileFullNames, commonRootLength, _directoryCompress, DirectoryStructure);
+ }
+ catch (Exception e)
+ {
+ if (!ThrowException(null, e))
+ {
+ return;
+ }
+ }
+ _directoryCompress = false;
+ if (FilesFound != null)
+ {
+ FilesFound(this, new IntEventArgs(fileFullNames.Length));
+ }
+ try
+ {
+ ISequentialOutStream sequentialArchiveStream;
+ using ((sequentialArchiveStream = GetOutStream(archiveStream)) as IDisposable)
+ {
+ IInStream inArchiveStream;
+ using ((inArchiveStream = GetInStream()) as IDisposable)
+ {
+ IOutArchive outArchive;
+ if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk)
+ {
+ SevenZipLibraryManager.LoadLibrary(this, _archiveFormat);
+ outArchive = SevenZipLibraryManager.OutArchive(_archiveFormat, this);
+ }
+ else
+ {
+ // Create IInArchive, read it and convert to IOutArchive
+ SevenZipLibraryManager.LoadLibrary(
+ this, Formats.InForOutFormats[_archiveFormat]);
+ if ((outArchive = MakeOutArchive(inArchiveStream)) == null)
+ {
+ return;
+ }
+ }
+ using (var auc = GetArchiveUpdateCallback(files, commonRootLength, password))
+ {
+ try
+ {
+ if (files != null) //ReSharper
+ CheckedExecute(
+ outArchive.UpdateItems(
+ sequentialArchiveStream, (uint)files.Length + _oldFilesCount, auc),
+ SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc);
+ }
+ finally
+ {
+ FreeCompressionCallback(auc);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk)
+ {
+ SevenZipLibraryManager.FreeLibrary(this, _archiveFormat);
+ }
+ else
+ {
+ SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]);
+ File.Delete(_archiveName);
+ }
+ _compressingFilesOnDisk = false;
+ OnEvent(CompressionFinished, EventArgs.Empty, false);
+ }
+ ThrowUserException();
+ }
+
+ #endregion
+
+ #region CompressDirectory overloads
+
+#if !CS4
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ public void CompressDirectory(
+ string directory, string archiveName)
+ {
+ CompressDirectory(directory, archiveName, "", "*", true);
+ }
+
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream)
+ {
+ CompressDirectory(directory, archiveStream, "", "*", true);
+ }
+
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressDirectory(
+ string directory, string archiveName, string password)
+ {
+ CompressDirectory(directory, archiveName, password, "*", true);
+ }
+
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream, string password)
+ {
+ CompressDirectory(directory, archiveStream, password, "*", true);
+ }
+
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, string archiveName, bool recursion)
+ {
+ CompressDirectory(directory, archiveName, "", "*", recursion);
+ }
+
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream, bool recursion)
+ {
+ CompressDirectory(directory, archiveStream, "", "*", recursion);
+ }
+
+ /// <summary>
+ /// Packs all files found by the specified pattern in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, string archiveName,
+ string searchPattern, bool recursion)
+ {
+ CompressDirectory(directory, archiveName, "", searchPattern, recursion);
+ }
+
+ /// <summary>
+ /// Packs all files found by the specified pattern in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream,
+ string searchPattern, bool recursion)
+ {
+ CompressDirectory(directory, archiveStream, "", searchPattern, recursion);
+ }
+
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressDirectory(
+ string directory, string archiveName,
+ bool recursion, string password)
+ {
+ CompressDirectory(directory, archiveName, password, "*", recursion);
+ }
+
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream,
+ bool recursion, string password)
+ {
+ CompressDirectory(directory, archiveStream, password, "*", recursion);
+ }
+#endif
+
+#if !CS4
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, string archiveName,
+ string password, string searchPattern, bool recursion)
+#else
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, string archiveName,
+ string password = "", string searchPattern = "*", bool recursion = true)
+#endif
+ {
+ _compressingFilesOnDisk = true;
+ _archiveName = archiveName;
+ using (FileStream fs = GetArchiveFileStream(archiveName))
+ {
+ if (fs == null && _volumeSize == 0)
+ {
+ return;
+ }
+ CompressDirectory(directory, fs, password, searchPattern, recursion);
+ }
+ FinalizeUpdate();
+ }
+
+#if !CS4
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream,
+ string password, string searchPattern, bool recursion)
+#else
+ /// <summary>
+ /// Packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ public void CompressDirectory(
+ string directory, Stream archiveStream,
+ string password = "", string searchPattern = "*", bool recursion = true)
+#endif
+ {
+ var files = new List<string>();
+ if (!Directory.Exists(directory))
+ {
+ throw new ArgumentException("Directory \"" + directory + "\" does not exist!");
+ }
+ if (RecursiveDirectoryEmptyCheck(directory))
+ {
+ throw new SevenZipInvalidFileNamesException("the specified directory is empty!");
+ }
+ if (recursion)
+ {
+ AddFilesFromDirectory(directory, files, searchPattern);
+ }
+ else
+ {
+#if CS4
+ files.AddRange((new DirectoryInfo(directory)).GetFiles(searchPattern).Select(fi => fi.FullName));
+#else
+ foreach (FileInfo fi in (new DirectoryInfo(directory)).GetFiles(searchPattern))
+ {
+ files.Add(fi.FullName);
+ }
+#endif
+ }
+ int commonRootLength = directory.Length;
+ if (directory.EndsWith("\\", StringComparison.OrdinalIgnoreCase))
+ {
+ directory = directory.Substring(0, directory.Length - 1);
+ }
+ else
+ {
+ commonRootLength++;
+ }
+ if (PreserveDirectoryRoot)
+ {
+ var upperRoot = Path.GetDirectoryName(directory);
+ commonRootLength = upperRoot.Length +
+ (upperRoot.EndsWith("\\", StringComparison.OrdinalIgnoreCase) ? 0 : 1);
+ }
+ _directoryCompress = true;
+ CompressFilesEncrypted(archiveStream, commonRootLength, password, files.ToArray());
+ }
+
+ #endregion
+
+ #region CompressFileDictionary overloads
+
+#if !CS4
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, string archiveName)
+ {
+ CompressFileDictionary(fileDictionary, archiveName, "");
+ }
+
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFileDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, Stream archiveStream)
+ {
+ CompressFileDictionary(fileDictionary, archiveStream, "");
+ }
+#endif
+
+#if !CS4
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, string archiveName, string password)
+#else
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, string archiveName, string password = "")
+#endif
+ {
+ _compressingFilesOnDisk = true;
+ _archiveName = archiveName;
+ using (FileStream fs = GetArchiveFileStream(archiveName))
+ {
+ if (fs == null && _volumeSize == 0)
+ {
+ return;
+ }
+ CompressFileDictionary(fileDictionary, fs, password);
+ }
+ FinalizeUpdate();
+ }
+
+#if !CS4
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, Stream archiveStream, string password)
+#else
+ /// <summary>
+ /// Packs the specified file dictionary.
+ /// </summary>
+ /// <param name="fileDictionary">Dictionary&lt;name of the archive entry, file name&gt;.
+ /// If a file name is null, the corresponding archive entry becomes a directory.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressFileDictionary(
+ Dictionary<string, string> fileDictionary, Stream archiveStream, string password = "")
+#endif
+ {
+ var streamDict = new Dictionary<string, Stream>(fileDictionary.Count);
+ foreach (var pair in fileDictionary)
+ {
+ if (pair.Value == null)
+ {
+ streamDict.Add(pair.Key, null);
+ }
+ else
+ {
+ if (!File.Exists(pair.Value))
+ {
+ throw new CompressionFailedException("The file corresponding to the archive entry \"" + pair.Key + "\" does not exist.");
+ }
+ streamDict.Add(
+ pair.Key,
+ new FileStream(pair.Value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
+ }
+ }
+ //The created streams will be automatically disposed inside.
+ CompressStreamDictionary(streamDict, archiveStream, password);
+ }
+
+ #endregion
+
+ #region CompressStreamDictionary overloads
+#if !CS4
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, string archiveName)
+ {
+ CompressStreamDictionary(streamDictionary, archiveName, "");
+ }
+
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, Stream archiveStream)
+ {
+ CompressStreamDictionary(streamDictionary, archiveStream, "");
+ }
+#endif
+
+#if !CS4
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, string archiveName, string password)
+#else
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, string archiveName, string password = "")
+#endif
+ {
+ _compressingFilesOnDisk = true;
+ _archiveName = archiveName;
+ using (FileStream fs = GetArchiveFileStream(archiveName))
+ {
+ if (fs == null && _volumeSize == 0)
+ {
+ return;
+ }
+ CompressStreamDictionary(streamDictionary, fs, password);
+ }
+ FinalizeUpdate();
+ }
+
+#if !CS4
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, Stream archiveStream, string password)
+#else
+ /// <summary>
+ /// Packs the specified stream dictionary.
+ /// </summary>
+ /// <param name="streamDictionary">Dictionary&lt;name of the archive entry, stream&gt;.
+ /// If a stream is null, the corresponding string becomes a directory name.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ public void CompressStreamDictionary(
+ Dictionary<string, Stream> streamDictionary, Stream archiveStream, string password = "")
+#endif
+ {
+ ClearExceptions();
+ if (streamDictionary.Count > 1 &&
+ (_archiveFormat == OutArchiveFormat.BZip2 || _archiveFormat == OutArchiveFormat.GZip ||
+ _archiveFormat == OutArchiveFormat.XZ))
+ {
+ if (!ThrowException(null,
+ new CompressionFailedException("Can not compress more than one file/stream in this format.")))
+ {
+ return;
+ }
+ }
+ if (_volumeSize == 0 || !_compressingFilesOnDisk)
+ {
+ ValidateStream(archiveStream);
+ }
+#if CS4
+ if (streamDictionary.Where(
+ pair => pair.Value != null && (!pair.Value.CanSeek || !pair.Value.CanRead)).Any(
+ pair => !ThrowException(null,
+ new ArgumentException("The specified stream dictionary contains an invalid stream corresponding to the archive entry \""
+ + pair.Key + "\".", "streamDictionary"))))
+ {
+ return;
+ }
+#else
+ foreach (var pair in streamDictionary)
+ {
+ if (pair.Value != null && (!pair.Value.CanSeek || !pair.Value.CanRead))
+ {
+ if (!ThrowException(null, new ArgumentException(
+ "The specified stream dictionary contains an invalid stream corresponding to the archive entry \"" + pair.Key + "\".",
+ "streamDictionary")))
+ {
+ return;
+ }
+ }
+ }
+#endif
+ try
+ {
+ ISequentialOutStream sequentialArchiveStream;
+ using ((sequentialArchiveStream = GetOutStream(archiveStream)) as IDisposable)
+ {
+ IInStream inArchiveStream;
+ using ((inArchiveStream = GetInStream()) as IDisposable)
+ {
+ IOutArchive outArchive;
+ if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk)
+ {
+ SevenZipLibraryManager.LoadLibrary(this, _archiveFormat);
+ outArchive = SevenZipLibraryManager.OutArchive(_archiveFormat, this);
+ }
+ else
+ {
+ // Create IInArchive, read it and convert to IOutArchive
+ SevenZipLibraryManager.LoadLibrary(
+ this, Formats.InForOutFormats[_archiveFormat]);
+ if ((outArchive = MakeOutArchive(inArchiveStream)) == null)
+ {
+ return;
+ }
+ }
+ using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback(
+ streamDictionary, password))
+ {
+ try
+ {
+ CheckedExecute(outArchive.UpdateItems(sequentialArchiveStream,
+ (uint)streamDictionary.Count + _oldFilesCount, auc),
+ SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc);
+ }
+ finally
+ {
+ FreeCompressionCallback(auc);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk)
+ {
+ SevenZipLibraryManager.FreeLibrary(this, _archiveFormat);
+ }
+ else
+ {
+ SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]);
+ File.Delete(_archiveName);
+ }
+ _compressingFilesOnDisk = false;
+ OnEvent(CompressionFinished, EventArgs.Empty, false);
+ }
+ ThrowUserException();
+ }
+
+ #endregion
+
+ #region CompressStream overloads
+
+#if !CS4
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <exception cref="ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+ public void CompressStream(Stream inStream, Stream outStream)
+ {
+ CompressStream(inStream, outStream, "");
+ }
+#endif
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <param name="password">The archive password.</param>
+ /// <exception cref="ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+ public void CompressStream(Stream inStream, Stream outStream, string password
+#if CS4
+ = ""
+#endif
+ )
+ {
+ ClearExceptions();
+ if (!inStream.CanSeek || !inStream.CanRead || !outStream.CanWrite)
+ {
+ if (!ThrowException(null, new ArgumentException("The specified streams are invalid.")))
+ {
+ return;
+ }
+ }
+ try
+ {
+ SevenZipLibraryManager.LoadLibrary(this, _archiveFormat);
+ ISequentialOutStream sequentialArchiveStream;
+ using ((sequentialArchiveStream = GetOutStream(outStream)) as IDisposable)
+ {
+ using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback(inStream, password))
+ {
+ try
+ {
+ CheckedExecute(
+ SevenZipLibraryManager.OutArchive(_archiveFormat, this).UpdateItems(
+ sequentialArchiveStream, 1, auc),
+ SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc);
+ }
+ finally
+ {
+ FreeCompressionCallback(auc);
+ }
+ }
+ }
+ }
+ finally
+ {
+ SevenZipLibraryManager.FreeLibrary(this, _archiveFormat);
+ OnEvent(CompressionFinished, EventArgs.Empty, false);
+ }
+ ThrowUserException();
+ }
+
+ #endregion
+
+ #region ModifyArchive overloads
+#if !CS4
+ /// <summary>
+ /// Modifies the existing archive (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+ public void ModifyArchive(string archiveName, Dictionary<int, string> newFileNames)
+ {
+ ModifyArchive(archiveName, newFileNames, "");
+ }
+#endif
+
+ /// <summary>
+ /// Modifies the existing archive (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+ /// <param name="password">The archive password.</param>
+ public void ModifyArchive(string archiveName, Dictionary<int, string> newFileNames, string password
+#if CS4
+ = ""
+#endif
+ )
+ {
+ ClearExceptions();
+ if (!SevenZipLibraryManager.ModifyCapable)
+ {
+ throw new SevenZipLibraryException("The specified 7zip native library does not support this method.");
+ }
+ if (!File.Exists(archiveName))
+ {
+ if (!ThrowException(null, new ArgumentException("The specified archive does not exist.", "archiveName")))
+ {
+ return;
+ }
+ }
+ if (newFileNames == null || newFileNames.Count == 0)
+ {
+ if (!ThrowException(null, new ArgumentException("Invalid new file names.", "newFileNames")))
+ {
+ return;
+ }
+ }
+ try
+ {
+ using (var extr = new SevenZipExtractor(archiveName))
+ {
+ _updateData = new UpdateData();
+ var archiveData = new ArchiveFileInfo[extr.ArchiveFileData.Count];
+ extr.ArchiveFileData.CopyTo(archiveData, 0);
+ _updateData.ArchiveFileData = new List<ArchiveFileInfo>(archiveData);
+ }
+ _updateData.FileNamesToModify = newFileNames;
+ _updateData.Mode = InternalCompressionMode.Modify;
+ }
+ catch (SevenZipException e)
+ {
+ if (!ThrowException(null, e))
+ {
+ return;
+ }
+ }
+ try
+ {
+ ISequentialOutStream sequentialArchiveStream;
+ _compressingFilesOnDisk = true;
+ using ((sequentialArchiveStream = GetOutStream(GetArchiveFileStream(archiveName))) as IDisposable)
+ {
+ IInStream inArchiveStream;
+ _archiveName = archiveName;
+ using ((inArchiveStream = GetInStream()) as IDisposable)
+ {
+ IOutArchive outArchive;
+ // Create IInArchive, read it and convert to IOutArchive
+ SevenZipLibraryManager.LoadLibrary(
+ this, Formats.InForOutFormats[_archiveFormat]);
+ if ((outArchive = MakeOutArchive(inArchiveStream)) == null)
+ {
+ return;
+ }
+ using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback(null, 0, password))
+ {
+ UInt32 deleteCount = 0;
+ if (_updateData.FileNamesToModify != null)
+ {
+#if CS4 // System.Linq of C# 4 is great
+ deleteCount = (UInt32)_updateData.FileNamesToModify.Sum(
+ pairDeleted => pairDeleted.Value == null ? 1 : 0);
+#else
+ foreach(var pairDeleted in _updateData.FileNamesToModify)
+ {
+ if (pairDeleted.Value == null)
+ {
+ deleteCount++;
+ }
+ }
+#endif
+ }
+ try
+ {
+ CheckedExecute(
+ outArchive.UpdateItems(
+ sequentialArchiveStream, _oldFilesCount - deleteCount, auc),
+ SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc);
+ }
+ finally
+ {
+ FreeCompressionCallback(auc);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]);
+ File.Delete(archiveName);
+ FinalizeUpdate();
+ _compressingFilesOnDisk = false;
+ _updateData.FileNamesToModify = null;
+ _updateData.ArchiveFileData = null;
+ OnEvent(CompressionFinished, EventArgs.Empty, false);
+ }
+ ThrowUserException();
+ }
+ #endregion
+
+ #endregion
+
+#endif
+
+ /// <summary>
+ /// Gets or sets the dictionary size for the managed LZMA algorithm.
+ /// </summary>
+ public static int LzmaDictionarySize
+ {
+ get
+ {
+ return _lzmaDictionarySize;
+ }
+ set
+ {
+ _lzmaDictionarySize = value;
+ }
+ }
+
+ internal static void WriteLzmaProperties(Encoder encoder)
+ {
+ #region LZMA properties definition
+
+ CoderPropId[] propIDs =
+ {
+ CoderPropId.DictionarySize,
+ CoderPropId.PosStateBits,
+ CoderPropId.LitContextBits,
+ CoderPropId.LitPosBits,
+ CoderPropId.Algorithm,
+ CoderPropId.NumFastBytes,
+ CoderPropId.MatchFinder,
+ CoderPropId.EndMarker
+ };
+ object[] properties =
+ {
+ _lzmaDictionarySize,
+ 2,
+ 3,
+ 0,
+ 2,
+ 256,
+ "bt4",
+ false
+ };
+
+ #endregion
+
+ encoder.SetCoderProperties(propIDs, properties);
+ }
+
+ /// <summary>
+ /// Compresses the specified stream with LZMA algorithm (C# inside)
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream</param>
+ /// <param name="outStream">The destination compressed stream</param>
+ /// <param name="inLength">The length of uncompressed data (null for inStream.Length)</param>
+ /// <param name="codeProgressEvent">The event for handling the code progress</param>
+ public static void CompressStream(Stream inStream, Stream outStream, int? inLength,
+ EventHandler<ProgressEventArgs> codeProgressEvent)
+ {
+ if (!inStream.CanRead || !outStream.CanWrite)
+ {
+ throw new ArgumentException("The specified streams are invalid.");
+ }
+ var encoder = new Encoder();
+ WriteLzmaProperties(encoder);
+ encoder.WriteCoderProperties(outStream);
+ long streamSize = inLength.HasValue ? inLength.Value : inStream.Length;
+ for (int i = 0; i < 8; i++)
+ {
+ outStream.WriteByte((byte)(streamSize >> (8 * i)));
+ }
+ encoder.Code(inStream, outStream, -1, -1, new LzmaProgressCallback(streamSize, codeProgressEvent));
+ }
+
+ /// <summary>
+ /// Compresses byte array with LZMA algorithm (C# inside)
+ /// </summary>
+ /// <param name="data">Byte array to compress</param>
+ /// <returns>Compressed byte array</returns>
+ public static byte[] CompressBytes(byte[] data)
+ {
+ using (var inStream = new MemoryStream(data))
+ {
+ using (var outStream = new MemoryStream())
+ {
+ var encoder = new Encoder();
+ WriteLzmaProperties(encoder);
+ encoder.WriteCoderProperties(outStream);
+ long streamSize = inStream.Length;
+ for (int i = 0; i < 8; i++)
+ outStream.WriteByte((byte)(streamSize >> (8 * i)));
+ encoder.Code(inStream, outStream, -1, -1, null);
+ return outStream.ToArray();
+ }
+ }
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/SevenZip/SevenZipCompressorAsynchronous.cs b/SevenZip/SevenZipCompressorAsynchronous.cs
new file mode 100644
index 00000000..cf53cbe0
--- /dev/null
+++ b/SevenZip/SevenZipCompressorAsynchronous.cs
@@ -0,0 +1,709 @@
+/* This file is part of SevenZipSharp.
+
+ SevenZipSharp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SevenZipSharp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
+namespace SevenZip
+{
+ using System.Collections.Generic;
+ using System.IO;
+#if DOTNET20
+ using System.Threading;
+#else
+ using System.Windows.Threading;
+#endif
+
+ partial class SevenZipCompressor
+ {
+ #region Delegates
+ private delegate void CompressFiles1Delegate(string archiveName, string[] fileFullNames);
+ private delegate void CompressFiles2Delegate(Stream archiveStream, string[] fileFullNames);
+ private delegate void CompressFiles3Delegate(string archiveName, int commonRootLength, string[] fileFullNames);
+ private delegate void CompressFiles4Delegate(Stream archiveStream, int commonRootLength, string[] fileFullNames);
+
+ private delegate void CompressFilesEncrypted1Delegate(string archiveName, string password, string[] fileFullNames);
+ private delegate void CompressFilesEncrypted2Delegate(Stream archiveStream, string password, string[] fileFullNames);
+ private delegate void CompressFilesEncrypted3Delegate(string archiveName, int commonRootLength, string password, string[] fileFullNames);
+ private delegate void CompressFilesEncrypted4Delegate(Stream archiveStream, int commonRootLength, string password, string[] fileFullNames);
+
+ private delegate void CompressDirectory1Delegate(string directory, string archiveName);
+ private delegate void CompressDirectory2Delegate(string directory, Stream archiveStream);
+ private delegate void CompressDirectory3Delegate(string directory, string archiveName, string password);
+ private delegate void CompressDirectory4Delegate(string directory, Stream archiveStream, string password);
+ private delegate void CompressDirectory5Delegate(string directory, string archiveName,
+ string password, string searchPattern, bool recursion);
+ private delegate void CompressDirectory6Delegate(string directory, Stream archiveStream,
+ string password, string searchPattern, bool recursion);
+
+ private delegate void CompressStream1Delegate(Stream inStream, Stream outStream);
+ private delegate void CompressStream2Delegate(Stream inStream, Stream outStream, string password);
+
+ private delegate void ModifyArchive1Delegate(string archiveName, Dictionary<int, string> newFileNames);
+ private delegate void ModifyArchive2Delegate(string archiveName, Dictionary<int, string> newFileNames,
+ string password);
+ #endregion
+
+ #region CompressFiles overloads
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name.</param>
+#endif
+ public void BeginCompressFiles(
+ string archiveName
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFiles1Delegate(CompressFiles)).BeginInvoke(archiveName, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk.</param>
+#endif
+ public void BeginCompressFiles(
+ Stream archiveStream
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFiles2Delegate(CompressFiles)).BeginInvoke(archiveStream, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveName">The archive file name.</param>
+#endif
+ public void BeginCompressFiles(
+ string archiveName, int commonRootLength
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFiles3Delegate(CompressFiles)).BeginInvoke(archiveName, commonRootLength, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk.</param>
+#endif
+ public void BeginCompressFiles(
+ Stream archiveStream, int commonRootLength
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFiles4Delegate(CompressFiles)).BeginInvoke(archiveStream, commonRootLength, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name</param>
+ /// <param name="password">The archive password.</param>
+#endif
+ public void BeginCompressFilesEncrypted(
+ string archiveName, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFilesEncrypted1Delegate(CompressFilesEncrypted)).BeginInvoke(archiveName, password, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+#endif
+ public void BeginCompressFilesEncrypted(
+ Stream archiveStream, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFilesEncrypted2Delegate(CompressFilesEncrypted)).BeginInvoke(archiveStream, password, fileFullNames,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveName">The archive file name</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+#endif
+ public void BeginCompressFilesEncrypted(
+ string archiveName, int commonRootLength, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFilesEncrypted3Delegate(CompressFilesEncrypted)).BeginInvoke(archiveName, commonRootLength, password,
+ fileFullNames, AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs files into the archive asynchronously.
+ /// </summary>
+ /// <param name="fileFullNames">Array of file names to pack.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="commonRootLength">The length of the common root of the file names.</param>
+#endif
+ public void BeginCompressFilesEncrypted(
+ Stream archiveStream, int commonRootLength, string password
+#if !DOTNET20
+, DispatcherPriority eventPriority
+#endif
+ , params string[] fileFullNames
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressFilesEncrypted4Delegate(CompressFilesEncrypted)).BeginInvoke(archiveStream, commonRootLength, password,
+ fileFullNames, AsyncCallbackImplementation, this);
+ }
+ #endregion
+
+ #region BeginCompressDirectory overloads
+
+#if !CS4
+#if !DOTNET20
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+#endif
+ public void BeginCompressDirectory(
+ string directory, string archiveName
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory1Delegate(CompressDirectory)).BeginInvoke(directory, archiveName,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+#endif
+ public void BeginCompressDirectory(
+ string directory, Stream archiveStream
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory2Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream,
+ AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+#endif
+ public void BeginCompressDirectory(
+ string directory, string archiveName, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory3Delegate(CompressDirectory)).BeginInvoke(directory, archiveName,
+ password, AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Recursively packs all files in the specified directory.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+#endif
+ public void BeginCompressDirectory(
+ string directory, Stream archiveStream, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory4Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream,
+ password, AsyncCallbackImplementation, this);
+ }
+#endif
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs all files in the specified directory asynchronously.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs all files in the specified directory asynchronously.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+#endif
+ public void BeginCompressDirectory(string directory, string archiveName,
+ string password
+#if CS4
+ = ""
+#endif
+ , string searchPattern
+#if CS4
+ = "*"
+#endif
+ , bool recursion
+#if CS4
+ = true
+#endif
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#if CS4
+ = DispatcherPriority.Normal
+#endif
+#endif
+)
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory5Delegate(CompressDirectory)).BeginInvoke(directory, archiveName,
+ password, searchPattern, recursion, AsyncCallbackImplementation, this);
+ }
+
+#if !DOTNET20
+ /// <summary>
+ /// Packs all files in the specified directory asynchronously.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Packs all files in the specified directory asynchronously.
+ /// </summary>
+ /// <param name="directory">The directory to compress.</param>
+ /// <param name="archiveStream">The archive output stream.
+ /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="searchPattern">Search string, such as "*.txt".</param>
+ /// <param name="recursion">If true, files will be searched for recursively; otherwise, not.</param>
+#endif
+ public void BeginCompressDirectory(string directory, Stream archiveStream,
+ string password
+#if CS4
+ = ""
+#endif
+ , string searchPattern
+#if CS4
+ = "*"
+#endif
+ , bool recursion
+#if CS4
+ = true
+#endif
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#if CS4
+ = DispatcherPriority.Normal
+#endif
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressDirectory6Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream,
+ password, searchPattern, recursion, AsyncCallbackImplementation, this);
+ }
+#endregion
+
+ #region BeginCompressStream overloads
+#if !CS4
+#if !DOTNET20
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <exception cref="ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <exception cref="System.ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+#endif
+ public void BeginCompressStream(Stream inStream, Stream outStream
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressStream1Delegate(CompressStream)).BeginInvoke(inStream, outStream, AsyncCallbackImplementation, this);
+ }
+#endif
+
+#if !DOTNET20
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <param name="password">The archive password.</param>
+ /// <exception cref="System.ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Compresses the specified stream.
+ /// </summary>
+ /// <param name="inStream">The source uncompressed stream.</param>
+ /// <param name="outStream">The destination compressed stream.</param>
+ /// <param name="password">The archive password.</param>
+ /// <exception cref="System.ArgumentException">ArgumentException: at least one of the specified streams is invalid.</exception>
+#endif
+ public void BeginCompressStream(Stream inStream, Stream outStream, string password
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#if CS4
+ = DispatcherPriority.Normal
+#endif
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new CompressStream2Delegate(CompressStream)).BeginInvoke(inStream, outStream, password, AsyncCallbackImplementation, this);
+
+ }
+ #endregion
+
+ #region BeginModifyArchive overloads
+#if !CS4
+#if !DOTNET20
+ /// <summary>
+ /// Modifies the existing archive asynchronously (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Modifies the existing archive asynchronously (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+#endif
+ public void BeginModifyArchive(string archiveName, Dictionary<int, string> newFileNames
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new ModifyArchive1Delegate(ModifyArchive)).BeginInvoke(archiveName, newFileNames, AsyncCallbackImplementation, this);
+ }
+#endif
+
+#if !DOTNET20
+ /// <summary>
+ /// Modifies the existing archive asynchronously (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+ /// <param name="password">The archive password.</param>
+ /// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
+#else
+ /// <summary>
+ /// Modifies the existing archive asynchronously (renames files or deletes them).
+ /// </summary>
+ /// <param name="archiveName">The archive file name.</param>
+ /// <param name="newFileNames">New file names. Null value to delete the corresponding index.</param>
+ /// <param name="password">The archive password.</param>
+#endif
+ public void BeginModifyArchive(string archiveName, Dictionary<int, string> newFileNames,
+ string password
+#if CS4
+ = ""
+#endif
+#if !DOTNET20
+ , DispatcherPriority eventPriority
+#if CS4
+ = DispatcherPriority.Normal
+#endif
+#endif
+ )
+ {
+ SaveContext(
+#if !DOTNET20
+ eventPriority
+#endif
+ );
+ (new ModifyArchive2Delegate(ModifyArchive)).BeginInvoke(archiveName, newFileNames, password, AsyncCallbackImplementation, this);
+ }
+ #endregion
+ }
+}
diff --git a/SevenZip/SevenZipExtractor.cs b/SevenZip/SevenZipExtractor.cs
index 4500c680..3497738a 100644
--- a/SevenZip/SevenZipExtractor.cs
+++ b/SevenZip/SevenZipExtractor.cs
@@ -17,6 +17,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;
diff --git a/SevenZip/SevenZipExtractorAsynchronous.cs b/SevenZip/SevenZipExtractorAsynchronous.cs
index b72b0ddb..26cf9844 100644
--- a/SevenZip/SevenZipExtractorAsynchronous.cs
+++ b/SevenZip/SevenZipExtractorAsynchronous.cs
@@ -13,8 +13,10 @@
You should have received a copy of the GNU Lesser General Public License
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
*/
+
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
namespace SevenZip
{
diff --git a/SevenZip/SevenZipSfx.cs b/SevenZip/SevenZipSfx.cs
new file mode 100644
index 00000000..76905bdb
--- /dev/null
+++ b/SevenZip/SevenZipSfx.cs
@@ -0,0 +1,502 @@
+/* This file is part of SevenZipSharp.
+
+ SevenZipSharp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ SevenZipSharp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define DOTNET20
+#define UNMANAGED
+#define COMPRESS
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+
+namespace SevenZip
+{
+#if SFX
+ using SfxSettings = Dictionary<string, string>;
+
+ /// <summary>
+ /// Sfx module choice enumeration
+ /// </summary>
+ public enum SfxModule
+ {
+ /// <summary>
+ /// Default module (leave this if unsure)
+ /// </summary>
+ Default,
+ /// <summary>
+ /// The simple sfx module by Igor Pavlov with no adjustable parameters
+ /// </summary>
+ Simple,
+ /// <summary>
+ /// The installer sfx module by Igor Pavlov
+ /// </summary>
+ Installer,
+ /// <summary>
+ /// The extended installer sfx module by Oleg Scherbakov
+ /// </summary>
+ Extended,
+ /// <summary>
+ /// The custom sfx module. First you must specify the module file name.
+ /// </summary>
+ Custom
+ }
+
+ /// <summary>
+ /// The class for making 7-zip based self-extracting archives.
+ /// </summary>
+ public class SevenZipSfx
+ {
+ private static readonly Dictionary<SfxModule, List<string>> SfxSupportedModuleNames =
+ new Dictionary<SfxModule, List<string>>(3)
+ {
+ {SfxModule.Default, new List<string>(1) {"7zxSD_All.sfx"}},
+ {SfxModule.Simple, new List<string>(2) {"7z.sfx", "7zCon.sfx"}},
+ {SfxModule.Installer, new List<string>(2) {"7zS.sfx", "7zSD.sfx"}},
+ {
+ SfxModule.Extended,
+ new List<string>(4) {"7zxSD_All.sfx", "7zxSD_Deflate", "7zxSD_LZMA", "7zxSD_PPMd"}
+ }
+ };
+
+ private SfxModule _module = SfxModule.Default;
+ private string _moduleFileName;
+ private Dictionary<SfxModule, List<string>> _sfxCommands;
+
+ /// <summary>
+ /// Initializes a new instance of the SevenZipSfx class.
+ /// </summary>
+ public SevenZipSfx()
+ {
+ _module = SfxModule.Default;
+ CommonInit();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the SevenZipSfx class.
+ /// </summary>
+ /// <param name="module">The sfx module to use as a front-end.</param>
+ public SevenZipSfx(SfxModule module)
+ {
+ if (module == SfxModule.Custom)
+ {
+ throw new ArgumentException("You must specify the custom module executable.", "module");
+ }
+ _module = module;
+ CommonInit();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the SevenZipSfx class.
+ /// </summary>
+ /// <param name="moduleFileName"></param>
+ public SevenZipSfx(string moduleFileName)
+ {
+ _module = SfxModule.Custom;
+ ModuleFileName = moduleFileName;
+ CommonInit();
+ }
+
+ /// <summary>
+ /// Gets the sfx module type.
+ /// </summary>
+ public SfxModule SfxModule
+ {
+ get
+ {
+ return _module;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the custom sfx module file name
+ /// </summary>
+ public string ModuleFileName
+ {
+ get
+ {
+ return _moduleFileName;
+ }
+
+ set
+ {
+ if (!File.Exists(value))
+ {
+ throw new ArgumentException("The specified file does not exist.");
+ }
+ _moduleFileName = value;
+ _module = SfxModule.Custom;
+ string sfxName = Path.GetFileName(value);
+ foreach (SfxModule mod in SfxSupportedModuleNames.Keys)
+ {
+ if (SfxSupportedModuleNames[mod].Contains(sfxName))
+ {
+ _module = mod;
+ }
+ }
+ }
+ }
+
+ private void CommonInit()
+ {
+ LoadCommandsFromResource("Configs");
+ }
+
+ private static string GetResourceString(string str)
+ {
+#if !WINCE
+ return "SevenZip.sfx." + str;
+#else
+ return "SevenZipSharpMobile.sfx." + str;
+#endif
+ }
+
+ /// <summary>
+ /// Gets the sfx module enum by the list of supported modules
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ private static SfxModule GetModuleByName(string name)
+ {
+ if (name.IndexOf("7z.sfx", StringComparison.Ordinal) > -1)
+ {
+ return SfxModule.Simple;
+ }
+ if (name.IndexOf("7zS.sfx", StringComparison.Ordinal) > -1)
+ {
+ return SfxModule.Installer;
+ }
+ if (name.IndexOf("7zxSD_All.sfx", StringComparison.Ordinal) > -1)
+ {
+ return SfxModule.Extended;
+ }
+ throw new SevenZipSfxValidationException("The specified configuration is unsupported.");
+ }
+
+ /// <summary>
+ /// Loads the commands for each supported sfx module configuration
+ /// </summary>
+ /// <param name="xmlDefinitions">The resource name for xml definitions</param>
+ private void LoadCommandsFromResource(string xmlDefinitions)
+ {
+ using (Stream cfg = Assembly.GetExecutingAssembly().GetManifestResourceStream(
+ GetResourceString(xmlDefinitions + ".xml")))
+ {
+ if (cfg == null)
+ {
+ throw new SevenZipSfxValidationException("The configuration \"" + xmlDefinitions +
+ "\" does not exist.");
+ }
+ using (Stream schm = Assembly.GetExecutingAssembly().GetManifestResourceStream(
+ GetResourceString(xmlDefinitions + ".xsd")))
+ {
+ if (schm == null)
+ {
+ throw new SevenZipSfxValidationException("The configuration schema \"" + xmlDefinitions +
+ "\" does not exist.");
+ }
+ var sc = new XmlSchemaSet();
+ using (XmlReader scr = XmlReader.Create(schm))
+ {
+ sc.Add(null, scr);
+ var settings = new XmlReaderSettings {ValidationType = ValidationType.Schema, Schemas = sc};
+ string validationErrors = "";
+ settings.ValidationEventHandler +=
+ ((s, t) =>
+ {
+ validationErrors += String.Format(CultureInfo.InvariantCulture, "[{0}]: {1}\n",
+ t.Severity.ToString(), t.Message);
+ });
+ using (XmlReader rdr = XmlReader.Create(cfg, settings))
+ {
+ _sfxCommands = new Dictionary<SfxModule, List<string>>();
+ rdr.Read();
+ rdr.Read();
+ rdr.Read();
+ rdr.Read();
+ rdr.Read();
+ rdr.ReadStartElement("sfxConfigs");
+ rdr.Read();
+ do
+ {
+ SfxModule mod = GetModuleByName(rdr["modules"]);
+ rdr.ReadStartElement("config");
+ rdr.Read();
+ if (rdr.Name == "id")
+ {
+ var cmds = new List<string>();
+ _sfxCommands.Add(mod, cmds);
+ do
+ {
+ cmds.Add(rdr["command"]);
+ rdr.Read();
+ rdr.Read();
+ } while (rdr.Name == "id");
+ rdr.ReadEndElement();
+ rdr.Read();
+ }
+ else
+ {
+ _sfxCommands.Add(mod, null);
+ }
+ } while (rdr.Name == "config");
+ }
+ if (!String.IsNullOrEmpty(validationErrors))
+ {
+ throw new SevenZipSfxValidationException(
+ "\n" + validationErrors.Substring(0, validationErrors.Length - 1));
+ }
+ _sfxCommands.Add(SfxModule.Default, _sfxCommands[SfxModule.Extended]);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Validates the sfx scenario commands.
+ /// </summary>
+ /// <param name="settings">The sfx settings dictionary to validate.</param>
+ private void ValidateSettings(SfxSettings settings)
+ {
+ if (_module == SfxModule.Custom)
+ {
+ return;
+ }
+ List<string> commands = _sfxCommands[_module];
+ if (commands == null)
+ {
+ return;
+ }
+ var invalidCommands = new List<string>();
+ foreach (string command in settings.Keys)
+ {
+ if (!commands.Contains(command))
+ {
+ invalidCommands.Add(command);
+ }
+ }
+ if (invalidCommands.Count > 0)
+ {
+ var invalidText = new StringBuilder("\nInvalid commands:\n");
+ foreach (string str in invalidCommands)
+ {
+ invalidText.Append(str);
+ }
+ throw new SevenZipSfxValidationException(invalidText.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Gets the stream containing the sfx settings.
+ /// </summary>
+ /// <param name="settings">The sfx settings dictionary.</param>
+ /// <returns></returns>
+ private static Stream GetSettingsStream(SfxSettings settings)
+ {
+ var ms = new MemoryStream();
+ byte[] buf = Encoding.UTF8.GetBytes(@";!@Install@!UTF-8!" + '\n');
+ ms.Write(buf, 0, buf.Length);
+ foreach (string command in settings.Keys)
+ {
+ buf =
+ Encoding.UTF8.GetBytes(String.Format(CultureInfo.InvariantCulture, "{0}=\"{1}\"\n", command,
+ settings[command]));
+ ms.Write(buf, 0, buf.Length);
+ }
+ buf = Encoding.UTF8.GetBytes(@";!@InstallEnd@!");
+ ms.Write(buf, 0, buf.Length);
+ return ms;
+ }
+
+ private SfxSettings GetDefaultSettings()
+ {
+ switch (_module)
+ {
+ default:
+ return null;
+ case SfxModule.Installer:
+ var settings = new Dictionary<string, string> {{"Title", "7-Zip self-extracting archive"}};
+ return settings;
+ case SfxModule.Default:
+ case SfxModule.Extended:
+ settings = new Dictionary<string, string>
+ {
+ {"GUIMode", "0"},
+ {"InstallPath", "."},
+ {"GUIFlags", "128+8"},
+ {"ExtractPathTitle", "7-Zip self-extracting archive"},
+ {"ExtractPathText", "Specify the path where to extract the files:"}
+ };
+ return settings;
+ }
+ }
+
+ /// <summary>
+ /// Writes the whole to the other one.
+ /// </summary>
+ /// <param name="src">The source stream to read from.</param>
+ /// <param name="dest">The destination stream to wrie to.</param>
+ private static void WriteStream(Stream src, Stream dest)
+ {
+ src.Seek(0, SeekOrigin.Begin);
+ var buf = new byte[32768];
+ int bytesRead;
+ while ((bytesRead = src.Read(buf, 0, buf.Length)) > 0)
+ {
+ dest.Write(buf, 0, bytesRead);
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archive">The archive stream.</param>
+ /// <param name="sfxFileName">The name of the self-extracting executable.</param>
+ public void MakeSfx(Stream archive, string sfxFileName)
+ {
+ using (Stream sfxStream = File.Create(sfxFileName))
+ {
+ MakeSfx(archive, GetDefaultSettings(), sfxStream);
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archive">The archive stream.</param>
+ /// <param name="sfxStream">The stream to write the self-extracting executable to.</param>
+ public void MakeSfx(Stream archive, Stream sfxStream)
+ {
+ MakeSfx(archive, GetDefaultSettings(), sfxStream);
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archive">The archive stream.</param>
+ /// <param name="settings">The sfx settings.</param>
+ /// <param name="sfxFileName">The name of the self-extracting executable.</param>
+ public void MakeSfx(Stream archive, SfxSettings settings, string sfxFileName)
+ {
+ using (Stream sfxStream = File.Create(sfxFileName))
+ {
+ MakeSfx(archive, settings, sfxStream);
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archive">The archive stream.</param>
+ /// <param name="settings">The sfx settings.</param>
+ /// <param name="sfxStream">The stream to write the self-extracting executable to.</param>
+ public void MakeSfx(Stream archive, SfxSettings settings, Stream sfxStream)
+ {
+ if (!sfxStream.CanWrite)
+ {
+ throw new ArgumentException("The specified output stream can not write.", "sfxStream");
+ }
+ ValidateSettings(settings);
+ using (Stream sfx = _module == SfxModule.Default
+ ? Assembly.GetExecutingAssembly().GetManifestResourceStream(
+ GetResourceString(SfxSupportedModuleNames[_module][0]))
+ : new FileStream(_moduleFileName, FileMode.Open, FileAccess.Read,
+ FileShare.ReadWrite))
+ {
+ WriteStream(sfx, sfxStream);
+ }
+ if (_module == SfxModule.Custom || _sfxCommands[_module] != null)
+ {
+ using (Stream set = GetSettingsStream(settings))
+ {
+ WriteStream(set, sfxStream);
+ }
+ }
+ WriteStream(archive, sfxStream);
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archiveFileName">The archive file name.</param>
+ /// <param name="sfxFileName">The name of the self-extracting executable.</param>
+ public void MakeSfx(string archiveFileName, string sfxFileName)
+ {
+ using (Stream sfxStream = File.Create(sfxFileName))
+ {
+ using (
+ Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
+ )
+ {
+ MakeSfx(archive, GetDefaultSettings(), sfxStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archiveFileName">The archive file name.</param>
+ /// <param name="sfxStream">The stream to write the self-extracting executable to.</param>
+ public void MakeSfx(string archiveFileName, Stream sfxStream)
+ {
+ using (Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
+ )
+ {
+ MakeSfx(archive, GetDefaultSettings(), sfxStream);
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archiveFileName">The archive file name.</param>
+ /// <param name="settings">The sfx settings.</param>
+ /// <param name="sfxFileName">The name of the self-extracting executable.</param>
+ public void MakeSfx(string archiveFileName, SfxSettings settings, string sfxFileName)
+ {
+ using (Stream sfxStream = File.Create(sfxFileName))
+ {
+ using (
+ Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
+ )
+ {
+ MakeSfx(archive, settings, sfxStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Makes the self-extracting archive.
+ /// </summary>
+ /// <param name="archiveFileName">The archive file name.</param>
+ /// <param name="settings">The sfx settings.</param>
+ /// <param name="sfxStream">The stream to write the self-extracting executable to.</param>
+ public void MakeSfx(string archiveFileName, SfxSettings settings, Stream sfxStream)
+ {
+ using (Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
+ )
+ {
+ MakeSfx(archive, settings, sfxStream);
+ }
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/SevenZip/StreamWrappers.cs b/SevenZip/StreamWrappers.cs
index 22f28abc..4e464235 100644
--- a/SevenZip/StreamWrappers.cs
+++ b/SevenZip/StreamWrappers.cs
@@ -16,6 +16,7 @@
#define DOTNET20
#define UNMANAGED
+#define COMPRESS
using System;
using System.Collections.Generic;