| // ZipFile.Events.cs | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // Copyright (c) 2008, 2009, 2011 Dino Chiesa . | 
 | // All rights reserved. | 
 | // | 
 | // This code module is part of DotNetZip, a zipfile class library. | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // This code is licensed under the Microsoft Public License. | 
 | // See the file License.txt for the license details. | 
 | // More info on: http://dotnetzip.codeplex.com | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // last saved (in emacs): | 
 | // Time-stamp: <2011-July-09 08:42:35> | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // This module defines the methods for issuing events from the ZipFile class. | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 |  | 
 | using System; | 
 | using System.IO; | 
 |  | 
 | namespace OfficeOpenXml.Packaging.Ionic.Zip | 
 | { | 
 |     internal partial class ZipFile | 
 |     { | 
 |         private string ArchiveNameForEvent | 
 |         { | 
 |             get | 
 |             { | 
 |                 return (_name != null) ? _name : "(stream)"; | 
 |             } | 
 |         } | 
 |  | 
 |         #region Save | 
 |  | 
 |         /// <summary> | 
 |         ///   An event handler invoked when a Save() starts, before and after each | 
 |         ///   entry has been written to the archive, when a Save() completes, and | 
 |         ///   during other Save events. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Depending on the particular event, different properties on the <see | 
 |         ///   cref="SaveProgressEventArgs"/> parameter are set.  The following | 
 |         ///   table summarizes the available EventTypes and the conditions under | 
 |         ///   which this event handler is invoked with a | 
 |         ///   <c>SaveProgressEventArgs</c> with the given EventType. | 
 |         /// </para> | 
 |         /// | 
 |         /// <list type="table"> | 
 |         /// <listheader> | 
 |         /// <term>value of EntryType</term> | 
 |         /// <description>Meaning and conditions</description> | 
 |         /// </listheader> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_Started</term> | 
 |         /// <description>Fired when ZipFile.Save() begins. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_BeforeSaveEntry</term> | 
 |         /// <description> | 
 |         ///   Fired within ZipFile.Save(), just before writing data for each | 
 |         ///   particular entry. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_AfterSaveEntry</term> | 
 |         /// <description> | 
 |         ///   Fired within ZipFile.Save(), just after having finished writing data | 
 |         ///   for each particular entry. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_Completed</term> | 
 |         /// <description>Fired when ZipFile.Save() has completed. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_AfterSaveTempArchive</term> | 
 |         /// <description> | 
 |         ///   Fired after the temporary file has been created.  This happens only | 
 |         ///   when saving to a disk file.  This event will not be invoked when | 
 |         ///   saving to a stream. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_BeforeRenameTempArchive</term> | 
 |         /// <description> | 
 |         ///   Fired just before renaming the temporary file to the permanent | 
 |         ///   location.  This happens only when saving to a disk file.  This event | 
 |         ///   will not be invoked when saving to a stream. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_AfterRenameTempArchive</term> | 
 |         /// <description> | 
 |         ///   Fired just after renaming the temporary file to the permanent | 
 |         ///   location.  This happens only when saving to a disk file.  This event | 
 |         ///   will not be invoked when saving to a stream. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_AfterCompileSelfExtractor</term> | 
 |         /// <description> | 
 |         ///   Fired after a self-extracting archive has finished compiling.  This | 
 |         ///   EventType is used only within SaveSelfExtractor(). | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Saving_BytesRead</term> | 
 |         /// <description> | 
 |         ///   Set during the save of a particular entry, to update progress of the | 
 |         ///   Save().  When this EventType is set, the BytesTransferred is the | 
 |         ///   number of bytes that have been read from the source stream.  The | 
 |         ///   TotalBytesToTransfer is the number of bytes in the uncompressed | 
 |         ///   file. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// </list> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         ///    This example uses an anonymous method to handle the | 
 |         ///    SaveProgress event, by updating a progress bar. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// progressBar1.Value = 0; | 
 |         /// progressBar1.Max = listbox1.Items.Count; | 
 |         /// using (ZipFile zip = new ZipFile()) | 
 |         /// { | 
 |         ///    // listbox1 contains a list of filenames | 
 |         ///    zip.AddFiles(listbox1.Items); | 
 |         /// | 
 |         ///    // do the progress bar: | 
 |         ///    zip.SaveProgress += (sender, e) => { | 
 |         ///       if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) { | 
 |         ///          progressBar1.PerformStep(); | 
 |         ///       } | 
 |         ///    }; | 
 |         /// | 
 |         ///    zip.Save(fs); | 
 |         /// } | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <example> | 
 |         ///   This example uses a named method as the | 
 |         ///   <c>SaveProgress</c> event handler, to update the user, in a | 
 |         ///   console-based application. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// static bool justHadByteUpdate= false; | 
 |         /// public static void SaveProgress(object sender, SaveProgressEventArgs e) | 
 |         /// { | 
 |         ///     if (e.EventType == ZipProgressEventType.Saving_Started) | 
 |         ///         Console.WriteLine("Saving: {0}", e.ArchiveName); | 
 |         /// | 
 |         ///     else if (e.EventType == ZipProgressEventType.Saving_Completed) | 
 |         ///     { | 
 |         ///         justHadByteUpdate= false; | 
 |         ///         Console.WriteLine(); | 
 |         ///         Console.WriteLine("Done: {0}", e.ArchiveName); | 
 |         ///     } | 
 |         /// | 
 |         ///     else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) | 
 |         ///     { | 
 |         ///         if (justHadByteUpdate) | 
 |         ///             Console.WriteLine(); | 
 |         ///         Console.WriteLine("  Writing: {0} ({1}/{2})", | 
 |         ///                           e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); | 
 |         ///         justHadByteUpdate= false; | 
 |         ///     } | 
 |         /// | 
 |         ///     else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) | 
 |         ///     { | 
 |         ///         if (justHadByteUpdate) | 
 |         ///             Console.SetCursorPosition(0, Console.CursorTop); | 
 |         ///          Console.Write("     {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, | 
 |         ///                       e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); | 
 |         ///         justHadByteUpdate= true; | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// public static ZipUp(string targetZip, string directory) | 
 |         /// { | 
 |         ///   using (var zip = new ZipFile()) { | 
 |         ///     zip.SaveProgress += SaveProgress; | 
 |         ///     zip.AddDirectory(directory); | 
 |         ///     zip.Save(targetZip); | 
 |         ///   } | 
 |         /// } | 
 |         /// | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String) | 
 |         ///     Using zip As ZipFile = New ZipFile | 
 |         ///         AddHandler zip.SaveProgress, AddressOf MySaveProgress | 
 |         ///         zip.AddDirectory(directory) | 
 |         ///         zip.Save(targetZip) | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// Private Shared justHadByteUpdate As Boolean = False | 
 |         /// | 
 |         /// Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs) | 
 |         ///     If (e.EventType Is ZipProgressEventType.Saving_Started) Then | 
 |         ///         Console.WriteLine("Saving: {0}", e.ArchiveName) | 
 |         /// | 
 |         ///     ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then | 
 |         ///         justHadByteUpdate = False | 
 |         ///         Console.WriteLine | 
 |         ///         Console.WriteLine("Done: {0}", e.ArchiveName) | 
 |         /// | 
 |         ///     ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then | 
 |         ///         If justHadByteUpdate Then | 
 |         ///             Console.WriteLine | 
 |         ///         End If | 
 |         ///         Console.WriteLine("  Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) | 
 |         ///         justHadByteUpdate = False | 
 |         /// | 
 |         ///     ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then | 
 |         ///         If justHadByteUpdate Then | 
 |         ///             Console.SetCursorPosition(0, Console.CursorTop) | 
 |         ///         End If | 
 |         ///         Console.Write("     {0}/{1} ({2:N0}%)", e.BytesTransferred, _ | 
 |         ///                       e.TotalBytesToTransfer, _ | 
 |         ///                       (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) | 
 |         ///         justHadByteUpdate = True | 
 |         ///     End If | 
 |         /// End Sub | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         /// This is a more complete example of using the SaveProgress | 
 |         /// events in a Windows Forms application, with a | 
 |         /// Thread object. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// delegate void SaveEntryProgress(SaveProgressEventArgs e); | 
 |         /// delegate void ButtonClick(object sender, EventArgs e); | 
 |         /// | 
 |         /// internal class WorkerOptions | 
 |         /// { | 
 |         ///     public string ZipName; | 
 |         ///     public string Folder; | 
 |         ///     public string Encoding; | 
 |         ///     public string Comment; | 
 |         ///     public int ZipFlavor; | 
 |         ///     public Zip64Option Zip64; | 
 |         /// } | 
 |         /// | 
 |         /// private int _progress2MaxFactor; | 
 |         /// private bool _saveCanceled; | 
 |         /// private long _totalBytesBeforeCompress; | 
 |         /// private long _totalBytesAfterCompress; | 
 |         /// private Thread _workerThread; | 
 |         /// | 
 |         /// | 
 |         /// private void btnZipup_Click(object sender, EventArgs e) | 
 |         /// { | 
 |         ///     KickoffZipup(); | 
 |         /// } | 
 |         /// | 
 |         /// private void btnCancel_Click(object sender, EventArgs e) | 
 |         /// { | 
 |         ///     if (this.lblStatus.InvokeRequired) | 
 |         ///     { | 
 |         ///         this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); | 
 |         ///     } | 
 |         ///     else | 
 |         ///     { | 
 |         ///         _saveCanceled = true; | 
 |         ///         lblStatus.Text = "Canceled..."; | 
 |         ///         ResetState(); | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// private void KickoffZipup() | 
 |         /// { | 
 |         ///     _folderName = tbDirName.Text; | 
 |         /// | 
 |         ///     if (_folderName == null || _folderName == "") return; | 
 |         ///     if (this.tbZipName.Text == null || this.tbZipName.Text == "") return; | 
 |         /// | 
 |         ///     // check for existence of the zip file: | 
 |         ///     if (System.IO.File.Exists(this.tbZipName.Text)) | 
 |         ///     { | 
 |         ///         var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." + | 
 |         ///                                                       "  Do you want to overwrite this file?", this.tbZipName.Text), | 
 |         ///                                         "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question); | 
 |         ///         if (dlgResult != DialogResult.Yes) return; | 
 |         ///         System.IO.File.Delete(this.tbZipName.Text); | 
 |         ///     } | 
 |         /// | 
 |         ///      _saveCanceled = false; | 
 |         ///     _nFilesCompleted = 0; | 
 |         ///     _totalBytesAfterCompress = 0; | 
 |         ///     _totalBytesBeforeCompress = 0; | 
 |         ///     this.btnOk.Enabled = false; | 
 |         ///     this.btnOk.Text = "Zipping..."; | 
 |         ///     this.btnCancel.Enabled = true; | 
 |         ///     lblStatus.Text = "Zipping..."; | 
 |         /// | 
 |         ///     var options = new WorkerOptions | 
 |         ///     { | 
 |         ///         ZipName = this.tbZipName.Text, | 
 |         ///         Folder = _folderName, | 
 |         ///         Encoding = "ibm437" | 
 |         ///     }; | 
 |         /// | 
 |         ///     if (this.comboBox1.SelectedIndex != 0) | 
 |         ///     { | 
 |         ///         options.Encoding = this.comboBox1.SelectedItem.ToString(); | 
 |         ///     } | 
 |         /// | 
 |         ///     if (this.radioFlavorSfxCmd.Checked) | 
 |         ///         options.ZipFlavor = 2; | 
 |         ///     else if (this.radioFlavorSfxGui.Checked) | 
 |         ///         options.ZipFlavor = 1; | 
 |         ///     else options.ZipFlavor = 0; | 
 |         /// | 
 |         ///     if (this.radioZip64AsNecessary.Checked) | 
 |         ///         options.Zip64 = Zip64Option.AsNecessary; | 
 |         ///     else if (this.radioZip64Always.Checked) | 
 |         ///         options.Zip64 = Zip64Option.Always; | 
 |         ///     else options.Zip64 = Zip64Option.Never; | 
 |         /// | 
 |         ///     options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n", | 
 |         ///                 options.Encoding, | 
 |         ///                 FlavorToString(options.ZipFlavor), | 
 |         ///                 options.Zip64.ToString(), | 
 |         ///                 System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"), | 
 |         ///                 this.Text); | 
 |         /// | 
 |         ///     if (this.tbComment.Text != TB_COMMENT_NOTE) | 
 |         ///         options.Comment += this.tbComment.Text; | 
 |         /// | 
 |         ///     _workerThread = new Thread(this.DoSave); | 
 |         ///     _workerThread.Name = "Zip Saver thread"; | 
 |         ///     _workerThread.Start(options); | 
 |         ///     this.Cursor = Cursors.WaitCursor; | 
 |         ///  } | 
 |         /// | 
 |         /// | 
 |         /// private void DoSave(Object p) | 
 |         /// { | 
 |         ///     WorkerOptions options = p as WorkerOptions; | 
 |         ///     try | 
 |         ///     { | 
 |         ///         using (var zip1 = new ZipFile()) | 
 |         ///         { | 
 |         ///             zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding); | 
 |         ///             zip1.Comment = options.Comment; | 
 |         ///             zip1.AddDirectory(options.Folder); | 
 |         ///             _entriesToZip = zip1.EntryFileNames.Count; | 
 |         ///             SetProgressBars(); | 
 |         ///             zip1.SaveProgress += this.zip1_SaveProgress; | 
 |         /// | 
 |         ///             zip1.UseZip64WhenSaving = options.Zip64; | 
 |         /// | 
 |         ///             if (options.ZipFlavor == 1) | 
 |         ///                 zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication); | 
 |         ///             else if (options.ZipFlavor == 2) | 
 |         ///                 zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication); | 
 |         ///             else | 
 |         ///                 zip1.Save(options.ZipName); | 
 |         ///         } | 
 |         ///     } | 
 |         ///     catch (System.Exception exc1) | 
 |         ///     { | 
 |         ///         MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message)); | 
 |         ///         btnCancel_Click(null, null); | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// | 
 |         /// | 
 |         /// void zip1_SaveProgress(object sender, SaveProgressEventArgs e) | 
 |         /// { | 
 |         ///     switch (e.EventType) | 
 |         ///     { | 
 |         ///         case ZipProgressEventType.Saving_AfterWriteEntry: | 
 |         ///             StepArchiveProgress(e); | 
 |         ///             break; | 
 |         ///         case ZipProgressEventType.Saving_EntryBytesRead: | 
 |         ///             StepEntryProgress(e); | 
 |         ///             break; | 
 |         ///         case ZipProgressEventType.Saving_Completed: | 
 |         ///             SaveCompleted(); | 
 |         ///             break; | 
 |         ///         case ZipProgressEventType.Saving_AfterSaveTempArchive: | 
 |         ///             // this event only occurs when saving an SFX file | 
 |         ///             TempArchiveSaved(); | 
 |         ///             break; | 
 |         ///     } | 
 |         ///     if (_saveCanceled) | 
 |         ///         e.Cancel = true; | 
 |         /// } | 
 |         /// | 
 |         /// | 
 |         /// | 
 |         /// private void StepArchiveProgress(SaveProgressEventArgs e) | 
 |         /// { | 
 |         ///     if (this.progressBar1.InvokeRequired) | 
 |         ///     { | 
 |         ///         this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); | 
 |         ///     } | 
 |         ///     else | 
 |         ///     { | 
 |         ///         if (!_saveCanceled) | 
 |         ///         { | 
 |         ///             _nFilesCompleted++; | 
 |         ///             this.progressBar1.PerformStep(); | 
 |         ///             _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; | 
 |         ///             _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; | 
 |         /// | 
 |         ///             // reset the progress bar for the entry: | 
 |         ///             this.progressBar2.Value = this.progressBar2.Maximum = 1; | 
 |         /// | 
 |         ///             this.Update(); | 
 |         ///         } | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// | 
 |         /// private void StepEntryProgress(SaveProgressEventArgs e) | 
 |         /// { | 
 |         ///     if (this.progressBar2.InvokeRequired) | 
 |         ///     { | 
 |         ///         this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); | 
 |         ///     } | 
 |         ///     else | 
 |         ///     { | 
 |         ///         if (!_saveCanceled) | 
 |         ///         { | 
 |         ///             if (this.progressBar2.Maximum == 1) | 
 |         ///             { | 
 |         ///                 // reset | 
 |         ///                 Int64 max = e.TotalBytesToTransfer; | 
 |         ///                 _progress2MaxFactor = 0; | 
 |         ///                 while (max > System.Int32.MaxValue) | 
 |         ///                 { | 
 |         ///                     max /= 2; | 
 |         ///                     _progress2MaxFactor++; | 
 |         ///                 } | 
 |         ///                 this.progressBar2.Maximum = (int)max; | 
 |         ///                 lblStatus.Text = String.Format("{0} of {1} files...({2})", | 
 |         ///                     _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName); | 
 |         ///             } | 
 |         /// | 
 |         ///              int xferred = e.BytesTransferred >> _progress2MaxFactor; | 
 |         /// | 
 |         ///              this.progressBar2.Value = (xferred >= this.progressBar2.Maximum) | 
 |         ///                 ? this.progressBar2.Maximum | 
 |         ///                 : xferred; | 
 |         /// | 
 |         ///              this.Update(); | 
 |         ///         } | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// private void SaveCompleted() | 
 |         /// { | 
 |         ///     if (this.lblStatus.InvokeRequired) | 
 |         ///     { | 
 |         ///         this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted)); | 
 |         ///     } | 
 |         ///     else | 
 |         ///     { | 
 |         ///         lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.", | 
 |         ///             _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress); | 
 |         ///          ResetState(); | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// private void ResetState() | 
 |         /// { | 
 |         ///     this.btnCancel.Enabled = false; | 
 |         ///     this.btnOk.Enabled = true; | 
 |         ///     this.btnOk.Text = "Zip it!"; | 
 |         ///     this.progressBar1.Value = 0; | 
 |         ///     this.progressBar2.Value = 0; | 
 |         ///     this.Cursor = Cursors.Default; | 
 |         ///     if (!_workerThread.IsAlive) | 
 |         ///         _workerThread.Join(); | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/> | 
 |         internal event EventHandler<SaveProgressEventArgs> SaveProgress; | 
 |  | 
 |  | 
 |         internal bool OnSaveBlock(ZipEntry entry, Int64 bytesXferred, Int64 totalBytesToXfer) | 
 |         { | 
 |             EventHandler<SaveProgressEventArgs> sp = SaveProgress; | 
 |             if (sp != null) | 
 |             { | 
 |                 var e = SaveProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, | 
 |                                                          bytesXferred, totalBytesToXfer); | 
 |                 sp(this, e); | 
 |                 if (e.Cancel) | 
 |                     _saveOperationCanceled = true; | 
 |             } | 
 |             return _saveOperationCanceled; | 
 |         } | 
 |  | 
 |         private void OnSaveEntry(int current, ZipEntry entry, bool before) | 
 |         { | 
 |             EventHandler<SaveProgressEventArgs> sp = SaveProgress; | 
 |             if (sp != null) | 
 |             { | 
 |                 var e = new SaveProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, entry); | 
 |                 sp(this, e); | 
 |                 if (e.Cancel) | 
 |                     _saveOperationCanceled = true; | 
 |             } | 
 |         } | 
 |  | 
 |         private void OnSaveEvent(ZipProgressEventType eventFlavor) | 
 |         { | 
 |             EventHandler<SaveProgressEventArgs> sp = SaveProgress; | 
 |             if (sp != null) | 
 |             { | 
 |                 var e = new SaveProgressEventArgs(ArchiveNameForEvent, eventFlavor); | 
 |                 sp(this, e); | 
 |                 if (e.Cancel) | 
 |                     _saveOperationCanceled = true; | 
 |             } | 
 |         } | 
 |  | 
 |         private void OnSaveStarted() | 
 |         { | 
 |             EventHandler<SaveProgressEventArgs> sp = SaveProgress; | 
 |             if (sp != null) | 
 |             { | 
 |                 var e = SaveProgressEventArgs.Started(ArchiveNameForEvent); | 
 |                 sp(this, e); | 
 |                 if (e.Cancel) | 
 |                     _saveOperationCanceled = true; | 
 |             } | 
 |         } | 
 |         private void OnSaveCompleted() | 
 |         { | 
 |             EventHandler<SaveProgressEventArgs> sp = SaveProgress; | 
 |             if (sp != null) | 
 |             { | 
 |                 var e = SaveProgressEventArgs.Completed(ArchiveNameForEvent); | 
 |                 sp(this, e); | 
 |             } | 
 |         } | 
 |         #endregion | 
 |  | 
 |  | 
 |         #region Read | 
 |         /// <summary> | 
 |         /// An event handler invoked before, during, and after the reading of a zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         /// Depending on the particular event being signaled, different properties on the | 
 |         /// <see cref="ReadProgressEventArgs"/> parameter are set.  The following table | 
 |         /// summarizes the available EventTypes and the conditions under which this | 
 |         /// event handler is invoked with a <c>ReadProgressEventArgs</c> with the given EventType. | 
 |         /// </para> | 
 |         /// | 
 |         /// <list type="table"> | 
 |         /// <listheader> | 
 |         /// <term>value of EntryType</term> | 
 |         /// <description>Meaning and conditions</description> | 
 |         /// </listheader> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Reading_Started</term> | 
 |         /// <description>Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Reading_Completed</term> | 
 |         /// <description>Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Reading_ArchiveBytesRead</term> | 
 |         /// <description>Fired while reading, updates the number of bytes read for the entire archive. | 
 |         /// Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Reading_BeforeReadEntry</term> | 
 |         /// <description>Indicates an entry is about to be read from the archive. | 
 |         /// Meaningful properties: ArchiveName, EntriesTotal. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Reading_AfterReadEntry</term> | 
 |         /// <description>Indicates an entry has just been read from the archive. | 
 |         /// Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// </list> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/> | 
 |         internal event EventHandler<ReadProgressEventArgs> ReadProgress; | 
 |  | 
 |         private void OnReadStarted() | 
 |         { | 
 |             EventHandler<ReadProgressEventArgs> rp = ReadProgress; | 
 |             if (rp != null) | 
 |             { | 
 |                     var e = ReadProgressEventArgs.Started(ArchiveNameForEvent); | 
 |                     rp(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |         private void OnReadCompleted() | 
 |         { | 
 |             EventHandler<ReadProgressEventArgs> rp = ReadProgress; | 
 |             if (rp != null) | 
 |             { | 
 |                     var e = ReadProgressEventArgs.Completed(ArchiveNameForEvent); | 
 |                     rp(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |         internal void OnReadBytes(ZipEntry entry) | 
 |         { | 
 |             EventHandler<ReadProgressEventArgs> rp = ReadProgress; | 
 |             if (rp != null) | 
 |             { | 
 |                     var e = ReadProgressEventArgs.ByteUpdate(ArchiveNameForEvent, | 
 |                                         entry, | 
 |                                         ReadStream.Position, | 
 |                                         LengthOfReadStream); | 
 |                     rp(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |         internal void OnReadEntry(bool before, ZipEntry entry) | 
 |         { | 
 |             EventHandler<ReadProgressEventArgs> rp = ReadProgress; | 
 |             if (rp != null) | 
 |             { | 
 |                 ReadProgressEventArgs e = (before) | 
 |                     ? ReadProgressEventArgs.Before(ArchiveNameForEvent, _entries.Count) | 
 |                     : ReadProgressEventArgs.After(ArchiveNameForEvent, entry, _entries.Count); | 
 |                 rp(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |         private Int64 _lengthOfReadStream = -99; | 
 |         private Int64 LengthOfReadStream | 
 |         { | 
 |             get | 
 |             { | 
 |                 if (_lengthOfReadStream == -99) | 
 |                 { | 
 |                     _lengthOfReadStream = (_ReadStreamIsOurs) | 
 |                         ? SharedUtilities.GetFileLength(_name) | 
 |                         : -1L; | 
 |                 } | 
 |                 return _lengthOfReadStream; | 
 |             } | 
 |         } | 
 |         #endregion | 
 |  | 
 |  | 
 |         #region Extract | 
 |         /// <summary> | 
 |         ///   An event handler invoked before, during, and after extraction of | 
 |         ///   entries in the zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Depending on the particular event, different properties on the <see | 
 |         ///   cref="ExtractProgressEventArgs"/> parameter are set.  The following | 
 |         ///   table summarizes the available EventTypes and the conditions under | 
 |         ///   which this event handler is invoked with a | 
 |         ///   <c>ExtractProgressEventArgs</c> with the given EventType. | 
 |         /// </para> | 
 |         /// | 
 |         /// <list type="table"> | 
 |         /// <listheader> | 
 |         /// <term>value of EntryType</term> | 
 |         /// <description>Meaning and conditions</description> | 
 |         /// </listheader> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_BeforeExtractAll</term> | 
 |         /// <description> | 
 |         ///   Set when ExtractAll() begins. The ArchiveName, Overwrite, and | 
 |         ///   ExtractLocation properties are meaningful.</description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_AfterExtractAll</term> | 
 |         /// <description> | 
 |         ///   Set when ExtractAll() has completed.  The ArchiveName, Overwrite, | 
 |         ///   and ExtractLocation properties are meaningful. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_BeforeExtractEntry</term> | 
 |         /// <description> | 
 |         ///   Set when an Extract() on an entry in the ZipFile has begun. | 
 |         ///   Properties that are meaningful: ArchiveName, EntriesTotal, | 
 |         ///   CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_AfterExtractEntry</term> | 
 |         /// <description> | 
 |         ///   Set when an Extract() on an entry in the ZipFile has completed. | 
 |         ///   Properties that are meaningful: ArchiveName, EntriesTotal, | 
 |         ///   CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_EntryBytesWritten</term> | 
 |         /// <description> | 
 |         ///   Set within a call to Extract() on an entry in the ZipFile, as data | 
 |         ///   is extracted for the entry.  Properties that are meaningful: | 
 |         ///   ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         /// <term>ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite</term> | 
 |         /// <description> | 
 |         ///   Set within a call to Extract() on an entry in the ZipFile, when the | 
 |         ///   extraction would overwrite an existing file. This event type is used | 
 |         ///   only when <c>ExtractExistingFileAction</c> on the <c>ZipFile</c> or | 
 |         ///   <c>ZipEntry</c> is set to <c>InvokeExtractProgressEvent</c>. | 
 |         /// </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// </list> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <code> | 
 |         /// private static bool justHadByteUpdate = false; | 
 |         /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e) | 
 |         /// { | 
 |         ///   if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) | 
 |         ///   { | 
 |         ///     if (justHadByteUpdate) | 
 |         ///       Console.SetCursorPosition(0, Console.CursorTop); | 
 |         /// | 
 |         ///     Console.Write("   {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, | 
 |         ///                   e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); | 
 |         ///     justHadByteUpdate = true; | 
 |         ///   } | 
 |         ///   else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) | 
 |         ///   { | 
 |         ///     if (justHadByteUpdate) | 
 |         ///       Console.WriteLine(); | 
 |         ///     Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName); | 
 |         ///     justHadByteUpdate= false; | 
 |         ///   } | 
 |         /// } | 
 |         /// | 
 |         /// public static ExtractZip(string zipToExtract, string directory) | 
 |         /// { | 
 |         ///   string TargetDirectory= "extract"; | 
 |         ///   using (var zip = ZipFile.Read(zipToExtract)) { | 
 |         ///     zip.ExtractProgress += ExtractProgress; | 
 |         ///     foreach (var e in zip1) | 
 |         ///     { | 
 |         ///       e.Extract(TargetDirectory, true); | 
 |         ///     } | 
 |         ///   } | 
 |         /// } | 
 |         /// | 
 |         /// </code> | 
 |         /// <code lang="VB"> | 
 |         /// Public Shared Sub Main(ByVal args As String()) | 
 |         ///     Dim ZipToUnpack As String = "C1P3SML.zip" | 
 |         ///     Dim TargetDir As String = "ExtractTest_Extract" | 
 |         ///     Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir) | 
 |         ///     Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack) | 
 |         ///         AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress | 
 |         ///         Dim e As ZipEntry | 
 |         ///         For Each e In zip1 | 
 |         ///             e.Extract(TargetDir, True) | 
 |         ///         Next | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// Private Shared justHadByteUpdate As Boolean = False | 
 |         /// | 
 |         /// Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) | 
 |         ///     If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then | 
 |         ///         If ExtractTest.justHadByteUpdate Then | 
 |         ///             Console.SetCursorPosition(0, Console.CursorTop) | 
 |         ///         End If | 
 |         ///         Console.Write("   {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) | 
 |         ///         ExtractTest.justHadByteUpdate = True | 
 |         ///     ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then | 
 |         ///         If ExtractTest.justHadByteUpdate Then | 
 |         ///             Console.WriteLine | 
 |         ///         End If | 
 |         ///         Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) | 
 |         ///         ExtractTest.justHadByteUpdate = False | 
 |         ///     End If | 
 |         /// End Sub | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddProgress"/> | 
 |         internal event EventHandler<ExtractProgressEventArgs> ExtractProgress; | 
 |  | 
 |  | 
 |  | 
 |         private void OnExtractEntry(int current, bool before, ZipEntry currentEntry, string path) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = new ExtractProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, currentEntry, path); | 
 |                 ep(this, e); | 
 |                 if (e.Cancel) | 
 |                     _extractOperationCanceled = true; | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         // Can be called from within ZipEntry._ExtractOne. | 
 |         internal bool OnExtractBlock(ZipEntry entry, Int64 bytesWritten, Int64 totalBytesToWrite) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = ExtractProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, | 
 |                                                             bytesWritten, totalBytesToWrite); | 
 |                 ep(this, e); | 
 |                 if (e.Cancel) | 
 |                     _extractOperationCanceled = true; | 
 |             } | 
 |             return _extractOperationCanceled; | 
 |         } | 
 |  | 
 |  | 
 |         // Can be called from within ZipEntry.InternalExtract. | 
 |         internal bool OnSingleEntryExtract(ZipEntry entry, string path, bool before) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = (before) | 
 |                     ? ExtractProgressEventArgs.BeforeExtractEntry(ArchiveNameForEvent, entry, path) | 
 |                     : ExtractProgressEventArgs.AfterExtractEntry(ArchiveNameForEvent, entry, path); | 
 |                 ep(this, e); | 
 |                 if (e.Cancel) | 
 |                     _extractOperationCanceled = true; | 
 |             } | 
 |             return _extractOperationCanceled; | 
 |         } | 
 |  | 
 |         internal bool OnExtractExisting(ZipEntry entry, string path) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = ExtractProgressEventArgs.ExtractExisting(ArchiveNameForEvent, entry, path); | 
 |                 ep(this, e); | 
 |                 if (e.Cancel) | 
 |                     _extractOperationCanceled = true; | 
 |             } | 
 |             return _extractOperationCanceled; | 
 |         } | 
 |  | 
 |  | 
 |         private void OnExtractAllCompleted(string path) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = ExtractProgressEventArgs.ExtractAllCompleted(ArchiveNameForEvent, | 
 |                                                                      path ); | 
 |                 ep(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         private void OnExtractAllStarted(string path) | 
 |         { | 
 |             EventHandler<ExtractProgressEventArgs> ep = ExtractProgress; | 
 |             if (ep != null) | 
 |             { | 
 |                 var e = ExtractProgressEventArgs.ExtractAllStarted(ArchiveNameForEvent, | 
 |                                                                    path ); | 
 |                 ep(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         #endregion | 
 |  | 
 |  | 
 |  | 
 |         #region Add | 
 |         /// <summary> | 
 |         /// An event handler invoked before, during, and after Adding entries to a zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///     Adding a large number of entries to a zip file can take a long | 
 |         ///     time.  For example, when calling <see cref="AddDirectory(string)"/> on a | 
 |         ///     directory that contains 50,000 files, it could take 3 minutes or so. | 
 |         ///     This event handler allws an application to track the progress of the Add | 
 |         ///     operation, and to optionally cancel a lengthy Add operation. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <code lang="C#"> | 
 |         /// | 
 |         /// int _numEntriesToAdd= 0; | 
 |         /// int _numEntriesAdded= 0; | 
 |         /// void AddProgressHandler(object sender, AddProgressEventArgs e) | 
 |         /// { | 
 |         ///     switch (e.EventType) | 
 |         ///     { | 
 |         ///         case ZipProgressEventType.Adding_Started: | 
 |         ///             Console.WriteLine("Adding files to the zip..."); | 
 |         ///             break; | 
 |         ///         case ZipProgressEventType.Adding_AfterAddEntry: | 
 |         ///             _numEntriesAdded++; | 
 |         ///             Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}", | 
 |         ///                                      _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName)); | 
 |         ///             break; | 
 |         ///         case ZipProgressEventType.Adding_Completed: | 
 |         ///             Console.WriteLine("Added all files"); | 
 |         ///             break; | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// void CreateTheZip() | 
 |         /// { | 
 |         ///     using (ZipFile zip = new ZipFile()) | 
 |         ///     { | 
 |         ///         zip.AddProgress += AddProgressHandler; | 
 |         ///         zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)); | 
 |         ///         zip.Save(ZipFileToCreate); | 
 |         ///     } | 
 |         /// } | 
 |         /// | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// | 
 |         /// Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs) | 
 |         ///     Select Case e.EventType | 
 |         ///         Case ZipProgressEventType.Adding_Started | 
 |         ///             Console.WriteLine("Adding files to the zip...") | 
 |         ///             Exit Select | 
 |         ///         Case ZipProgressEventType.Adding_AfterAddEntry | 
 |         ///             Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName)) | 
 |         ///             Exit Select | 
 |         ///         Case ZipProgressEventType.Adding_Completed | 
 |         ///             Console.WriteLine("Added all files") | 
 |         ///             Exit Select | 
 |         ///     End Select | 
 |         /// End Sub | 
 |         /// | 
 |         /// Sub CreateTheZip() | 
 |         ///     Using zip as ZipFile = New ZipFile | 
 |         ///         AddHandler zip.AddProgress, AddressOf AddProgressHandler | 
 |         ///         zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)) | 
 |         ///         zip.Save(ZipFileToCreate); | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// </code> | 
 |         /// | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.SaveProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ReadProgress"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ExtractProgress"/> | 
 |         internal event EventHandler<AddProgressEventArgs> AddProgress; | 
 |  | 
 |         private void OnAddStarted() | 
 |         { | 
 |             EventHandler<AddProgressEventArgs> ap = AddProgress; | 
 |             if (ap != null) | 
 |             { | 
 |                 var e = AddProgressEventArgs.Started(ArchiveNameForEvent); | 
 |                 ap(this, e); | 
 |                 if (e.Cancel) // workitem 13371 | 
 |                     _addOperationCanceled = true; | 
 |             } | 
 |         } | 
 |  | 
 |         private void OnAddCompleted() | 
 |         { | 
 |             EventHandler<AddProgressEventArgs> ap = AddProgress; | 
 |             if (ap != null) | 
 |             { | 
 |                 var e = AddProgressEventArgs.Completed(ArchiveNameForEvent); | 
 |                 ap(this, e); | 
 |             } | 
 |         } | 
 |  | 
 |         internal void AfterAddEntry(ZipEntry entry) | 
 |         { | 
 |             EventHandler<AddProgressEventArgs> ap = AddProgress; | 
 |             if (ap != null) | 
 |             { | 
 |                 var e = AddProgressEventArgs.AfterEntry(ArchiveNameForEvent, entry, _entries.Count); | 
 |                 ap(this, e); | 
 |                 if (e.Cancel) // workitem 13371 | 
 |                     _addOperationCanceled = true; | 
 |             } | 
 |         } | 
 |  | 
 |         #endregion | 
 |  | 
 |  | 
 |  | 
 |         #region Error | 
 |         /// <summary> | 
 |         /// An event that is raised when an error occurs during open or read of files | 
 |         /// while saving a zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///  <para> | 
 |         ///     Errors can occur as a file is being saved to the zip archive.  For | 
 |         ///     example, the File.Open may fail, or a File.Read may fail, because of | 
 |         ///     lock conflicts or other reasons.  If you add a handler to this event, | 
 |         ///     you can handle such errors in your own code.  If you don't add a | 
 |         ///     handler, the library will throw an exception if it encounters an I/O | 
 |         ///     error during a call to <c>Save()</c>. | 
 |         ///  </para> | 
 |         /// | 
 |         ///  <para> | 
 |         ///    Setting a handler implicitly sets <see cref="ZipFile.ZipErrorAction"/> to | 
 |         ///    <c>ZipErrorAction.InvokeErrorEvent</c>. | 
 |         ///  </para> | 
 |         /// | 
 |         ///  <para> | 
 |         ///    The handler you add applies to all <see cref="ZipEntry"/> items that are | 
 |         ///    subsequently added to the <c>ZipFile</c> instance. If you set this | 
 |         ///    property after you have added items to the <c>ZipFile</c>, but before you | 
 |         ///    have called <c>Save()</c>, errors that occur while saving those items | 
 |         ///    will not cause the error handler to be invoked. | 
 |         ///  </para> | 
 |         /// | 
 |         ///  <para> | 
 |         ///    If you want to handle any errors that occur with any entry in the zip | 
 |         ///    file using the same error handler, then add your error handler once, | 
 |         ///    before adding any entries to the zip archive. | 
 |         ///  </para> | 
 |         /// | 
 |         ///  <para> | 
 |         ///    In the error handler method, you need to set the <see | 
 |         ///    cref="ZipEntry.ZipErrorAction"/> property on the | 
 |         ///    <c>ZipErrorEventArgs.CurrentEntry</c>.  This communicates back to | 
 |         ///    DotNetZip what you would like to do with this particular error.  Within | 
 |         ///    an error handler, if you set the <c>ZipEntry.ZipErrorAction</c> property | 
 |         ///    on the <c>ZipEntry</c> to <c>ZipErrorAction.InvokeErrorEvent</c> or if | 
 |         ///    you don't set it at all, the library will throw the exception. (It is the | 
 |         ///    same as if you had set the <c>ZipEntry.ZipErrorAction</c> property on the | 
 |         ///    <c>ZipEntry</c> to <c>ZipErrorAction.Throw</c>.) If you set the | 
 |         ///    <c>ZipErrorEventArgs.Cancel</c> to true, the entire <c>Save()</c> will be | 
 |         ///    canceled. | 
 |         ///  </para> | 
 |         /// | 
 |         ///  <para> | 
 |         ///    In the case that you use <c>ZipErrorAction.Skip</c>, implying that | 
 |         ///    you want to skip the entry for which there's been an error, DotNetZip | 
 |         ///    tries to seek backwards in the output stream, and truncate all bytes | 
 |         ///    written on behalf of that particular entry. This works only if the | 
 |         ///    output stream is seekable.  It will not work, for example, when using | 
 |         ///    ASPNET's Response.OutputStream. | 
 |         ///  </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         /// This example shows how to use an event handler to handle | 
 |         /// errors during save of the zip file. | 
 |         /// <code lang="C#"> | 
 |         /// | 
 |         /// public static void MyZipError(object sender, ZipErrorEventArgs e) | 
 |         /// { | 
 |         ///     Console.WriteLine("Error saving {0}...", e.FileName); | 
 |         ///     Console.WriteLine("   Exception: {0}", e.exception); | 
 |         ///     ZipEntry entry = e.CurrentEntry; | 
 |         ///     string response = null; | 
 |         ///     // Ask the user whether he wants to skip this error or not | 
 |         ///     do | 
 |         ///     { | 
 |         ///         Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) "); | 
 |         ///         response = Console.ReadLine(); | 
 |         ///         Console.WriteLine(); | 
 |         /// | 
 |         ///     } while (response != null && | 
 |         ///              response[0]!='S' && response[0]!='s' && | 
 |         ///              response[0]!='R' && response[0]!='r' && | 
 |         ///              response[0]!='T' && response[0]!='t' && | 
 |         ///              response[0]!='C' && response[0]!='c'); | 
 |         /// | 
 |         ///     e.Cancel = (response[0]=='C' || response[0]=='c'); | 
 |         /// | 
 |         ///     if (response[0]=='S' || response[0]=='s') | 
 |         ///         entry.ZipErrorAction = ZipErrorAction.Skip; | 
 |         ///     else if (response[0]=='R' || response[0]=='r') | 
 |         ///         entry.ZipErrorAction = ZipErrorAction.Retry; | 
 |         ///     else if (response[0]=='T' || response[0]=='t') | 
 |         ///         entry.ZipErrorAction = ZipErrorAction.Throw; | 
 |         /// } | 
 |         /// | 
 |         /// public void SaveTheFile() | 
 |         /// { | 
 |         ///   string directoryToZip = "fodder"; | 
 |         ///   string directoryInArchive = "files"; | 
 |         ///   string zipFileToCreate = "Archive.zip"; | 
 |         ///   using (var zip = new ZipFile()) | 
 |         ///   { | 
 |         ///     // set the event handler before adding any entries | 
 |         ///     zip.ZipError += MyZipError; | 
 |         ///     zip.AddDirectory(directoryToZip, directoryInArchive); | 
 |         ///     zip.Save(zipFileToCreate); | 
 |         ///   } | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs) | 
 |         ///     ' At this point, the application could prompt the user for an action to take. | 
 |         ///     ' But in this case, this application will simply automatically skip the file, in case of error. | 
 |         ///     Console.WriteLine("Zip Error,  entry {0}", e.CurrentEntry.FileName) | 
 |         ///     Console.WriteLine("   Exception: {0}", e.exception) | 
 |         ///     ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip | 
 |         ///     e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip | 
 |         /// End Sub | 
 |         /// | 
 |         /// Public Sub SaveTheFile() | 
 |         ///     Dim directoryToZip As String = "fodder" | 
 |         ///     Dim directoryInArchive As String = "files" | 
 |         ///     Dim zipFileToCreate as String = "Archive.zip" | 
 |         ///     Using zipArchive As ZipFile = New ZipFile | 
 |         ///         ' set the event handler before adding any entries | 
 |         ///         AddHandler zipArchive.ZipError, AddressOf MyZipError | 
 |         ///         zipArchive.AddDirectory(directoryToZip, directoryInArchive) | 
 |         ///         zipArchive.Save(zipFileToCreate) | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.ZipErrorAction"/> | 
 |         internal event EventHandler<ZipErrorEventArgs> ZipError; | 
 |  | 
 |         internal bool OnZipErrorSaving(ZipEntry entry, Exception exc) | 
 |         { | 
 |             if (ZipError != null) | 
 |             { | 
 |                 lock (LOCK) | 
 |                 { | 
 |                     var e = ZipErrorEventArgs.Saving(this.Name, entry, exc); | 
 |                     ZipError(this, e); | 
 |                     if (e.Cancel) | 
 |                         _saveOperationCanceled = true; | 
 |                 } | 
 |             } | 
 |             return _saveOperationCanceled; | 
 |         } | 
 |         #endregion | 
 |  | 
 |     } | 
 | } |