[Mono-dev] Patch for ZipPackagePart.GetStreamCore in System.IO.Packaging (olive)
Alan McGovern
alan.mcgovern at gmail.com
Wed Mar 18 07:58:19 EDT 2009
Working on this one now.
Thanks!
Alan.
On Mon, Mar 16, 2009 at 7:21 PM, Yves Dhondt <yves.dhondt at gmail.com> wrote:
> Issue:
> -------
> ZipPackagePart.GetStreamCore in System.IO.Packaging does not handle
> Filemode mode input parameter (correctly).
>
> Test program (requires an existing openxml document, for example
> test.docx as input):
> -------------------
> I'm not that good with unit testing, but the following code should be
> easily translated into 4 tests.
>
>
> using System;
> using System.IO;
> using System.IO.Packaging;
>
> namespace MonoOpenXmlExperiment
> {
> class Program
> {
> static void Main(string[] args)
> {
> // Warning do this with a document which can be damaged!!!
> Package pack = Package.Open(args[0]);
> PackagePart part = pack.CreatePart(new Uri("/somepart.xml",
> UriKind.Relative), "application/xml");
>
> try
> {
> Stream s2 = part.GetStream(FileMode.CreateNew, FileAccess.Write);
> }
> catch (Exception ex)
> {
> // An ArgumentException should be throw as CreateNew is an
> unsupported mode.
> Console.WriteLine("Expected ArgumentException, got {0}.",
> ex.GetType().ToString());
> }
>
> try
> {
> Stream s3 = part.GetStream(FileMode.Truncate, FileAccess.Write);
> }
> catch (Exception ex)
> {
> // An ArgumentException should be throw as Truncate is an
> unsupported mode.
> Console.WriteLine("Expected ArgumentException, got {0}.",
> ex.GetType().ToString());
> }
>
> try
> {
> Stream s4 = part.GetStream(FileMode.Append, FileAccess.Write);
> }
> catch (Exception ex)
> {
> // An ArgumentException should be throw as Append is an
> unsupported mode.
> Console.WriteLine("Expected ArgumentException, got {0}.",
> ex.GetType().ToString());
> }
>
> Stream s = part.GetStream(FileMode.OpenOrCreate, FileAccess.Write);
> StreamWriter sw = new StreamWriter(s);
> sw.Write("<test>aaaaaaa</test>");
> sw.Flush();
>
> Stream s5 = part.GetStream(FileMode.Create, FileAccess.ReadWrite);
> StreamWriter sw2 = new StreamWriter(s5);
> sw2.Write("<test>bbb</test>");
> sw2.Flush();
>
> // Verify that the part got overwritten correctly.
> Stream s6 = part.GetStream();
> StreamReader sr = new StreamReader(s6);
> Console.WriteLine("Expected <test>bbb</test>, got {0}.",
> sr.ReadToEnd());
>
> pack.Close();
> }
> }
> }
>
>
>
> Expected output:
> ------------------------
> Expected ArgumentException, got System.ArgumentException.
> Expected ArgumentException, got System.ArgumentException.
> Expected ArgumentException, got System.ArgumentException.
> Expected <test>bbb</test>, got <test>bbb</test>.
>
> Output currently given by mono:
> ---------------------------------------------
> Expected <test>bbb</test>, got <test>bbb</test>.
>
> Remarks:
> -------------
> The last test is especially important as it indicates that a create
> would only overwrite part of stream.
>
> Solution:
> ------------
> Replace function by:
>
> protected override Stream GetStreamCore (FileMode mode, FileAccess access)
> {
> MemoryStream stream;
>
> switch (mode)
> {
> case FileMode.CreateNew:
> throw new ArgumentException("FileMode not supported",
> "CreateNew");
> case FileMode.Truncate:
> throw new ArgumentException("FileMode not supported",
> "Truncate");
> case FileMode.Append:
> throw new ArgumentException("FileMode not supported", "Append");
> case FileMode.Open:
> if (Package.PartStreams.TryGetValue(Uri, out stream)) {
> return new ZipPartStream(Package, stream, access);
> }
> else {
> throw new IOException(); // Verify that this is the
> correct exception.
> }
> case FileMode.OpenOrCreate:
> case FileMode.Create:
> // Check if a stream is already loaded. If not, load it or
> create an empty one.
> if (!Package.PartStreams.TryGetValue(Uri, out stream)) {
> stream = new MemoryStream();
>
> try
> {
> using (UnzipArchive archive = new
> UnzipArchive(Package.PackageStream))
> {
> foreach (string file in archive.GetFiles())
> {
> if (file != Uri.ToString().Substring(1))
> continue;
>
> using (Stream archiveStream = archive.GetStream(file))
> {
> int read = 0;
> byte[] buffer = new
> byte[Math.Min(archiveStream.Length, 2 * 1024)];
> while ((read = archiveStream.Read(buffer, 0,
> buffer.Length)) != 0)
> stream.Write(buffer, 0, read);
> }
> }
> }
> }
> catch
> {
> // The zipfile is invalid, so just create the file
> // as if it didn't exist
> stream.SetLength(0);
> }
>
> Package.PartStreams.Add(Uri, stream);
> }
>
> // This ensures that an existing stream to which a create
> // is applied will be overwritten.
> if (mode == FileMode.Create)
> stream.SetLength(0);
>
> return new ZipPartStream(Package, stream, access);
> default:
> throw new ArgumentOutOfRangeException("mode");
> }
> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20090318/33e55964/attachment-0001.html
More information about the Mono-devel-list
mailing list