Merge pull request #3040 from xmcclure/debugger-step-recursive
[mono.git] / mcs / class / WindowsBase / System.IO.Packaging / ZipPackage.cs
index 28acee83b5a3499b00af40f6cb216a3e3a844f08..783350b09344a6943326be5ae5eafa28a5e589b3 100644 (file)
@@ -49,6 +49,10 @@ namespace System.IO.Packaging {
                private const string ContentNamespace = "http://schemas.openxmlformats.org/package/2006/content-types";
                private const string ContentUri = "[Content_Types].xml";
                
+               bool OwnsStream {
+                       get; set;
+               }
+               
                Dictionary<Uri, ZipPackagePart> parts;
                internal Dictionary<Uri, MemoryStream> PartStreams = new Dictionary<Uri, MemoryStream> (new  UriComparer());
 
@@ -61,16 +65,19 @@ namespace System.IO.Packaging {
                                return parts;
                        }
                }
-               internal ZipPackage (FileAccess access)
+               
+               internal ZipPackage (FileAccess access, bool ownsStream, Stream stream)
                        : base (access)
                {
-
+                       OwnsStream = ownsStream;
+                       PackageStream = stream;
                }
 
-               internal ZipPackage (FileAccess access, bool streaming)
+               internal ZipPackage (FileAccess access, bool ownsStream, Stream stream, bool streaming)
                        : base (access, streaming)
                {
-
+                       OwnsStream = ownsStream;
+                       PackageStream = stream;
                }
                
                protected override void Dispose (bool disposing)
@@ -78,16 +85,21 @@ namespace System.IO.Packaging {
                        foreach (Stream s in PartStreams.Values)
                                s.Close ();
                        
-                       PackageStream.Close ();
+                       base.Dispose (disposing);
+                       
+                       if (OwnsStream)
+                               PackageStream.Close ();
                }
 
                protected override void FlushCore ()
                {
                        // Ensure that all the data has been read out of the package
                        // stream already. Otherwise we'll lose data when we recreate the zip
-                       foreach (ZipPackagePart part in Parts.Values)
-                               part.GetStream ().Dispose ();
-
+                       foreach (ZipPackagePart part in Parts.Values) {
+                               if (part.Package != null)
+                                       part.GetStream ().Dispose ();
+                       }
+                       
                        // Empty the package stream
                        PackageStream.Position = 0;
                        PackageStream.SetLength (0);
@@ -97,10 +109,13 @@ namespace System.IO.Packaging {
 
                                // Write all the part streams
                                foreach (ZipPackagePart part in Parts.Values) {
+                                       if (part.Package == null)
+                                               continue;
+
                                        Stream partStream = part.GetStream ();
                                        partStream.Seek (0, SeekOrigin.Begin);
                                        
-                                       using (Stream destination = archive.GetStream (part.Uri.ToString ().Substring(1))) {
+                                       using (Stream destination = archive.GetStream (part.Uri.ToString ().Substring(1), part.CompressionOption)) {
                                                int count = (int) Math.Min (2048, partStream.Length);
                                                byte[] buffer = new byte [count];
 
@@ -109,7 +124,7 @@ namespace System.IO.Packaging {
                                        }
                                }
 
-                               using (Stream s = archive.GetStream (ContentUri))
+                               using (Stream s = archive.GetStream (ContentUri, CompressionOption.Maximum))
                                        WriteContentType (s);
                        }
                }
@@ -151,20 +166,24 @@ namespace System.IO.Packaging {
                                        using (Stream s = archive.GetStream (ContentUri))
                                                doc.Load (s);
 
-                                       doc.WriteContentTo (new XmlTextWriter (Console.Out));
                                        XmlNamespaceManager manager = new XmlNamespaceManager (doc.NameTable);
                                        manager.AddNamespace ("content", ContentNamespace);
 
+                                       // The file names in the zip archive are not prepended with '/'
                                        foreach (string file in archive.GetFiles ()) {
+                                               if (file.Equals (ContentUri, StringComparison.Ordinal))
+                                                       continue;
+
                                                XmlNode node;
+                                               CompressionOption compression = archive.GetCompressionLevel (file);
 
                                                if (file == RelationshipUri.ToString ().Substring (1))
                                                {
-                                                       CreatePart (RelationshipUri, RelationshipContentType);
+                                                       CreatePartCore (RelationshipUri, RelationshipContentType, compression);
                                                        continue;
                                                }
 
-                                               string xPath = string.Format ("/content:Types/content:Override[@PartName='{0}']", file);
+                                               string xPath = string.Format ("/content:Types/content:Override[@PartName='/{0}']", file);
                                                node = doc.SelectSingleNode (xPath, manager);
 
                                                if (node == null)
@@ -179,7 +198,7 @@ namespace System.IO.Packaging {
                                                // What do i do if the node is null? This means some has tampered with the
                                                // package file manually
                                                if (node != null)
-                                                       CreatePart (new Uri ("/" + file, UriKind.Relative), node.Attributes["ContentType"].Value);
+                                                       CreatePartCore (new Uri ("/" + file, UriKind.Relative), node.Attributes["ContentType"].Value, compression);
                                        }
                                }
                        } catch {
@@ -191,6 +210,8 @@ namespace System.IO.Packaging {
                {
                        XmlDocument doc = new XmlDocument ();
                        XmlNamespaceManager manager = new XmlNamespaceManager (doc.NameTable);
+                       Dictionary<string, string> mimes = new Dictionary<string, string> ();
+                       
                        manager.AddNamespace ("content", ContentNamespace);
 
                        doc.AppendChild(doc.CreateNode (XmlNodeType.XmlDeclaration, "", ""));
@@ -199,19 +220,35 @@ namespace System.IO.Packaging {
                        doc.AppendChild (root);
                        foreach (ZipPackagePart part in Parts.Values)
                        {
-                               XmlNode node = doc.CreateNode (XmlNodeType.Element, "Override", ContentNamespace);
+                               XmlNode node = null;
+                               string existingMimeType;
+                                                                       
+                               var extension = Path.GetExtension (part.Uri.OriginalString);
+                               if (extension.Length > 0)
+                                       extension = extension.Substring (1);
                                
-                               XmlAttribute contentType = doc.CreateAttribute ("ContentType");
-                               contentType.Value = part.ContentType;
-                               
-                               XmlAttribute name = doc.CreateAttribute ("PartName");
-                               name.Value = part.Uri.ToString ().Substring(1);
+                               if (!mimes.TryGetValue (extension, out existingMimeType)) {
+                                       node = doc.CreateNode (XmlNodeType.Element, "Default", ContentNamespace);
+                                       
+                                       XmlAttribute ext = doc.CreateAttribute ("Extension");
+                                       ext.Value = extension;
+                                       node.Attributes.Append (ext);
+                                       mimes [extension] = part.ContentType;
+                               } else if (part.ContentType != existingMimeType) {
+                                       node = doc.CreateNode (XmlNodeType.Element, "Override", ContentNamespace);
+                                       
+                                       XmlAttribute name = doc.CreateAttribute ("PartName");
+                                       name.Value = part.Uri.ToString ();
+                                       node.Attributes.Append (name);
+                               }
                                
-
-                               node.Attributes.Append (contentType);
-                               node.Attributes.Append (name);
-
-                               root.AppendChild (node);                                
+                               if (node != null) {
+                                       XmlAttribute contentType = doc.CreateAttribute ("ContentType");
+                                       contentType.Value = part.ContentType;
+                                       node.Attributes.Prepend (contentType);
+       
+                                       root.AppendChild (node);
+                               }
                        }
 
                        using (XmlTextWriter writer = new XmlTextWriter (s, System.Text.Encoding.UTF8))