|  | // 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; | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | } |