Преглед изворни кода

Fix to prevent deadlocks in multi-threaded applications

See https://support.microsoft.com/en-us/kb/2996566 (Issue 1) for more
details. But in summary if the document is larger than 10Mb, then deadlocks
can occur in multi-threaded applications.
master
teatime пре 9 година
родитељ
комит
6f4d3e506a
7 измењених фајлова са 126 додато и 40 уклоњено
  1. 2
    2
      DocX/Container.cs
  2. 31
    31
      DocX/DocX.cs
  3. 1
    0
      DocX/DocX.csproj
  4. 5
    5
      DocX/HelperFunctions.cs
  5. 1
    1
      DocX/Image.cs
  6. 85
    0
      DocX/PackagePartStream.cs
  7. 1
    1
      DocX/Paragraph.cs

+ 2
- 2
DocX/Container.cs Прегледај датотеку

if (!Document.package.PartExists(style_package_uri)) if (!Document.package.PartExists(style_package_uri))
{ {
PackagePart style_package = Document.package.CreatePart(style_package_uri, "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", CompressionOption.Maximum); PackagePart style_package = Document.package.CreatePart(style_package_uri, "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", CompressionOption.Maximum);
using (TextWriter tw = new StreamWriter(style_package.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(style_package.GetStream())))
{ {
style_document = new XDocument style_document = new XDocument
( (
} }
} }
using (TextWriter tw = new StreamWriter(styles_document.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(styles_document.GetStream())))
style_document.Save(tw); style_document.Save(tw);
} }
#endregion #endregion

+ 31
- 31
DocX/DocX.cs Прегледај датотеку

evenAndOddHeaders.Remove(); evenAndOddHeaders.Remove();
} }
using (TextWriter tw = new StreamWriter(settingsPart.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream())))
settings.Save(tw); settings.Save(tw);
} }
} }
using (Stream s_read = remote_pp.GetStream()) using (Stream s_read = remote_pp.GetStream())
{ {
using (Stream s_write = new_pp.GetStream(FileMode.Create))
using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create)))
{ {
byte[] buffer = new byte[32768]; byte[] buffer = new byte[32768];
int read; int read;
} }
// Save the modified local custom styles.xml file. // Save the modified local custom styles.xml file.
using (TextWriter tw = new StreamWriter(local_pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(local_pp.GetStream(FileMode.Create, FileAccess.Write))))
local_custom_document.Save(tw, SaveOptions.None); local_custom_document.Save(tw, SaveOptions.None);
} }
using (Stream s_read = pp.GetStream()) using (Stream s_read = pp.GetStream())
{ {
using (Stream s_write = new_pp.GetStream(FileMode.Create))
using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create)))
{ {
byte[] buffer = new byte[32768]; byte[] buffer = new byte[32768];
int read; int read;
wordStyles.Element(w + "styles").Add(style); wordStyles.Element(w + "styles").Add(style);
// Save the styles document. // Save the styles document.
using (TextWriter tw = new StreamWriter(package.GetPart(wordStylesUri).GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(wordStylesUri).GetStream())))
wordStyles.Save(tw); wordStyles.Save(tw);
} }
} }
// Save the main document // Save the main document
using (TextWriter tw = new StreamWriter(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write))))
mainDoc.Save(tw, SaveOptions.None); mainDoc.Save(tw, SaveOptions.None);
#endregion #endregion
{ {
using ( using (
StreamWriter tw = new StreamWriter( StreamWriter tw = new StreamWriter(
globalRelsPart.GetStream(FileMode.Create, FileAccess.Write), Encoding.UTF8))
new PackagePartStream(globalRelsPart.GetStream(FileMode.Create, FileAccess.Write)), Encoding.UTF8))
{ {
tw.Write(tr.ReadToEnd()); tw.Write(tr.ReadToEnd());
} }
{ {
using ( using (
StreamWriter tw = new StreamWriter( StreamWriter tw = new StreamWriter(
nativePart.GetStream(FileMode.Create, FileAccess.Write), tr.CurrentEncoding))
new PackagePartStream(nativePart.GetStream(FileMode.Create, FileAccess.Write)), tr.CurrentEncoding))
{ {
tw.Write(tr.ReadToEnd()); tw.Write(tr.ReadToEnd());
} }
} }
PackagePart documentNewPart = this.package.CreatePart( PackagePart documentNewPart = this.package.CreatePart(
documentPart.Uri, mainContentType, documentPart.CompressionOption); documentPart.Uri, mainContentType, documentPart.CompressionOption);
using (XmlWriter xw = XmlWriter.Create(documentNewPart.GetStream(FileMode.Create, FileAccess.Write)))
using (XmlWriter xw = XmlWriter.Create(new PackagePartStream(documentNewPart.GetStream(FileMode.Create, FileAccess.Write))))
{ {
documentDoc.WriteTo(xw); documentDoc.WriteTo(xw);
} }
word_styles.Element(w + "styles").Add(style); word_styles.Element(w + "styles").Add(style);
// Save the styles document. // Save the styles document.
using (TextWriter tw = new StreamWriter(package.GetPart(word_styles_Uri).GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(word_styles_Uri).GetStream())))
word_styles.Save(tw); word_styles.Save(tw);
} }
} }
} }
// Save the main document // Save the main document
using (TextWriter tw = new StreamWriter(headerPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(headerPart.GetStream(FileMode.Create, FileAccess.Write))))
header.Save(tw, SaveOptions.None); header.Save(tw, SaveOptions.None);
string type; string type;
PackageRelationship rel = mainPart.CreateRelationship(img.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); PackageRelationship rel = mainPart.CreateRelationship(img.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
// Open a Stream to the newly created Image part. // Open a Stream to the newly created Image part.
using (Stream stream = img.GetStream(FileMode.Create, FileAccess.Write))
using (Stream stream = new PackagePartStream(img.GetStream(FileMode.Create, FileAccess.Write)))
{ {
// Using the Stream to the real image, copy this streams data into the newly create Image part. // Using the Stream to the real image, copy this streams data into the newly create Image part.
using (newImageStream) using (newImageStream)
Headers headers = Headers; Headers headers = Headers;
// Save the main document // Save the main document
using (TextWriter tw = new StreamWriter(mainPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(mainPart.GetStream(FileMode.Create, FileAccess.Write))))
mainDoc.Save(tw, SaveOptions.None); mainDoc.Save(tw, SaveOptions.None);
if (settings == null) if (settings == null)
mainPart.GetRelationship(evenHeaderRef).TargetUri mainPart.GetRelationship(evenHeaderRef).TargetUri
); );
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
); );
// Save header1 // Save header1
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
); );
// Save header3 // Save header3
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
); );
// Save header1 // Save header1
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
); );
// Save header2 // Save header2
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
); );
// Save header3 // Save header3
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{ {
new XDocument new XDocument
( (
} }
// Save the settings document. // Save the settings document.
using (TextWriter tw = new StreamWriter(settingsPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream(FileMode.Create, FileAccess.Write))))
settings.Save(tw, SaveOptions.None); settings.Save(tw, SaveOptions.None);
if (endnotesPart != null) if (endnotesPart != null)
{ {
using (TextWriter tw = new StreamWriter(endnotesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(endnotesPart.GetStream(FileMode.Create, FileAccess.Write))))
endnotes.Save(tw, SaveOptions.None); endnotes.Save(tw, SaveOptions.None);
} }
if (footnotesPart != null) if (footnotesPart != null)
{ {
using (TextWriter tw = new StreamWriter(footnotesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(footnotesPart.GetStream(FileMode.Create, FileAccess.Write))))
footnotes.Save(tw, SaveOptions.None); footnotes.Save(tw, SaveOptions.None);
} }
if (stylesPart != null) if (stylesPart != null)
{ {
using (TextWriter tw = new StreamWriter(stylesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(stylesPart.GetStream(FileMode.Create, FileAccess.Write))))
styles.Save(tw, SaveOptions.None); styles.Save(tw, SaveOptions.None);
} }
if (stylesWithEffectsPart != null) if (stylesWithEffectsPart != null)
{ {
using (TextWriter tw = new StreamWriter(stylesWithEffectsPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(stylesWithEffectsPart.GetStream(FileMode.Create, FileAccess.Write))))
stylesWithEffects.Save(tw, SaveOptions.None); stylesWithEffects.Save(tw, SaveOptions.None);
} }
if (numberingPart != null) if (numberingPart != null)
{ {
using (TextWriter tw = new StreamWriter(numberingPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(numberingPart.GetStream(FileMode.Create, FileAccess.Write))))
numbering.Save(tw, SaveOptions.None); numbering.Save(tw, SaveOptions.None);
} }
if (fontTablePart != null) if (fontTablePart != null)
{ {
using (TextWriter tw = new StreamWriter(fontTablePart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(fontTablePart.GetStream(FileMode.Create, FileAccess.Write))))
fontTable.Save(tw, SaveOptions.None); fontTable.Save(tw, SaveOptions.None);
} }
} }
corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue)); corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue));
} }
using (TextWriter tw = new StreamWriter(corePropPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(corePropPart.GetStream(FileMode.Create, FileAccess.Write))))
{ {
corePropDoc.Save(tw); corePropDoc.Save(tw);
} }
} }
} }
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream(FileMode.Create, FileAccess.Write))))
header.Save(tw); header.Save(tw);
} }
#endregion #endregion
} }
} }
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream(FileMode.Create, FileAccess.Write))))
footer.Save(tw); footer.Save(tw);
} }
#endregion #endregion
); );
// Save the custom properties // Save the custom properties
using (TextWriter tw = new StreamWriter(customPropPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(customPropPart.GetStream(FileMode.Create, FileAccess.Write))))
customPropDoc.Save(tw, SaveOptions.None); customPropDoc.Save(tw, SaveOptions.None);
// Refresh all fields in this document which display this custom property. // Refresh all fields in this document which display this custom property.
PackageRelationship rel = mainPart.CreateRelationship(chartPackagePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", relID); PackageRelationship rel = mainPart.CreateRelationship(chartPackagePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", relID);
// Save a chart info the chartPackagePart // Save a chart info the chartPackagePart
using (TextWriter tw = new StreamWriter(chartPackagePart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(chartPackagePart.GetStream(FileMode.Create, FileAccess.Write))))
chart.Xml.Save(tw); chart.Xml.Save(tw);
// Insert a new chart into a paragraph. // Insert a new chart into a paragraph.

+ 1
- 0
DocX/DocX.csproj Прегледај датотеку

<Compile Include="IContentContainer.cs" /> <Compile Include="IContentContainer.cs" />
<Compile Include="IParagraphContainer.cs" /> <Compile Include="IParagraphContainer.cs" />
<Compile Include="List.cs" /> <Compile Include="List.cs" />
<Compile Include="PackagePartStream.cs" />
<Compile Include="PageLayout.cs" /> <Compile Include="PageLayout.cs" />
<Compile Include="Section.cs" /> <Compile Include="Section.cs" />
<Compile Include="TableOfContents.cs" /> <Compile Include="TableOfContents.cs" />

+ 5
- 5
DocX/HelperFunctions.cs Прегледај датотеку

internal static void CreateRelsPackagePart(DocX Document, Uri uri) internal static void CreateRelsPackagePart(DocX Document, Uri uri)
{ {
PackagePart pp = Document.package.CreatePart(uri, "application/vnd.openxmlformats-package.relationships+xml", CompressionOption.Maximum); PackagePart pp = Document.package.CreatePart(uri, "application/vnd.openxmlformats-package.relationships+xml", CompressionOption.Maximum);
using (TextWriter tw = new StreamWriter(pp.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream())))
{ {
XDocument d = new XDocument XDocument d = new XDocument
( (
themeFontLang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture); themeFontLang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture);
// Save the settings document. // Save the settings document.
using (TextWriter tw = new StreamWriter(settingsPart.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream())))
settings.Save(tw); settings.Save(tw);
} }
else else
) )
); );
using (TextWriter tw = new StreamWriter(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write))))
customPropDoc.Save(tw, SaveOptions.None); customPropDoc.Save(tw, SaveOptions.None);
document.package.CreateRelationship(customPropertiesPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"); document.package.CreateRelationship(customPropertiesPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
numberingDoc = DecompressXMLResource("Novacode.Resources.numbering.xml.gz"); numberingDoc = DecompressXMLResource("Novacode.Resources.numbering.xml.gz");
// Save /word/numbering.xml // Save /word/numbering.xml
using (TextWriter tw = new StreamWriter(wordNumbering.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(wordNumbering.GetStream(FileMode.Create, FileAccess.Write))))
numberingDoc.Save(tw, SaveOptions.None); numberingDoc.Save(tw, SaveOptions.None);
PackagePart mainDocumentPart = package.GetParts().Single(p => p.ContentType.Equals(DOCUMENT_DOCUMENTTYPE, StringComparison.CurrentCultureIgnoreCase) || PackagePart mainDocumentPart = package.GetParts().Single(p => p.ContentType.Equals(DOCUMENT_DOCUMENTTYPE, StringComparison.CurrentCultureIgnoreCase) ||
lang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture); lang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture);
// Save /word/styles.xml // Save /word/styles.xml
using (TextWriter tw = new StreamWriter(word_styles.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(word_styles.GetStream(FileMode.Create, FileAccess.Write))))
stylesDoc.Save(tw, SaveOptions.None); stylesDoc.Save(tw, SaveOptions.None);
PackagePart mainDocumentPart = package.GetParts().Where PackagePart mainDocumentPart = package.GetParts().Where

+ 1
- 1
DocX/Image.cs Прегледај датотеку

string end = pr.TargetUri.OriginalString; string end = pr.TargetUri.OriginalString;
string full = start + "/" + end; string full = start + "/" + end;
return(document.package.GetPart(new Uri(full, UriKind.Relative)).GetStream(mode, access));
return(new PackagePartStream(document.package.GetPart(new Uri(full, UriKind.Relative)).GetStream(mode, access)));
} }
/// <summary> /// <summary>

+ 85
- 0
DocX/PackagePartStream.cs Прегледај датотеку

using System.IO;
using System.Threading;

namespace Novacode
{
/// <summary>
/// See <a href="https://support.microsoft.com/en-gb/kb/951731" /> for explanation
/// </summary>
public class PackagePartStream : Stream
{
private static readonly Mutex Mutex = new Mutex(false);

private readonly Stream stream;

public PackagePartStream(Stream stream)
{
this.stream = stream;
}

public override bool CanRead
{
get { return this.stream.CanRead; }
}

public override bool CanSeek
{
get { return this.stream.CanSeek; }
}

public override bool CanWrite
{
get { return this.stream.CanWrite; }
}

public override long Length
{
get { return this.stream.Length; }
}

public override long Position
{
get { return this.stream.Position; }
set { this.stream.Position = value; }
}

public override long Seek(long offset, SeekOrigin origin)
{
return this.stream.Seek(offset, origin);
}

public override void SetLength(long value)
{
this.stream.SetLength(value);
}

public override int Read(byte[] buffer, int offset, int count)
{
return this.stream.Read(buffer, offset, count);
}

public override void Write(byte[] buffer, int offset, int count)
{
Mutex.WaitOne(Timeout.Infinite, false);
this.stream.Write(buffer, offset, count);
Mutex.ReleaseMutex();
}

public override void Flush()
{
Mutex.WaitOne(Timeout.Infinite, false);
this.stream.Flush();
Mutex.ReleaseMutex();
}

public override void Close()
{
this.stream.Close();
}

protected override void Dispose(bool disposing)
{
this.stream.Dispose();
}
}
}

+ 1
- 1
DocX/Paragraph.cs Прегледај датотеку

int cx, cy; int cx, cy;
using (System.Drawing.Image img = System.Drawing.Image.FromStream(part.GetStream()))
using (System.Drawing.Image img = System.Drawing.Image.FromStream(new PackagePartStream(part.GetStream())))
{ {
cx = img.Width * 9526; cx = img.Width * 9526;
cy = img.Height * 9526; cy = img.Height * 9526;

Loading…
Откажи
Сачувај