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());
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)
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);
// 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];
}
}
- using (Stream s = archive.GetStream (ContentUri))
+ using (Stream s = archive.GetStream (ContentUri, CompressionOption.Maximum))
WriteContentType (s);
}
}
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)
// 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 {
{
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, "", ""));
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))