Working on this one now.<br><br>Thanks!<br><br>Alan.<br><br><div class="gmail_quote">On Mon, Mar 16, 2009 at 7:21 PM, Yves Dhondt <span dir="ltr">&lt;<a href="mailto:yves.dhondt@gmail.com">yves.dhondt@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Issue:<br>
-------<br>
ZipPackagePart.GetStreamCore in System.IO.Packaging does not handle<br>
Filemode mode input parameter (correctly).<br>
<br>
Test program (requires an existing openxml document, for example<br>
test.docx as input):<br>
-------------------<br>
I&#39;m not that good with unit testing, but the following code should be<br>
easily translated into 4 tests.<br>
<br>
<br>
using System;<br>
using System.IO;<br>
using System.IO.Packaging;<br>
<br>
namespace MonoOpenXmlExperiment<br>
{<br>
  class Program<br>
  {<br>
    static void Main(string[] args)<br>
    {<br>
      // Warning do this with a document which can be damaged!!!<br>
      Package pack = Package.Open(args[0]);<br>
      PackagePart part = pack.CreatePart(new Uri(&quot;/somepart.xml&quot;,<br>
UriKind.Relative), &quot;application/xml&quot;);<br>
<br>
      try<br>
      {<br>
        Stream s2 = part.GetStream(FileMode.CreateNew, FileAccess.Write);<br>
      }<br>
      catch (Exception ex)<br>
      {<br>
        // An ArgumentException should be throw as CreateNew is an<br>
unsupported mode.<br>
        Console.WriteLine(&quot;Expected ArgumentException, got {0}.&quot;,<br>
ex.GetType().ToString());<br>
      }<br>
<br>
      try<br>
      {<br>
        Stream s3 = part.GetStream(FileMode.Truncate, FileAccess.Write);<br>
      }<br>
      catch (Exception ex)<br>
      {<br>
        // An ArgumentException should be throw as Truncate is an<br>
unsupported mode.<br>
        Console.WriteLine(&quot;Expected ArgumentException, got {0}.&quot;,<br>
ex.GetType().ToString());<br>
      }<br>
<br>
      try<br>
      {<br>
        Stream s4 = part.GetStream(FileMode.Append, FileAccess.Write);<br>
      }<br>
      catch (Exception ex)<br>
      {<br>
        // An ArgumentException should be throw as Append is an<br>
unsupported mode.<br>
        Console.WriteLine(&quot;Expected ArgumentException, got {0}.&quot;,<br>
ex.GetType().ToString());<br>
      }<br>
<br>
      Stream s = part.GetStream(FileMode.OpenOrCreate, FileAccess.Write);<br>
      StreamWriter sw = new StreamWriter(s);<br>
      sw.Write(&quot;&lt;test&gt;aaaaaaa&lt;/test&gt;&quot;);<br>
      sw.Flush();<br>
<br>
      Stream s5 = part.GetStream(FileMode.Create, FileAccess.ReadWrite);<br>
      StreamWriter sw2 = new StreamWriter(s5);<br>
      sw2.Write(&quot;&lt;test&gt;bbb&lt;/test&gt;&quot;);<br>
      sw2.Flush();<br>
<br>
      // Verify that the part got overwritten correctly.<br>
      Stream s6 = part.GetStream();<br>
      StreamReader sr = new StreamReader(s6);<br>
      Console.WriteLine(&quot;Expected &lt;test&gt;bbb&lt;/test&gt;, got {0}.&quot;, sr.ReadToEnd());<br>
<br>
      pack.Close();<br>
    }<br>
  }<br>
}<br>
<br>
<br>
<br>
Expected output:<br>
------------------------<br>
Expected ArgumentException, got System.ArgumentException.<br>
Expected ArgumentException, got System.ArgumentException.<br>
Expected ArgumentException, got System.ArgumentException.<br>
Expected &lt;test&gt;bbb&lt;/test&gt;, got &lt;test&gt;bbb&lt;/test&gt;.<br>
<br>
Output currently given by mono:<br>
---------------------------------------------<br>
Expected &lt;test&gt;bbb&lt;/test&gt;, got &lt;test&gt;bbb&lt;/test&gt;.<br>
<br>
Remarks:<br>
-------------<br>
The last test is especially important as it indicates that a create<br>
would only overwrite part of stream.<br>
<br>
Solution:<br>
------------<br>
Replace function by:<br>
<br>
protected override Stream GetStreamCore (FileMode mode, FileAccess access)<br>
    {<br>
      MemoryStream stream;<br>
<br>
      switch (mode)<br>
      {<br>
        case FileMode.CreateNew:<br>
          throw new ArgumentException(&quot;FileMode not supported&quot;, &quot;CreateNew&quot;);<br>
        case FileMode.Truncate:<br>
          throw new ArgumentException(&quot;FileMode not supported&quot;, &quot;Truncate&quot;);<br>
        case FileMode.Append:<br>
          throw new ArgumentException(&quot;FileMode not supported&quot;, &quot;Append&quot;);<br>
        case FileMode.Open:<br>
          if (Package.PartStreams.TryGetValue(Uri, out stream)) {<br>
            return new ZipPartStream(Package, stream, access);<br>
          }<br>
          else {<br>
            throw new IOException(); // Verify that this is the<br>
correct exception.<br>
          }<br>
        case FileMode.OpenOrCreate:<br>
        case FileMode.Create:<br>
          // Check if a stream is already loaded. If not, load it or<br>
create an empty one.<br>
          if (!Package.PartStreams.TryGetValue(Uri, out stream)) {<br>
            stream = new MemoryStream();<br>
<br>
            try<br>
            {<br>
              using (UnzipArchive archive = new<br>
UnzipArchive(Package.PackageStream))<br>
              {<br>
                foreach (string file in archive.GetFiles())<br>
                {<br>
                  if (file != Uri.ToString().Substring(1))<br>
                    continue;<br>
<br>
                  using (Stream archiveStream = archive.GetStream(file))<br>
                  {<br>
                    int read = 0;<br>
                    byte[] buffer = new<br>
byte[Math.Min(archiveStream.Length, 2 * 1024)];<br>
                    while ((read = archiveStream.Read(buffer, 0,<br>
buffer.Length)) != 0)<br>
                      stream.Write(buffer, 0, read);<br>
                  }<br>
                }<br>
              }<br>
            }<br>
            catch<br>
            {<br>
              // The zipfile is invalid, so just create the file<br>
              // as if it didn&#39;t exist<br>
              stream.SetLength(0);<br>
            }<br>
<br>
            Package.PartStreams.Add(Uri, stream);<br>
          }<br>
<br>
   // This ensures that an existing stream to which a create<br>
   // is applied will be overwritten.<br>
   if (mode == FileMode.Create)<br>
            stream.SetLength(0);<br>
<br>
          return new ZipPartStream(Package, stream, access);<br>
 default:<br>
   throw new ArgumentOutOfRangeException(&quot;mode&quot;);<br>
      }<br>
}<br>
</blockquote></div><br>