| // ZipFile.AddUpdate.cs | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // Copyright (c) 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-November-01 13:56:58> | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // This module defines the methods for Adding and Updating entries in | 
 | // the ZipFile. | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 |  | 
 |  | 
 | using System; | 
 | using System.IO; | 
 | using System.Collections.Generic; | 
 |  | 
 | namespace OfficeOpenXml.Packaging.Ionic.Zip | 
 | { | 
 |     internal partial class ZipFile | 
 |     { | 
 |         /// <summary> | 
 |         ///   Adds an item, either a file or a directory, to a zip file archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This method is handy if you are adding things to zip archive and don't | 
 |         ///   want to bother distinguishing between directories or files.  Any files are | 
 |         ///   added as single entries.  A directory added through this method is added | 
 |         ///   recursively: all files and subdirectories contained within the directory | 
 |         ///   are added to the <c>ZipFile</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The name of the item may be a relative path or a fully-qualified | 
 |         ///   path. Remember, the items contained in <c>ZipFile</c> instance get written | 
 |         ///   to the disk only when you call <see cref="ZipFile.Save()"/> or a similar | 
 |         ///   save method. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The directory name used for the file within the archive is the same | 
 |         ///   as the directory name (potentially a relative path) specified in the | 
 |         ///   <paramref name="fileOrDirectoryName"/>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/> | 
 |         /// | 
 |         /// <overloads>This method has two overloads.</overloads> | 
 |         /// <param name="fileOrDirectoryName"> | 
 |         /// the name of the file or directory to add.</param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddItem(string fileOrDirectoryName) | 
 |         { | 
 |             return AddItem(fileOrDirectoryName, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds an item, either a file or a directory, to a zip file archive, | 
 |         ///   explicitly specifying the directory path to be used in the archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   If adding a directory, the add is recursive on all files and | 
 |         ///   subdirectories contained within it. | 
 |         /// </para> | 
 |         /// <para> | 
 |         ///   The name of the item may be a relative path or a fully-qualified path. | 
 |         ///   The item added by this call to the <c>ZipFile</c> is not read from the | 
 |         ///   disk nor written to the zip file archive until the application calls | 
 |         ///   Save() on the <c>ZipFile</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This version of the method allows the caller to explicitly specify the | 
 |         ///   directory path to be used in the archive, which would override the | 
 |         ///   "natural" path of the filesystem file. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Encryption will be used on the file data if the <c>Password</c> has | 
 |         ///   been set on the <c>ZipFile</c> object, prior to calling this method. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <exception cref="System.IO.FileNotFoundException"> | 
 |         ///   Thrown if the file or directory passed in does not exist. | 
 |         /// </exception> | 
 |         /// | 
 |         /// <param name="fileOrDirectoryName">the name of the file or directory to add. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   The name of the directory path to use within the zip archive.  This path | 
 |         ///   need not refer to an extant directory in the current filesystem.  If the | 
 |         ///   files within the zip are later extracted, this is the path used for the | 
 |         ///   extracted file.  Passing <c>null</c> (<c>Nothing</c> in VB) will use the | 
 |         ///   path on the fileOrDirectoryName.  Passing the empty string ("") will | 
 |         ///   insert the item at the root path within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string, string)"/> | 
 |         /// | 
 |         /// <example> | 
 |         ///   This example shows how to zip up a set of files into a flat hierarchy, | 
 |         ///   regardless of where in the filesystem the files originated. The resulting | 
 |         ///   zip archive will contain a toplevel directory named "flat", which itself | 
 |         ///   will contain files Readme.txt, MyProposal.docx, and Image1.jpg.  A | 
 |         ///   subdirectory under "flat" called SupportFiles will contain all the files | 
 |         ///   in the "c:\SupportFiles" directory on disk. | 
 |         /// | 
 |         /// <code> | 
 |         /// String[] itemnames= { | 
 |         ///   "c:\\fixedContent\\Readme.txt", | 
 |         ///   "MyProposal.docx", | 
 |         ///   "c:\\SupportFiles",  // a directory | 
 |         ///   "images\\Image1.jpg" | 
 |         /// }; | 
 |         /// | 
 |         /// try | 
 |         /// { | 
 |         ///   using (ZipFile zip = new ZipFile()) | 
 |         ///   { | 
 |         ///     for (int i = 1; i < itemnames.Length; i++) | 
 |         ///     { | 
 |         ///       // will add Files or Dirs, recurses and flattens subdirectories | 
 |         ///       zip.AddItem(itemnames[i],"flat"); | 
 |         ///     } | 
 |         ///     zip.Save(ZipToCreate); | 
 |         ///   } | 
 |         /// } | 
 |         /// catch (System.Exception ex1) | 
 |         /// { | 
 |         ///   System.Console.Error.WriteLine("exception: {0}", ex1); | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         ///   Dim itemnames As String() = _ | 
 |         ///     New String() { "c:\fixedContent\Readme.txt", _ | 
 |         ///                    "MyProposal.docx", _ | 
 |         ///                    "SupportFiles", _ | 
 |         ///                    "images\Image1.jpg" } | 
 |         ///   Try | 
 |         ///       Using zip As New ZipFile | 
 |         ///           Dim i As Integer | 
 |         ///           For i = 1 To itemnames.Length - 1 | 
 |         ///               ' will add Files or Dirs, recursing and flattening subdirectories. | 
 |         ///               zip.AddItem(itemnames(i), "flat") | 
 |         ///           Next i | 
 |         ///           zip.Save(ZipToCreate) | 
 |         ///       End Using | 
 |         ///   Catch ex1 As Exception | 
 |         ///       Console.Error.WriteLine("exception: {0}", ex1.ToString()) | 
 |         ///   End Try | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddItem(String fileOrDirectoryName, String directoryPathInArchive) | 
 |         { | 
 |             if (File.Exists(fileOrDirectoryName)) | 
 |                 return AddFile(fileOrDirectoryName, directoryPathInArchive); | 
 |  | 
 |             if (Directory.Exists(fileOrDirectoryName)) | 
 |                 return AddDirectory(fileOrDirectoryName, directoryPathInArchive); | 
 |  | 
 |             throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", | 
 |                                                           fileOrDirectoryName)); | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a File to a Zip file archive. | 
 |         /// </summary> | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This call collects metadata for the named file in the filesystem, | 
 |         ///   including the file attributes and the timestamp, and inserts that metadata | 
 |         ///   into the resulting ZipEntry.  Only when the application calls Save() on | 
 |         ///   the <c>ZipFile</c>, does DotNetZip read the file from the filesystem and | 
 |         ///   then write the content to the zip file archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This method will throw an exception if an entry with the same name already | 
 |         ///   exists in the <c>ZipFile</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <para> | 
 |         ///   In this example, three files are added to a Zip archive. The ReadMe.txt | 
 |         ///   file will be placed in the root of the archive. The .png file will be | 
 |         ///   placed in a folder within the zip called photos\personal.  The pdf file | 
 |         ///   will be included into a folder within the zip called Desktop. | 
 |         /// </para> | 
 |         /// <code> | 
 |         ///    try | 
 |         ///    { | 
 |         ///      using (ZipFile zip = new ZipFile()) | 
 |         ///      { | 
 |         ///        zip.AddFile("c:\\photos\\personal\\7440-N49th.png"); | 
 |         ///        zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf"); | 
 |         ///        zip.AddFile("ReadMe.txt"); | 
 |         /// | 
 |         ///        zip.Save("Package.zip"); | 
 |         ///      } | 
 |         ///    } | 
 |         ///    catch (System.Exception ex1) | 
 |         ///    { | 
 |         ///      System.Console.Error.WriteLine("exception: " + ex1); | 
 |         ///    } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         ///  Try | 
 |         ///       Using zip As ZipFile = New ZipFile | 
 |         ///           zip.AddFile("c:\photos\personal\7440-N49th.png") | 
 |         ///           zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf") | 
 |         ///           zip.AddFile("ReadMe.txt") | 
 |         ///           zip.Save("Package.zip") | 
 |         ///       End Using | 
 |         ///   Catch ex1 As Exception | 
 |         ///       Console.Error.WriteLine("exception: {0}", ex1.ToString) | 
 |         ///   End Try | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <overloads>This method has two overloads.</overloads> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/> | 
 |         /// | 
 |         /// <param name="fileName"> | 
 |         ///   The name of the file to add. It should refer to a file in the filesystem. | 
 |         ///   The name of the file may be a relative path or a fully-qualified path. | 
 |         /// </param> | 
 |         /// <returns>The <c>ZipEntry</c> corresponding to the File added.</returns> | 
 |         public ZipEntry AddFile(string fileName) | 
 |         { | 
 |             return AddFile(fileName, null); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a File to a Zip file archive, potentially overriding the path to be | 
 |         ///   used within the zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   The file added by this call to the <c>ZipFile</c> is not written to the | 
 |         ///   zip file archive until the application calls Save() on the <c>ZipFile</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This method will throw an exception if an entry with the same name already | 
 |         ///   exists in the <c>ZipFile</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This version of the method allows the caller to explicitly specify the | 
 |         ///   directory path to be used in the archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <para> | 
 |         ///   In this example, three files are added to a Zip archive. The ReadMe.txt | 
 |         ///   file will be placed in the root of the archive. The .png file will be | 
 |         ///   placed in a folder within the zip called images.  The pdf file will be | 
 |         ///   included into a folder within the zip called files\docs, and will be | 
 |         ///   encrypted with the given password. | 
 |         /// </para> | 
 |         /// <code> | 
 |         /// try | 
 |         /// { | 
 |         ///   using (ZipFile zip = new ZipFile()) | 
 |         ///   { | 
 |         ///     // the following entry will be inserted at the root in the archive. | 
 |         ///     zip.AddFile("c:\\datafiles\\ReadMe.txt", ""); | 
 |         ///     // this image file will be inserted into the "images" directory in the archive. | 
 |         ///     zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images"); | 
 |         ///     // the following will result in a password-protected file called | 
 |         ///     // files\\docs\\2008-Regional-Sales-Report.pdf  in the archive. | 
 |         ///     zip.Password = "EncryptMe!"; | 
 |         ///     zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs"); | 
 |         ///     zip.Save("Archive.zip"); | 
 |         ///   } | 
 |         /// } | 
 |         /// catch (System.Exception ex1) | 
 |         /// { | 
 |         ///   System.Console.Error.WriteLine("exception: {0}", ex1); | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         ///   Try | 
 |         ///       Using zip As ZipFile = New ZipFile | 
 |         ///           ' the following entry will be inserted at the root in the archive. | 
 |         ///           zip.AddFile("c:\datafiles\ReadMe.txt", "") | 
 |         ///           ' this image file will be inserted into the "images" directory in the archive. | 
 |         ///           zip.AddFile("c:\photos\personal\7440-N49th.png", "images") | 
 |         ///           ' the following will result in a password-protected file called | 
 |         ///           ' files\\docs\\2008-Regional-Sales-Report.pdf  in the archive. | 
 |         ///           zip.Password = "EncryptMe!" | 
 |         ///           zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents") | 
 |         ///           zip.Save("Archive.zip") | 
 |         ///       End Using | 
 |         ///   Catch ex1 As Exception | 
 |         ///       Console.Error.WriteLine("exception: {0}", ex1) | 
 |         ///   End Try | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string,string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/> | 
 |         /// | 
 |         /// <param name="fileName"> | 
 |         ///   The name of the file to add.  The name of the file may be a relative path | 
 |         ///   or a fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the fileName. | 
 |         ///   This path may, or may not, correspond to a real directory in the current | 
 |         ///   filesystem.  If the files within the zip are later extracted, this is the | 
 |         ///   path used for the extracted file.  Passing <c>null</c> (<c>Nothing</c> in | 
 |         ///   VB) will use the path on the fileName, if any.  Passing the empty string | 
 |         ///   ("") will insert the item at the root path within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> corresponding to the file added.</returns> | 
 |         public ZipEntry AddFile(string fileName, String directoryPathInArchive) | 
 |         { | 
 |             string nameInArchive = ZipEntry.NameInArchive(fileName, directoryPathInArchive); | 
 |             ZipEntry ze = ZipEntry.CreateFromFile(fileName, nameInArchive); | 
 |             if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", fileName); | 
 |             return _InternalAddEntry(ze); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   This method removes a collection of entries from the <c>ZipFile</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <param name="entriesToRemove"> | 
 |         ///   A collection of ZipEntry instances from this zip file to be removed. For | 
 |         ///   example, you can pass in an array of ZipEntry instances; or you can call | 
 |         ///   SelectEntries(), and then add or remove entries from that | 
 |         ///   ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass | 
 |         ///   that ICollection to this method. | 
 |         /// </param> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" /> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" /> | 
 |         public void RemoveEntries(System.Collections.Generic.ICollection<ZipEntry> entriesToRemove) | 
 |         { | 
 |             if (entriesToRemove == null) | 
 |                 throw new ArgumentNullException("entriesToRemove"); | 
 |  | 
 |             foreach (ZipEntry e in entriesToRemove) | 
 |             { | 
 |                 this.RemoveEntry(e); | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   This method removes a collection of entries from the <c>ZipFile</c>, by name. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <param name="entriesToRemove"> | 
 |         ///   A collection of strings that refer to names of entries to be removed | 
 |         ///   from the <c>ZipFile</c>.  For example, you can pass in an array or a | 
 |         ///   List of Strings that provide the names of entries to be removed. | 
 |         /// </param> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" /> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" /> | 
 |         public void RemoveEntries(System.Collections.Generic.ICollection<String> entriesToRemove) | 
 |         { | 
 |             if (entriesToRemove == null) | 
 |                 throw new ArgumentNullException("entriesToRemove"); | 
 |  | 
 |             foreach (String e in entriesToRemove) | 
 |             { | 
 |                 this.RemoveEntry(e); | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   This method adds a set of files to the <c>ZipFile</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Use this method to add a set of files to the zip archive, in one call. | 
 |         ///   For example, a list of files received from | 
 |         ///   <c>System.IO.Directory.GetFiles()</c> can be added to a zip archive in one | 
 |         ///   call. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="fileNames"> | 
 |         ///   The collection of names of the files to add. Each string should refer to a | 
 |         ///   file in the filesystem. The name of the file may be a relative path or a | 
 |         ///   fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <example> | 
 |         ///   This example shows how to create a zip file, and add a few files into it. | 
 |         /// <code> | 
 |         /// String ZipFileToCreate = "archive1.zip"; | 
 |         /// String DirectoryToZip = "c:\\reports"; | 
 |         /// using (ZipFile zip = new ZipFile()) | 
 |         /// { | 
 |         ///   // Store all files found in the top level directory, into the zip archive. | 
 |         ///   String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); | 
 |         ///   zip.AddFiles(filenames); | 
 |         ///   zip.Save(ZipFileToCreate); | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// Dim ZipFileToCreate As String = "archive1.zip" | 
 |         /// Dim DirectoryToZip As String = "c:\reports" | 
 |         /// Using zip As ZipFile = New ZipFile | 
 |         ///     ' Store all files found in the top level directory, into the zip archive. | 
 |         ///     Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) | 
 |         ///     zip.AddFiles(filenames) | 
 |         ///     zip.Save(ZipFileToCreate) | 
 |         /// End Using | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" /> | 
 |         public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames) | 
 |         { | 
 |             this.AddFiles(fileNames, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds or updates a set of files in the <c>ZipFile</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Any files that already exist in the archive are updated. Any files that | 
 |         ///   don't yet exist in the archive are added. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="fileNames"> | 
 |         ///   The collection of names of the files to update. Each string should refer to a file in | 
 |         ///   the filesystem. The name of the file may be a relative path or a fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames) | 
 |         { | 
 |             this.UpdateFiles(fileNames, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a set of files to the <c>ZipFile</c>, using the | 
 |         ///   specified directory path in the archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Any directory structure that may be present in the | 
 |         ///   filenames contained in the list is "flattened" in the | 
 |         ///   archive.  Each file in the list is added to the archive in | 
 |         ///   the specified top-level directory. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see | 
 |         ///   cref="Encryption"/>, <see cref="Password"/>, <see | 
 |         ///   cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see | 
 |         ///   cref="ExtractExistingFile"/>, <see | 
 |         ///   cref="ZipErrorAction"/>, and <see | 
 |         ///   cref="CompressionLevel"/>, their respective values at the | 
 |         ///   time of this call will be applied to each ZipEntry added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="fileNames"> | 
 |         ///   The names of the files to add. Each string should refer to | 
 |         ///   a file in the filesystem.  The name of the file may be a | 
 |         ///   relative path or a fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the file name. | 
 |         ///   Th is path may, or may not, correspond to a real directory in the current | 
 |         ///   filesystem.  If the files within the zip are later extracted, this is the | 
 |         ///   path used for the extracted file.  Passing <c>null</c> (<c>Nothing</c> in | 
 |         ///   VB) will use the path on each of the <c>fileNames</c>, if any.  Passing | 
 |         ///   the empty string ("") will insert the item at the root path within the | 
 |         ///   archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" /> | 
 |         public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive) | 
 |         { | 
 |             AddFiles(fileNames, false, directoryPathInArchive); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a set of files to the <c>ZipFile</c>, using the specified directory | 
 |         ///   path in the archive, and preserving the full directory structure in the | 
 |         ///   filenames. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Think of the <paramref name="directoryPathInArchive"/> as a "root" or | 
 |         ///   base directory used in the archive for the files that get added.  when | 
 |         ///   <paramref name="preserveDirHierarchy"/> is true, the hierarchy of files | 
 |         ///   found in the filesystem will be placed, with the hierarchy intact, | 
 |         ///   starting at that root in the archive. When <c>preserveDirHierarchy</c> | 
 |         ///   is false, the path hierarchy of files is flattned, and the flattened | 
 |         ///   set of files gets placed in the root within the archive as specified in | 
 |         ///   <c>directoryPathInArchive</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="fileNames"> | 
 |         ///   The names of the files to add. Each string should refer to a file in the | 
 |         ///   filesystem.  The name of the file may be a relative path or a | 
 |         ///   fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use as a prefix for each entry name. | 
 |         ///   This path may, or may not, correspond to a real directory in the current | 
 |         ///   filesystem.  If the files within the zip are later extracted, this is the | 
 |         ///   path used for the extracted file.  Passing <c>null</c> (<c>Nothing</c> in | 
 |         ///   VB) will use the path on each of the <c>fileNames</c>, if any.  Passing | 
 |         ///   the empty string ("") will insert the item at the root path within the | 
 |         ///   archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="preserveDirHierarchy"> | 
 |         ///   whether the entries in the zip archive will reflect the directory | 
 |         ///   hierarchy that is present in the various filenames.  For example, if | 
 |         ///   <paramref name="fileNames"/> includes two paths, | 
 |         ///   \Animalia\Chordata\Mammalia\Info.txt and | 
 |         ///   \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method | 
 |         ///   with <paramref name="preserveDirHierarchy"/> = <c>false</c> will | 
 |         ///   result in an exception because of a duplicate entry name, while | 
 |         ///   calling this method with <paramref name="preserveDirHierarchy"/> = | 
 |         ///   <c>true</c> will result in the full direcory paths being included in | 
 |         ///   the entries added to the ZipFile. | 
 |         /// </param> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" /> | 
 |         public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames, | 
 |                              bool preserveDirHierarchy, | 
 |                              String directoryPathInArchive) | 
 |         { | 
 |             if (fileNames == null) | 
 |                 throw new ArgumentNullException("fileNames"); | 
 |  | 
 |             _addOperationCanceled = false; | 
 |             OnAddStarted(); | 
 |             if (preserveDirHierarchy) | 
 |             { | 
 |                 foreach (var f in fileNames) | 
 |                 { | 
 |                     if (_addOperationCanceled) break; | 
 |                     if (directoryPathInArchive != null) | 
 |                     { | 
 |                         //string s = SharedUtilities.NormalizePath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f))); | 
 |                         string s = Path.GetFullPath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f))); | 
 |                         this.AddFile(f, s); | 
 |                     } | 
 |                     else | 
 |                         this.AddFile(f, null); | 
 |                 } | 
 |             } | 
 |             else | 
 |             { | 
 |                 foreach (var f in fileNames) | 
 |                 { | 
 |                     if (_addOperationCanceled) break; | 
 |                     this.AddFile(f, directoryPathInArchive); | 
 |                 } | 
 |             } | 
 |             if (!_addOperationCanceled) | 
 |                 OnAddCompleted(); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds or updates a set of files to the <c>ZipFile</c>, using the specified | 
 |         ///   directory path in the archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Any files that already exist in the archive are updated. Any files that | 
 |         ///   don't yet exist in the archive are added. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="fileNames"> | 
 |         ///   The names of the files to add or update. Each string should refer to a | 
 |         ///   file in the filesystem.  The name of the file may be a relative path or a | 
 |         ///   fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the file name. | 
 |         ///   This path may, or may not, correspond to a real directory in the current | 
 |         ///   filesystem.  If the files within the zip are later extracted, this is the | 
 |         ///   path used for the extracted file.  Passing <c>null</c> (<c>Nothing</c> in | 
 |         ///   VB) will use the path on each of the <c>fileNames</c>, if any.  Passing | 
 |         ///   the empty string ("") will insert the item at the root path within the | 
 |         ///   archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" /> | 
 |         public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive) | 
 |         { | 
 |             if (fileNames == null) | 
 |                 throw new ArgumentNullException("fileNames"); | 
 |  | 
 |             OnAddStarted(); | 
 |             foreach (var f in fileNames) | 
 |                 this.UpdateFile(f, directoryPathInArchive); | 
 |             OnAddCompleted(); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds or Updates a File in a Zip file archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This method adds a file to a zip archive, or, if the file already exists | 
 |         ///   in the zip archive, this method Updates the content of that given filename | 
 |         ///   in the zip archive.  The <c>UpdateFile</c> method might more accurately be | 
 |         ///   called "AddOrUpdateFile". | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Upon success, there is no way for the application to learn whether the file | 
 |         ///   was added versus updated. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         ///   This example shows how to Update an existing entry in a zipfile. The first | 
 |         ///   call to UpdateFile adds the file to the newly-created zip archive.  The | 
 |         ///   second call to UpdateFile updates the content for that file in the zip | 
 |         ///   archive. | 
 |         /// | 
 |         /// <code> | 
 |         /// using (ZipFile zip1 = new ZipFile()) | 
 |         /// { | 
 |         ///   // UpdateFile might more accurately be called "AddOrUpdateFile" | 
 |         ///   zip1.UpdateFile("MyDocuments\\Readme.txt"); | 
 |         ///   zip1.UpdateFile("CustomerList.csv"); | 
 |         ///   zip1.Comment = "This zip archive has been created."; | 
 |         ///   zip1.Save("Content.zip"); | 
 |         /// } | 
 |         /// | 
 |         /// using (ZipFile zip2 = ZipFile.Read("Content.zip")) | 
 |         /// { | 
 |         ///   zip2.UpdateFile("Updates\\Readme.txt"); | 
 |         ///   zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."; | 
 |         ///   zip2.Save(); | 
 |         /// } | 
 |         /// | 
 |         /// </code> | 
 |         /// <code lang="VB"> | 
 |         ///   Using zip1 As New ZipFile | 
 |         ///       ' UpdateFile might more accurately be called "AddOrUpdateFile" | 
 |         ///       zip1.UpdateFile("MyDocuments\Readme.txt") | 
 |         ///       zip1.UpdateFile("CustomerList.csv") | 
 |         ///       zip1.Comment = "This zip archive has been created." | 
 |         ///       zip1.Save("Content.zip") | 
 |         ///   End Using | 
 |         /// | 
 |         ///   Using zip2 As ZipFile = ZipFile.Read("Content.zip") | 
 |         ///       zip2.UpdateFile("Updates\Readme.txt") | 
 |         ///       zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed." | 
 |         ///       zip2.Save | 
 |         ///   End Using | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/> | 
 |         /// | 
 |         /// <param name="fileName"> | 
 |         ///   The name of the file to add or update. It should refer to a file in the | 
 |         ///   filesystem.  The name of the file may be a relative path or a | 
 |         ///   fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns> | 
 |         ///   The <c>ZipEntry</c> corresponding to the File that was added or updated. | 
 |         /// </returns> | 
 |         public ZipEntry UpdateFile(string fileName) | 
 |         { | 
 |             return UpdateFile(fileName, null); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds or Updates a File in a Zip file archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This method adds a file to a zip archive, or, if the file already exists | 
 |         ///   in the zip archive, this method Updates the content of that given filename | 
 |         ///   in the zip archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This version of the method allows the caller to explicitly specify the | 
 |         ///   directory path to be used in the archive.  The entry to be added or | 
 |         ///   updated is found by using the specified directory path, combined with the | 
 |         ///   basename of the specified filename. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Upon success, there is no way for the application to learn if the file was | 
 |         ///   added versus updated. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string,string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string,string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/> | 
 |         /// | 
 |         /// <param name="fileName"> | 
 |         ///   The name of the file to add or update. It should refer to a file in the | 
 |         ///   filesystem.  The name of the file may be a relative path or a | 
 |         ///   fully-qualified path. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the | 
 |         ///   <c>fileName</c>.  This path may, or may not, correspond to a real | 
 |         ///   directory in the current filesystem.  If the files within the zip are | 
 |         ///   later extracted, this is the path used for the extracted file.  Passing | 
 |         ///   <c>null</c> (<c>Nothing</c> in VB) will use the path on the | 
 |         ///   <c>fileName</c>, if any.  Passing the empty string ("") will insert the | 
 |         ///   item at the root path within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns> | 
 |         ///   The <c>ZipEntry</c> corresponding to the File that was added or updated. | 
 |         /// </returns> | 
 |         public ZipEntry UpdateFile(string fileName, String directoryPathInArchive) | 
 |         { | 
 |             // ideally this would all be transactional! | 
 |             var key = ZipEntry.NameInArchive(fileName, directoryPathInArchive); | 
 |             if (this[key] != null) | 
 |                 this.RemoveEntry(key); | 
 |             return this.AddFile(fileName, directoryPathInArchive); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add or update a directory in a zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   If the specified directory does not exist in the archive, then this method | 
 |         ///   is equivalent to calling <c>AddDirectory()</c>.  If the specified | 
 |         ///   directory already exists in the archive, then this method updates any | 
 |         ///   existing entries, and adds any new entries. Any entries that are in the | 
 |         ///   zip archive but not in the specified directory, are left alone.  In other | 
 |         ///   words, the contents of the zip file will be a union of the previous | 
 |         ///   contents and the new files. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/> | 
 |         /// | 
 |         /// <param name="directoryName"> | 
 |         ///   The path to the directory to be added to the zip archive, or updated in | 
 |         ///   the zip archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns> | 
 |         /// The <c>ZipEntry</c> corresponding to the Directory that was added or updated. | 
 |         /// </returns> | 
 |         public ZipEntry UpdateDirectory(string directoryName) | 
 |         { | 
 |             return UpdateDirectory(directoryName, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add or update a directory in the zip archive at the specified root | 
 |         ///   directory in the archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   If the specified directory does not exist in the archive, then this method | 
 |         ///   is equivalent to calling <c>AddDirectory()</c>.  If the specified | 
 |         ///   directory already exists in the archive, then this method updates any | 
 |         ///   existing entries, and adds any new entries. Any entries that are in the | 
 |         ///   zip archive but not in the specified directory, are left alone.  In other | 
 |         ///   words, the contents of the zip file will be a union of the previous | 
 |         ///   contents and the new files. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string,string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/> | 
 |         /// | 
 |         /// <param name="directoryName"> | 
 |         ///   The path to the directory to be added to the zip archive, or updated | 
 |         ///   in the zip archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the | 
 |         ///   <c>directoryName</c>.  This path may, or may not, correspond to a real | 
 |         ///   directory in the current filesystem.  If the files within the zip are | 
 |         ///   later extracted, this is the path used for the extracted file.  Passing | 
 |         ///   <c>null</c> (<c>Nothing</c> in VB) will use the path on the | 
 |         ///   <c>directoryName</c>, if any.  Passing the empty string ("") will insert | 
 |         ///   the item at the root path within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns> | 
 |         ///   The <c>ZipEntry</c> corresponding to the Directory that was added or updated. | 
 |         /// </returns> | 
 |         public ZipEntry UpdateDirectory(string directoryName, String directoryPathInArchive) | 
 |         { | 
 |             return this.AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOrUpdate); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add or update a file or directory in the zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This is useful when the application is not sure or does not care if the | 
 |         ///   item to be added is a file or directory, and does not know or does not | 
 |         ///   care if the item already exists in the <c>ZipFile</c>. Calling this method | 
 |         ///   is equivalent to calling <c>RemoveEntry()</c> if an entry by the same name | 
 |         ///   already exists, followed calling by <c>AddItem()</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/> | 
 |         /// | 
 |         /// <param name="itemName"> | 
 |         ///  the path to the file or directory to be added or updated. | 
 |         /// </param> | 
 |         public void UpdateItem(string itemName) | 
 |         { | 
 |             UpdateItem(itemName, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add or update a file or directory. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This method is useful when the application is not sure or does not care if | 
 |         ///   the item to be added is a file or directory, and does not know or does not | 
 |         ///   care if the item already exists in the <c>ZipFile</c>. Calling this method | 
 |         ///   is equivalent to calling <c>RemoveEntry()</c>, if an entry by that name | 
 |         ///   exists, and then calling <c>AddItem()</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This version of the method allows the caller to explicitly specify the | 
 |         ///   directory path to be used for the item being added to the archive.  The | 
 |         ///   entry or entries that are added or updated will use the specified | 
 |         ///   <c>DirectoryPathInArchive</c>. Extracting the entry from the archive will | 
 |         ///   result in a file stored in that directory path. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/> | 
 |         /// | 
 |         /// <param name="itemName"> | 
 |         ///   The path for the File or Directory to be added or updated. | 
 |         /// </param> | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the | 
 |         ///   <c>itemName</c>.  This path may, or may not, correspond to a real | 
 |         ///   directory in the current filesystem.  If the files within the zip are | 
 |         ///   later extracted, this is the path used for the extracted file.  Passing | 
 |         ///   <c>null</c> (<c>Nothing</c> in VB) will use the path on the | 
 |         ///   <c>itemName</c>, if any.  Passing the empty string ("") will insert the | 
 |         ///   item at the root path within the archive. | 
 |         /// </param> | 
 |         public void UpdateItem(string itemName, string directoryPathInArchive) | 
 |         { | 
 |             if (File.Exists(itemName)) | 
 |                 UpdateFile(itemName, directoryPathInArchive); | 
 |  | 
 |             else if (Directory.Exists(itemName)) | 
 |                 UpdateDirectory(itemName, directoryPathInArchive); | 
 |  | 
 |             else | 
 |                 throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", itemName)); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a named entry into the zip archive, taking content for the entry | 
 |         ///   from a string. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Calling this method creates an entry using the given fileName and | 
 |         ///   directory path within the archive.  There is no need for a file by the | 
 |         ///   given name to exist in the filesystem; the name is used within the zip | 
 |         ///   archive only. The content for the entry is encoded using the default text | 
 |         ///   encoding for the machine, or on Silverlight, using UTF-8. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="content"> | 
 |         ///   The content of the file, should it be extracted from the zip. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use for the entry within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         /// This example shows how to add an entry to the zipfile, using a string as | 
 |         /// content for that entry. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// string Content = "This string will be the content of the Readme.txt file in the zip archive."; | 
 |         /// using (ZipFile zip1 = new ZipFile()) | 
 |         /// { | 
 |         ///   zip1.AddFile("MyDocuments\\Resume.doc", "files"); | 
 |         ///   zip1.AddEntry("Readme.txt", Content); | 
 |         ///   zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); | 
 |         ///   zip1.Save("Content.zip"); | 
 |         /// } | 
 |         /// | 
 |         /// </code> | 
 |         /// <code lang="VB"> | 
 |         /// Public Sub Run() | 
 |         ///   Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." | 
 |         ///   Using zip1 As ZipFile = New ZipFile | 
 |         ///     zip1.AddEntry("Readme.txt", Content) | 
 |         ///     zip1.AddFile("MyDocuments\Resume.doc", "files") | 
 |         ///     zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) | 
 |         ///     zip1.Save("Content.zip") | 
 |         ///   End Using | 
 |         /// End Sub | 
 |         /// </code> | 
 |         /// </example> | 
 |         public ZipEntry AddEntry(string entryName, string content) | 
 |         { | 
 | #if SILVERLIGHT | 
 |             return AddEntry(entryName, content, System.Text.Encoding.UTF8); | 
 | #else | 
 |             return AddEntry(entryName, content, System.Text.Encoding.Default); | 
 | #endif | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds a named entry into the zip archive, taking content for the entry | 
 |         ///   from a string, and using the specified text encoding. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Calling this method creates an entry using the given fileName and | 
 |         ///   directory path within the archive.  There is no need for a file by the | 
 |         ///   given name to exist in the filesystem; the name is used within the zip | 
 |         ///   archive only. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The content for the entry, a string value, is encoded using the given | 
 |         ///   text encoding. A BOM (byte-order-mark) is emitted into the file, if the | 
 |         ///   Encoding parameter is set for that. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Most Encoding classes support a constructor that accepts a boolean, | 
 |         ///   indicating whether to emit a BOM or not. For example see <see | 
 |         ///   cref="System.Text.UTF8Encoding(bool)"/>. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="content"> | 
 |         ///   The content of the file, should it be extracted from the zip. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="encoding"> | 
 |         ///   The text encoding to use when encoding the string. Be aware: This is | 
 |         ///   distinct from the text encoding used to encode the fileName, as specified | 
 |         ///   in <see cref="ProvisionalAlternateEncoding" />. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         public ZipEntry AddEntry(string entryName, string content, System.Text.Encoding encoding) | 
 |         { | 
 |             // cannot employ a using clause here.  We need the stream to | 
 |             // persist after exit from this method. | 
 |             var ms = new MemoryStream(); | 
 |  | 
 |             // cannot use a using clause here; StreamWriter takes | 
 |             // ownership of the stream and Disposes it before we are ready. | 
 |             var sw = new StreamWriter(ms, encoding); | 
 |             sw.Write(content); | 
 |             sw.Flush(); | 
 |  | 
 |             // reset to allow reading later | 
 |             ms.Seek(0, SeekOrigin.Begin); | 
 |  | 
 |             return AddEntry(entryName, ms); | 
 |  | 
 |             // must not dispose the MemoryStream - it will be used later. | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Create an entry in the <c>ZipFile</c> using the given <c>Stream</c> | 
 |         ///   as input.  The entry will have the given filename. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The application should provide an open, readable stream; in this case it | 
 |         ///   will be read during the call to <see cref="ZipFile.Save()"/> or one of | 
 |         ///   its overloads. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The passed stream will be read from its current position. If | 
 |         ///   necessary, callers should set the position in the stream before | 
 |         ///   calling AddEntry(). This might be appropriate when using this method | 
 |         ///   with a MemoryStream, for example. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   In cases where a large number of streams will be added to the | 
 |         ///   <c>ZipFile</c>, the application may wish to avoid maintaining all of the | 
 |         ///   streams open simultaneously.  To handle this situation, the application | 
 |         ///   should use the <see cref="AddEntry(string, OpenDelegate, CloseDelegate)"/> | 
 |         ///   overload. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <para> | 
 |         ///   This example adds a single entry to a <c>ZipFile</c> via a <c>Stream</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// String zipToCreate = "Content.zip"; | 
 |         /// String fileNameInArchive = "Content-From-Stream.bin"; | 
 |         /// using (System.IO.Stream streamToRead = MyStreamOpener()) | 
 |         /// { | 
 |         ///   using (ZipFile zip = new ZipFile()) | 
 |         ///   { | 
 |         ///     ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead); | 
 |         ///     zip.AddFile("Readme.txt"); | 
 |         ///     zip.Save(zipToCreate);  // the stream is read implicitly here | 
 |         ///   } | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// Dim zipToCreate As String = "Content.zip" | 
 |         /// Dim fileNameInArchive As String = "Content-From-Stream.bin" | 
 |         /// Using streamToRead as System.IO.Stream = MyStreamOpener() | 
 |         ///   Using zip As ZipFile = New ZipFile() | 
 |         ///     Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead) | 
 |         ///     zip.AddFile("Readme.txt") | 
 |         ///     zip.Save(zipToCreate)  '' the stream is read implicitly, here | 
 |         ///   End Using | 
 |         /// End Using | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateEntry(string, System.IO.Stream)"/> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, which is shown in the zip file for the added | 
 |         ///   entry. | 
 |         /// </param> | 
 |         /// <param name="stream"> | 
 |         ///   The input stream from which to grab content for the file | 
 |         /// </param> | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddEntry(string entryName, Stream stream) | 
 |         { | 
 |             ZipEntry ze = ZipEntry.CreateForStream(entryName, stream); | 
 |             ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); | 
 |             if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); | 
 |             return _InternalAddEntry(ze); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add a ZipEntry for which content is written directly by the application. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   When the application needs to write the zip entry data, use this | 
 |         ///   method to add the ZipEntry. For example, in the case that the | 
 |         ///   application wishes to write the XML representation of a DataSet into | 
 |         ///   a ZipEntry, the application can use this method to do so. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   About progress events: When using the WriteDelegate, DotNetZip does | 
 |         ///   not issue any SaveProgress events with <c>EventType</c> = <see | 
 |         ///   cref="ZipProgressEventType.Saving_EntryBytesRead"> | 
 |         ///   Saving_EntryBytesRead</see>. (This is because it is the | 
 |         ///   application's code that runs in WriteDelegate - there's no way for | 
 |         ///   DotNetZip to know when to issue a EntryBytesRead event.) | 
 |         ///   Applications that want to update a progress bar or similar status | 
 |         ///   indicator should do so from within the WriteDelegate | 
 |         ///   itself. DotNetZip will issue the other SaveProgress events, | 
 |         ///   including <see cref="ZipProgressEventType.Saving_Started"> | 
 |         ///   Saving_Started</see>, | 
 |         ///   <see cref="ZipProgressEventType.Saving_BeforeWriteEntry"> | 
 |         ///   Saving_BeforeWriteEntry</see>, and <see | 
 |         ///   cref="ZipProgressEventType.Saving_AfterWriteEntry"> | 
 |         ///   Saving_AfterWriteEntry</see>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Note: When you use PKZip encryption, it's normally necessary to | 
 |         ///   compute the CRC of the content to be encrypted, before compressing or | 
 |         ///   encrypting it. Therefore, when using PKZip encryption with a | 
 |         ///   WriteDelegate, the WriteDelegate CAN BE called twice: once to compute | 
 |         ///   the CRC, and the second time to potentially compress and | 
 |         ///   encrypt. Surprising, but true. This is because PKWARE specified that | 
 |         ///   the encryption initialization data depends on the CRC. | 
 |         ///   If this happens, for each call of the delegate, your | 
 |         ///   application must stream the same entry data in its entirety. If your | 
 |         ///   application writes different data during the second call, it will | 
 |         ///   result in a corrupt zip file. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The double-read behavior happens with all types of entries, not only | 
 |         ///   those that use WriteDelegate. It happens if you add an entry from a | 
 |         ///   filesystem file, or using a string, or a stream, or an opener/closer | 
 |         ///   pair. But in those cases, DotNetZip takes care of reading twice; in | 
 |         ///   the case of the WriteDelegate, the application code gets invoked | 
 |         ///   twice. Be aware. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   As you can imagine, this can cause performance problems for large | 
 |         ///   streams, and it can lead to correctness problems when you use a | 
 |         ///   <c>WriteDelegate</c>. This is a pretty big pitfall.  There are two | 
 |         ///   ways to avoid it.  First, and most preferred: don't use PKZIP | 
 |         ///   encryption.  If you use the WinZip AES encryption, this problem | 
 |         ///   doesn't occur, because the encryption protocol doesn't require the CRC | 
 |         ///   up front. Second: if you do choose to use PKZIP encryption, write out | 
 |         ///   to a non-seekable stream (like standard output, or the | 
 |         ///   Response.OutputStream in an ASP.NET application).  In this case, | 
 |         ///   DotNetZip will use an alternative encryption protocol that does not | 
 |         ///   rely on the CRC of the content.  This also implies setting bit 3 in | 
 |         ///   the zip entry, which still presents problems for some zip tools. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   In the future I may modify DotNetZip to *always* use bit 3 when PKZIP | 
 |         ///   encryption is in use.  This seems like a win overall, but there will | 
 |         ///   be some work involved.  If you feel strongly about it, visit the | 
 |         ///   DotNetZip forums and vote up <see | 
 |         ///   href="http://dotnetzip.codeplex.com/workitem/13686">the Workitem | 
 |         ///   tracking this issue</see>. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName">the name of the entry to add</param> | 
 |         /// <param name="writer">the delegate which will write the entry content</param> | 
 |         /// <returns>the ZipEntry added</returns> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         ///   This example shows an application filling a DataSet, then saving the | 
 |         ///   contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an | 
 |         ///   anonymous delegate in C#. The DataSet XML is never saved to a disk file. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// var c1= new System.Data.SqlClient.SqlConnection(connstring1); | 
 |         /// var da = new System.Data.SqlClient.SqlDataAdapter() | 
 |         ///     { | 
 |         ///         SelectCommand=  new System.Data.SqlClient.SqlCommand(strSelect, c1) | 
 |         ///     }; | 
 |         /// | 
 |         /// DataSet ds1 = new DataSet(); | 
 |         /// da.Fill(ds1, "Invoices"); | 
 |         /// | 
 |         /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) | 
 |         /// { | 
 |         ///     zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) ); | 
 |         ///     zip.Save(zipFileName); | 
 |         /// } | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         /// This example uses an anonymous method in C# as the WriteDelegate to provide | 
 |         /// the data for the ZipEntry. The example is a bit contrived - the | 
 |         /// <c>AddFile()</c> method is a simpler way to insert the contents of a file | 
 |         /// into an entry in a zip file. On the other hand, if there is some sort of | 
 |         /// processing or transformation of the file contents required before writing, | 
 |         /// the application could use the <c>WriteDelegate</c> to do it, in this way. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite )) | 
 |         /// { | 
 |         ///     using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) | 
 |         ///     { | 
 |         ///         zip.AddEntry(zipEntryName, (name,output) => | 
 |         ///             { | 
 |         ///                 byte[] buffer = new byte[BufferSize]; | 
 |         ///                 int n; | 
 |         ///                 while ((n = input.Read(buffer, 0, buffer.Length)) != 0) | 
 |         ///                 { | 
 |         ///                     // could transform the data here... | 
 |         ///                     output.Write(buffer, 0, n); | 
 |         ///                     // could update a progress bar here | 
 |         ///                 } | 
 |         ///             }); | 
 |         /// | 
 |         ///         zip.Save(zipFileName); | 
 |         ///     } | 
 |         /// } | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         /// This example uses a named delegate in VB to write data for the given | 
 |         /// ZipEntry (VB9 does not have anonymous delegates). The example here is a bit | 
 |         /// contrived - a simpler way to add the contents of a file to a ZipEntry is to | 
 |         /// simply use the appropriate <c>AddFile()</c> method.  The key scenario for | 
 |         /// which the <c>WriteDelegate</c> makes sense is saving a DataSet, in XML | 
 |         /// format, to the zip file. The DataSet can write XML to a stream, and the | 
 |         /// WriteDelegate is the perfect place to write into the zip file.  There may be | 
 |         /// other data structures that can write to a stream, but cannot be read as a | 
 |         /// stream.  The <c>WriteDelegate</c> would be appropriate for those cases as | 
 |         /// well. | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// Private Sub WriteEntry (ByVal name As String, ByVal output As Stream) | 
 |         ///     Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) | 
 |         ///         Dim n As Integer = -1 | 
 |         ///         Dim buffer As Byte() = New Byte(BufferSize){} | 
 |         ///         Do While n <> 0 | 
 |         ///             n = input.Read(buffer, 0, buffer.Length) | 
 |         ///             output.Write(buffer, 0, n) | 
 |         ///         Loop | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// Public Sub Run() | 
 |         ///     Using zip = New ZipFile | 
 |         ///         zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) | 
 |         ///         zip.Save(zipFileName) | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// </code> | 
 |         /// </example> | 
 |         public ZipEntry AddEntry(string entryName, WriteDelegate writer) | 
 |         { | 
 |             ZipEntry ze = ZipEntry.CreateForWriter(entryName, writer); | 
 |             if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); | 
 |             return _InternalAddEntry(ze); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add an entry, for which the application will provide a stream | 
 |         ///   containing the entry data, on a just-in-time basis. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   In cases where the application wishes to open the stream that | 
 |         ///   holds the content for the ZipEntry, on a just-in-time basis, the | 
 |         ///   application can use this method.  The application provides an | 
 |         ///   opener delegate that will be called by the DotNetZip library to | 
 |         ///   obtain a readable stream that can be read to get the bytes for | 
 |         ///   the given entry.  Typically, this delegate opens a stream. | 
 |         ///   Optionally, the application can provide a closer delegate as | 
 |         ///   well, which will be called by DotNetZip when all bytes have been | 
 |         ///   read from the entry. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   These delegates are called from within the scope of the call to | 
 |         ///   ZipFile.Save(). | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         ///   This example uses anonymous methods in C# to open and close the | 
 |         ///   source stream for the content for a zip entry. | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) | 
 |         /// { | 
 |         ///     zip.AddEntry(zipEntryName, | 
 |         ///                  (name) =>  File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ), | 
 |         ///                  (name, stream) =>  stream.Close() | 
 |         ///                  ); | 
 |         /// | 
 |         ///     zip.Save(zipFileName); | 
 |         /// } | 
 |         /// </code> | 
 |         /// | 
 |         /// </example> | 
 |         /// | 
 |         /// <example> | 
 |         /// | 
 |         ///   This example uses delegates in VB.NET to open and close the | 
 |         ///   the source stream for the content for a zip entry.  VB 9.0 lacks | 
 |         ///   support for "Sub" lambda expressions, and so the CloseDelegate must | 
 |         ///   be an actual, named Sub. | 
 |         /// | 
 |         /// <code lang="VB"> | 
 |         /// | 
 |         /// Function MyStreamOpener(ByVal entryName As String) As Stream | 
 |         ///     '' This simply opens a file.  You probably want to do somethinig | 
 |         ///     '' more involved here: open a stream to read from a database, | 
 |         ///     '' open a stream on an HTTP connection, and so on. | 
 |         ///     Return File.OpenRead(entryName) | 
 |         /// End Function | 
 |         /// | 
 |         /// Sub MyStreamCloser(entryName As String, stream As Stream) | 
 |         ///     stream.Close() | 
 |         /// End Sub | 
 |         /// | 
 |         /// Public Sub Run() | 
 |         ///     Dim dirToZip As String = "fodder" | 
 |         ///     Dim zipFileToCreate As String = "Archive.zip" | 
 |         ///     Dim opener As OpenDelegate = AddressOf MyStreamOpener | 
 |         ///     Dim closer As CloseDelegate = AddressOf MyStreamCloser | 
 |         ///     Dim numFilestoAdd As Int32 = 4 | 
 |         ///     Using zip As ZipFile = New ZipFile | 
 |         ///         Dim i As Integer | 
 |         ///         For i = 0 To numFilesToAdd - 1 | 
 |         ///             zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer) | 
 |         ///         Next i | 
 |         ///         zip.Save(zipFileToCreate) | 
 |         ///     End Using | 
 |         /// End Sub | 
 |         /// | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <param name="entryName">the name of the entry to add</param> | 
 |         /// <param name="opener"> | 
 |         ///  the delegate that will be invoked by ZipFile.Save() to get the | 
 |         ///  readable stream for the given entry. ZipFile.Save() will call | 
 |         ///  read on this stream to obtain the data for the entry. This data | 
 |         ///  will then be compressed and written to the newly created zip | 
 |         ///  file. | 
 |         /// </param> | 
 |         /// <param name="closer"> | 
 |         ///  the delegate that will be invoked to close the stream. This may | 
 |         ///  be null (Nothing in VB), in which case no call is makde to close | 
 |         ///  the stream. | 
 |         /// </param> | 
 |         /// <returns>the ZipEntry added</returns> | 
 |         /// | 
 |         public ZipEntry AddEntry(string entryName, OpenDelegate opener, CloseDelegate closer) | 
 |         { | 
 |             ZipEntry ze = ZipEntry.CreateForJitStreamProvider(entryName, opener, closer); | 
 |             ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); | 
 |             if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); | 
 |             return _InternalAddEntry(ze); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         private ZipEntry _InternalAddEntry(ZipEntry ze) | 
 |         { | 
 |             // stamp all the props onto the entry | 
 |             ze._container = new ZipContainer(this); | 
 |             ze.CompressionMethod = this.CompressionMethod; | 
 |             ze.CompressionLevel = this.CompressionLevel; | 
 |             ze.ExtractExistingFile = this.ExtractExistingFile; | 
 |             ze.ZipErrorAction = this.ZipErrorAction; | 
 |             ze.SetCompression = this.SetCompression; | 
 |             ze.AlternateEncoding = this.AlternateEncoding; | 
 |             ze.AlternateEncodingUsage = this.AlternateEncodingUsage; | 
 |             ze.Password = this._Password; | 
 |             ze.Encryption = this.Encryption; | 
 |             ze.EmitTimesInWindowsFormatWhenSaving = this._emitNtfsTimes; | 
 |             ze.EmitTimesInUnixFormatWhenSaving = this._emitUnixTimes; | 
 |             //string key = DictionaryKeyForEntry(ze); | 
 |             InternalAddEntry(ze.FileName,ze); | 
 |             AfterAddEntry(ze); | 
 |             return ze; | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given | 
 |         ///   string as content for the <c>ZipEntry</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Calling this method is equivalent to removing the <c>ZipEntry</c> for | 
 |         ///   the given file name and directory path, if it exists, and then calling | 
 |         ///   <see cref="AddEntry(String,String)" />.  See the documentation for | 
 |         ///   that method for further explanation. The string content is encoded | 
 |         ///   using the default encoding for the machine, or on Silverlight, using | 
 |         ///   UTF-8. This encoding is distinct from the encoding used for the | 
 |         ///   filename itself.  See <see cref="AlternateEncoding"/>. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="content"> | 
 |         ///   The content of the file, should it be extracted from the zip. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         public ZipEntry UpdateEntry(string entryName, string content) | 
 |         { | 
 | #if SILVERLIGHT | 
 |             return UpdateEntry(entryName, content, System.Text.Encoding.UTF8); | 
 | #else | 
 |             return UpdateEntry(entryName, content, System.Text.Encoding.Default); | 
 | #endif | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given string as | 
 |         ///   content for the <c>ZipEntry</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Calling this method is equivalent to removing the <c>ZipEntry</c> for the | 
 |         ///   given file name and directory path, if it exists, and then calling <see | 
 |         ///   cref="AddEntry(String,String, System.Text.Encoding)" />.  See the | 
 |         ///   documentation for that method for further explanation. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="content"> | 
 |         ///   The content of the file, should it be extracted from the zip. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="encoding"> | 
 |         ///   The text encoding to use when encoding the string. Be aware: This is | 
 |         ///   distinct from the text encoding used to encode the filename. See <see | 
 |         ///   cref="AlternateEncoding" />. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         public ZipEntry UpdateEntry(string entryName, string content, System.Text.Encoding encoding) | 
 |         { | 
 |             RemoveEntryForUpdate(entryName); | 
 |             return AddEntry(entryName, content, encoding); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given delegate | 
 |         ///   as the source for content for the <c>ZipEntry</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Calling this method is equivalent to removing the <c>ZipEntry</c> for the | 
 |         ///   given file name and directory path, if it exists, and then calling <see | 
 |         ///   cref="AddEntry(String,WriteDelegate)" />.  See the | 
 |         ///   documentation for that method for further explanation. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="writer">the delegate which will write the entry content.</param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         public ZipEntry UpdateEntry(string entryName, WriteDelegate writer) | 
 |         { | 
 |             RemoveEntryForUpdate(entryName); | 
 |             return AddEntry(entryName, writer); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given delegates | 
 |         ///   to open and close the stream that provides the content for the <c>ZipEntry</c>. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Calling this method is equivalent to removing the <c>ZipEntry</c> for the | 
 |         ///   given file name and directory path, if it exists, and then calling <see | 
 |         ///   cref="AddEntry(String,OpenDelegate, CloseDelegate)" />.  See the | 
 |         ///   documentation for that method for further explanation. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="opener"> | 
 |         ///  the delegate that will be invoked to open the stream | 
 |         /// </param> | 
 |         /// <param name="closer"> | 
 |         ///  the delegate that will be invoked to close the stream | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added or updated.</returns> | 
 |         /// | 
 |         public ZipEntry UpdateEntry(string entryName, OpenDelegate opener, CloseDelegate closer) | 
 |         { | 
 |             RemoveEntryForUpdate(entryName); | 
 |             return AddEntry(entryName, opener, closer); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given stream as | 
 |         ///   input, and the given filename and given directory Path. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Calling the method is equivalent to calling <c>RemoveEntry()</c> if an | 
 |         ///   entry by the same name already exists, and then calling <c>AddEntry()</c> | 
 |         ///   with the given <c>fileName</c> and stream. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The stream must be open and readable during the call to | 
 |         ///   <c>ZipFile.Save</c>.  You can dispense the stream on a just-in-time basis | 
 |         ///   using the <see cref="ZipEntry.InputStream"/> property. Check the | 
 |         ///   documentation of that property for more information. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to the | 
 |         ///   <c>ZipEntry</c> added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(string, System.IO.Stream)"/> | 
 |         /// <seealso cref="ZipEntry.InputStream"/> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="stream">The input stream from which to read file data.</param> | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry UpdateEntry(string entryName, Stream stream) | 
 |         { | 
 |             RemoveEntryForUpdate(entryName); | 
 |             return AddEntry(entryName, stream); | 
 |         } | 
 |  | 
 |  | 
 |         private void RemoveEntryForUpdate(string entryName) | 
 |         { | 
 |             if (String.IsNullOrEmpty(entryName)) | 
 |                 throw new ArgumentNullException("entryName"); | 
 |  | 
 |             string directoryPathInArchive = null; | 
 |             if (entryName.IndexOf('\\') != -1) | 
 |             { | 
 |                 directoryPathInArchive = Path.GetDirectoryName(entryName); | 
 |                 entryName = Path.GetFileName(entryName); | 
 |             } | 
 |             var key = ZipEntry.NameInArchive(entryName, directoryPathInArchive); | 
 |             if (this[key] != null) | 
 |                 this.RemoveEntry(key); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Add an entry into the zip archive using the given filename and | 
 |         ///   directory path within the archive, and the given content for the | 
 |         ///   file. No file is created in the filesystem. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <param name="byteContent">The data to use for the entry.</param> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddEntry(string entryName, byte[] byteContent) | 
 |         { | 
 |             if (byteContent == null) throw new ArgumentException("bad argument", "byteContent"); | 
 |             var ms = new MemoryStream(byteContent); | 
 |             return AddEntry(entryName, ms); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Updates the given entry in the <c>ZipFile</c>, using the given byte | 
 |         ///   array as content for the entry. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Calling this method is equivalent to removing the <c>ZipEntry</c> | 
 |         ///   for the given filename and directory path, if it exists, and then | 
 |         ///   calling <see cref="AddEntry(String,byte[])" />.  See the | 
 |         ///   documentation for that method for further explanation. | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="entryName"> | 
 |         ///   The name, including any path, to use within the archive for the entry. | 
 |         /// </param> | 
 |         /// | 
 |         /// <param name="byteContent">The content to use for the <c>ZipEntry</c>.</param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         /// | 
 |         public ZipEntry UpdateEntry(string entryName, byte[] byteContent) | 
 |         { | 
 |             RemoveEntryForUpdate(entryName); | 
 |             return AddEntry(entryName, byteContent); | 
 |         } | 
 |  | 
 |  | 
 | //         private string DictionaryKeyForEntry(ZipEntry ze1) | 
 | //         { | 
 | //             var filename = SharedUtilities.NormalizePathForUseInZipFile(ze1.FileName); | 
 | //             return filename; | 
 | //         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds the contents of a filesystem directory to a Zip file archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The name of the directory may be a relative path or a fully-qualified | 
 |         ///   path. Any files within the named directory are added to the archive.  Any | 
 |         ///   subdirectories within the named directory are also added to the archive, | 
 |         ///   recursively. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Top-level entries in the named directory will appear as top-level entries | 
 |         ///   in the zip archive.  Entries in subdirectories in the named directory will | 
 |         ///   result in entries in subdirectories in the zip archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If you want the entries to appear in a containing directory in the zip | 
 |         ///   archive itself, then you should call the AddDirectory() overload that | 
 |         ///   allows you to explicitly specify a directory path for use in the archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/> | 
 |         /// | 
 |         /// <overloads>This method has 2 overloads.</overloads> | 
 |         /// | 
 |         /// <param name="directoryName">The name of the directory to add.</param> | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddDirectory(string directoryName) | 
 |         { | 
 |             return AddDirectory(directoryName, null); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Adds the contents of a filesystem directory to a Zip file archive, | 
 |         ///   overriding the path to be used for entries in the archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   The name of the directory may be a relative path or a fully-qualified | 
 |         ///   path. The add operation is recursive, so that any files or subdirectories | 
 |         ///   within the name directory are also added to the archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Top-level entries in the named directory will appear as top-level entries | 
 |         ///   in the zip archive.  Entries in subdirectories in the named directory will | 
 |         ///   result in entries in subdirectories in the zip archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see | 
 |         ///   cref="Password"/>, <see cref="SetCompression"/>, <see | 
 |         ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>, | 
 |         ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their | 
 |         ///   respective values at the time of this call will be applied to each | 
 |         ///   ZipEntry added. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         /// <para> | 
 |         ///   In this code, calling the ZipUp() method with a value of "c:\reports" for | 
 |         ///   the directory parameter will result in a zip file structure in which all | 
 |         ///   entries are contained in a toplevel "reports" directory. | 
 |         /// </para> | 
 |         /// | 
 |         /// <code lang="C#"> | 
 |         /// public void ZipUp(string targetZip, string directory) | 
 |         /// { | 
 |         ///   using (var zip = new ZipFile()) | 
 |         ///   { | 
 |         ///     zip.AddDirectory(directory, System.IO.Path.GetFileName(directory)); | 
 |         ///     zip.Save(targetZip); | 
 |         ///   } | 
 |         /// } | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/> | 
 |         /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/> | 
 |         /// | 
 |         /// <param name="directoryName">The name of the directory to add.</param> | 
 |         /// | 
 |         /// <param name="directoryPathInArchive"> | 
 |         ///   Specifies a directory path to use to override any path in the | 
 |         ///   DirectoryName.  This path may, or may not, correspond to a real directory | 
 |         ///   in the current filesystem.  If the zip is later extracted, this is the | 
 |         ///   path used for the extracted file or directory.  Passing <c>null</c> | 
 |         ///   (<c>Nothing</c> in VB) or the empty string ("") will insert the items at | 
 |         ///   the root path within the archive. | 
 |         /// </param> | 
 |         /// | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddDirectory(string directoryName, string directoryPathInArchive) | 
 |         { | 
 |             return AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOnly); | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Creates a directory in the zip archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Use this when you want to create a directory in the archive but there is | 
 |         ///   no corresponding filesystem representation for that directory. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   You will probably not need to do this in your code. One of the only times | 
 |         ///   you will want to do this is if you want an empty directory in the zip | 
 |         ///   archive.  The reason: if you add a file to a zip archive that is stored | 
 |         ///   within a multi-level directory, all of the directory tree is implicitly | 
 |         ///   created in the zip archive. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <param name="directoryNameInArchive"> | 
 |         ///   The name of the directory to create in the archive. | 
 |         /// </param> | 
 |         /// <returns>The <c>ZipEntry</c> added.</returns> | 
 |         public ZipEntry AddDirectoryByName(string directoryNameInArchive) | 
 |         { | 
 |             // workitem 9073 | 
 |             ZipEntry dir = ZipEntry.CreateFromNothing(directoryNameInArchive); | 
 |             dir._container = new ZipContainer(this); | 
 |             dir.MarkAsDirectory(); | 
 |             dir.AlternateEncoding = this.AlternateEncoding;  // workitem 8984 | 
 |             dir.AlternateEncodingUsage = this.AlternateEncodingUsage; | 
 |             dir.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); | 
 |             dir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes; | 
 |             dir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes; | 
 |             dir._Source = ZipEntrySource.Stream; | 
 |             //string key = DictionaryKeyForEntry(dir); | 
 |             InternalAddEntry(dir.FileName,dir); | 
 |             AfterAddEntry(dir); | 
 |             return dir; | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         private ZipEntry AddOrUpdateDirectoryImpl(string directoryName, | 
 |                                                   string rootDirectoryPathInArchive, | 
 |                                                   AddOrUpdateAction action) | 
 |         { | 
 |             if (rootDirectoryPathInArchive == null) | 
 |             { | 
 |                 rootDirectoryPathInArchive = ""; | 
 |             } | 
 |  | 
 |             return AddOrUpdateDirectoryImpl(directoryName, rootDirectoryPathInArchive, action, true, 0); | 
 |         } | 
 |  | 
 |  | 
 |         internal void InternalAddEntry(String name, ZipEntry entry) | 
 |         { | 
 |             _entries.Add(name, entry); | 
 |             _zipEntriesAsList = null; | 
 |             _contentsChanged = true; | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         private ZipEntry AddOrUpdateDirectoryImpl(string directoryName, | 
 |                                                   string rootDirectoryPathInArchive, | 
 |                                                   AddOrUpdateAction action, | 
 |                                                   bool recurse, | 
 |                                                   int level) | 
 |         { | 
 |             if (Verbose) | 
 |                 StatusMessageTextWriter.WriteLine("{0} {1}...", | 
 |                                                   (action == AddOrUpdateAction.AddOnly) ? "adding" : "Adding or updating", | 
 |                                                   directoryName); | 
 |  | 
 |             if (level == 0) | 
 |             { | 
 |                 _addOperationCanceled = false; | 
 |                 OnAddStarted(); | 
 |             } | 
 |  | 
 |             // workitem 13371 | 
 |             if (_addOperationCanceled) | 
 |                 return null; | 
 |  | 
 |             string dirForEntries = rootDirectoryPathInArchive; | 
 |             ZipEntry baseDir = null; | 
 |  | 
 |             if (level > 0) | 
 |             { | 
 |                 int f = directoryName.Length; | 
 |                 for (int i = level; i > 0; i--) | 
 |                     f = directoryName.LastIndexOfAny("/\\".ToCharArray(), f - 1, f - 1); | 
 |  | 
 |                 dirForEntries = directoryName.Substring(f + 1); | 
 |                 dirForEntries = Path.Combine(rootDirectoryPathInArchive, dirForEntries); | 
 |             } | 
 |  | 
 |             // if not top level, or if the root is non-empty, then explicitly add the directory | 
 |             if (level > 0 || rootDirectoryPathInArchive != "") | 
 |             { | 
 |                 baseDir = ZipEntry.CreateFromFile(directoryName, dirForEntries); | 
 |                 baseDir._container = new ZipContainer(this); | 
 |                 baseDir.AlternateEncoding = this.AlternateEncoding;  // workitem 6410 | 
 |                 baseDir.AlternateEncodingUsage = this.AlternateEncodingUsage; | 
 |                 baseDir.MarkAsDirectory(); | 
 |                 baseDir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes; | 
 |                 baseDir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes; | 
 |  | 
 |                 // add the directory only if it does not exist. | 
 |                 // It's not an error if it already exists. | 
 |                 if (!_entries.ContainsKey(baseDir.FileName)) | 
 |                 { | 
 |                     InternalAddEntry(baseDir.FileName,baseDir); | 
 |                     AfterAddEntry(baseDir); | 
 |                 } | 
 |                 dirForEntries = baseDir.FileName; | 
 |             } | 
 |  | 
 |             if (!_addOperationCanceled) | 
 |             { | 
 |  | 
 |                 String[] filenames = Directory.GetFiles(directoryName); | 
 |  | 
 |                 if (recurse) | 
 |                 { | 
 |                     // add the files: | 
 |                     foreach (String filename in filenames) | 
 |                     { | 
 |                         if (_addOperationCanceled) break; | 
 |                         if (action == AddOrUpdateAction.AddOnly) | 
 |                             AddFile(filename, dirForEntries); | 
 |                         else | 
 |                             UpdateFile(filename, dirForEntries); | 
 |                     } | 
 |  | 
 |                     if (!_addOperationCanceled) | 
 |                     { | 
 |                         // add the subdirectories: | 
 |                         String[] dirnames = Directory.GetDirectories(directoryName); | 
 |                         foreach (String dir in dirnames) | 
 |                         { | 
 |                             // workitem 8617: Optionally traverse reparse points | 
 | #if SILVERLIGHT | 
 | #elif NETCF | 
 |                             FileAttributes fileAttrs = (FileAttributes) NetCfFile.GetAttributes(dir); | 
 | #else | 
 |                             FileAttributes fileAttrs = System.IO.File.GetAttributes(dir); | 
 | #endif | 
 |                             if (this.AddDirectoryWillTraverseReparsePoints | 
 | #if !SILVERLIGHT | 
 |                                 || ((fileAttrs & FileAttributes.ReparsePoint) == 0) | 
 | #endif | 
 |                                 ) | 
 |                                 AddOrUpdateDirectoryImpl(dir, rootDirectoryPathInArchive, action, recurse, level + 1); | 
 |  | 
 |                         } | 
 |  | 
 |                     } | 
 |                 } | 
 |             } | 
 |  | 
 |             if (level == 0) | 
 |                 OnAddCompleted(); | 
 |  | 
 |             return baseDir; | 
 |         } | 
 |  | 
 |     } | 
 |  | 
 | } |