Skip to content

Commit

Permalink
Merge pull request #1486 from antony-liu/npoi-bug-1481
Browse files Browse the repository at this point in the history
fix: avoid corrupting docx file with comments
  • Loading branch information
tonyqus authored Feb 7, 2025
2 parents 735c986 + 4e59a37 commit 58de0e4
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
51 changes: 45 additions & 6 deletions OpenXmlFormats/Wordprocessing/Markup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,49 @@ public class CT_Comments

private List<CT_Comment> commentField;

private Dictionary<string, string> extraXmlNamespace = new Dictionary<string, string>();
private Dictionary<string, string> defaultXmlNamespace = new Dictionary<string, string>(){
{ "o", "urn:schemas-microsoft-com:office:office" },
{ "ve", "http://schemas.openxmlformats.org/markup-compatibility/2006" },
{ "r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships" },
{ "v", "urn:schemas-microsoft-com:vml" },
{ "m", "http://schemas.openxmlformats.org/officeDocument/2006/math" },
{ "w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
{ "wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" },
{ "w10", "urn:schemas-microsoft-com:office:word" },
{ "w14", "http://schemas.microsoft.com/office/word/2010/wordml" },
{ "wne", "http://schemas.microsoft.com/office/word/2006/wordml" },

};
public CT_Comments()
{
this.commentField = new List<CT_Comment>();
}
private void FindExtraNamespace(XmlNode node)
{
if (node.Attributes != null)
{
foreach (XmlAttribute attr in node.Attributes)
{
if (attr.Name.StartsWith("xmlns:"))
{
string[] strs = attr.Name.Split(':');
if (strs.Length == 2)
{
if (!extraXmlNamespace.ContainsKey(strs[1]) &&
!defaultXmlNamespace.ContainsKey(strs[1]))
extraXmlNamespace.Add(strs[1], attr.Value);
}
}
}
}
}
public static CT_Comments Parse(XmlNode node, XmlNamespaceManager namespaceManager)
{
if (node == null)
return null;
CT_Comments ctObj = new CT_Comments();
ctObj.FindExtraNamespace(node);
ctObj.comment = new List<CT_Comment>();
foreach (XmlNode childNode in node.ChildNodes)
{
Expand All @@ -201,16 +235,21 @@ public static CT_Comments Parse(XmlNode node, XmlNamespaceManager namespaceManag
}



private void WriteXmlNamespace(StreamWriter sw, Dictionary<string, string> ns)
{
if(ns == null || ns.Count == 0)
return;
foreach (var kv in ns)
{
sw.Write(string.Format($"xmlns:{kv.Key}=\"{kv.Value}\" ", kv.Key, kv.Value));
}
}
internal void Write(StreamWriter sw)
{
sw.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sw.Write(string.Format("<w:comments "));
sw.Write("xmlns:ve=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" ");
sw.Write("xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" ");
sw.Write("xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" ");
sw.Write("xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ");
sw.Write("xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\">");
WriteXmlNamespace(sw, defaultXmlNamespace);
WriteXmlNamespace(sw, extraXmlNamespace);
sw.Write(">");
if (this.comment != null)
{
Expand Down
28 changes: 28 additions & 0 deletions testcases/ooxml/XWPF/UserModel/TestXWPFComments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using NPOI.XWPF.UserModel;
using NUnit.Framework;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;

[TestFixture]
public class TestXWPFComments
Expand Down Expand Up @@ -56,5 +58,31 @@ public void TestReadComments()
Assert.AreEqual(1, allPictures.Count);
}
}

[Test]
public void TestNPOIBug1481()
{
using(XWPFDocument doc = XWPFTestDataSamples.OpenSampleDocument("NPOI-bug-1481.docx"))
{
XWPFComment[] comments = doc.GetComments();
Assert.AreEqual(1, comments.Length);

XWPFComment comment = comments[0];
Assert.AreEqual("Claudio Pais", comment.GetAuthor());
Assert.AreEqual("2025-01-23T17:18:00Z", comment.Date);
Assert.AreEqual("Bla bla", comment.GetText());

XWPFDocument docIn = XWPFTestDataSamples.WriteOutAndReadBack(doc);

comments = docIn.GetComments();
Assert.AreEqual(1, comments.Length);

comment = comments[0];
Assert.AreEqual("Claudio Pais", comment.GetAuthor());
Assert.AreEqual("2025-01-23T17:18:00Z", comment.Date);
Assert.AreEqual("Bla bla", comment.GetText());

}
}
}
}
Binary file added testcases/test-data/document/NPOI-bug-1481.docx
Binary file not shown.

0 comments on commit 58de0e4

Please sign in to comment.