瀏覽代碼

Merge pull request #102 from VictorLoktev/master

Added check for restricted XML characters.
master
PrzemyslawKlys 8 年之前
父節點
當前提交
17a7df543d
共有 6 個檔案被更改,包括 203 行新增22 行删除
  1. 21
    2
      DocX/HelperFunctions.cs
  2. 6
    4
      DocX/Paragraph.cs
  3. 26
    15
      DocX/Table.cs
  4. 6
    0
      DocX/bin/Release/DocX.XML
  5. 二進制
      DocX/bin/Release/DocX.dll
  6. 144
    1
      UnitTests/DocXUnitTests.cs

+ 21
- 2
DocX/HelperFunctions.cs 查看文件

@@ -17,7 +17,18 @@ namespace Novacode
public const string DOCUMENT_DOCUMENTTYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
public const string TEMPLATE_DOCUMENTTYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml";
public static bool IsNullOrWhiteSpace(this string value)
/// <summary>
/// List of restricted character in xml: [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]
/// See: https://www.w3.org/TR/xml11/#sec-xml11
/// </summary>
public static readonly char[] RestrictedXmlChar = new char[] {
'\x1','\x2','\x3','\x4','\x5','\x6','\x7','\x8','\xb','\xc','\xe','\xf',
'\x10','\x11','\x12','\x13','\x14','\x15','\x16','\x17','\x18','\x19','\x1a','\x1b','\x1c','\x1e','\x1f',
'\x7f','\x80','\x81','\x82','\x83','\x84','\x86','\x87','\x88','\x89','\x8a','\x8b','\x8c','\x8d','\x8e','\x8f',
'\x90','\x91','\x92','\x93','\x94','\x95','\x96','\x97','\x98','\x99','\x9a','\x9b','\x9c','\x9d','\x9e','\x9f'
};
public static bool IsNullOrWhiteSpace(this string value)
{
if (value == null) return true;
return string.IsNullOrEmpty(value.Trim());
@@ -589,7 +600,15 @@ namespace Novacode
break;
default:
sb.Append(c);
// Check the character against restricted list:
// RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]
// See https://www.w3.org/TR/xml11/#sec-xml11
if( RestrictedXmlChar.Contains( c ) )
{
// skip the character
}
else
sb.Append(c);
break;
}

+ 6
- 4
DocX/Paragraph.cs 查看文件

@@ -1097,7 +1097,7 @@ namespace Novacode
XElement h_xml;
if (index == 0)
{
// Add this hyperlink as the last element.
// Add this hyperlink as the first element.
Xml.AddFirst(h.Xml);
// Extract the picture back out of the DOM.
@@ -1138,10 +1138,12 @@ namespace Novacode
h_xml = (XElement)run.Xml.NextNode;
}
h_xml.SetAttributeValue(DocX.r + "id", Id);
}
}
h_xml.SetAttributeValue( DocX.r + "id", Id );
return this;
this.runs = Xml.Elements().Last().Elements( XName.Get( "r", DocX.w.NamespaceName ) ).ToList();
return this;
}
/// <summary>

+ 26
- 15
DocX/Table.cs 查看文件

@@ -785,19 +785,29 @@ namespace Novacode
if (design == TableDesign.Custom)
{
if (string.IsNullOrEmpty(_customTableDesignName))
{
design = TableDesign.None;
if (style != null)
style.Remove();
}
else
{
val.Value = _customTableDesignName;
}
}
else
#region Code is commented out
// The code gives a problem while copiing a table.
// Look at Test_Clone_Table_Twice method in test.
//Example:
//Table tab1 = doc.Tables[ 0 ];
//Table tab2 = doc.InsertTable( tab1 );
//Table tab3 = doc.InsertTable( tab2 ); - here we have exception at "var styleElement =" line below in this method
// The source of the problem is loosing the "<w:tblStyle w:val="a3"/>" by the commented code
//if (string.IsNullOrEmpty(_customTableDesignName))
//{
// design = TableDesign.None;
// if (style != null)
// style.Remove();
//}
//else
//{
// val.Value = _customTableDesignName;
//}
#endregion
}
else
{
switch (design)
{
@@ -1132,9 +1142,10 @@ namespace Novacode
let styleId = e.Attribute(XName.Get("styleId", DocX.w.NamespaceName))
where (styleId != null && styleId.Value == val.Value)
select e
).First();
).FirstOrDefault();
Document.styles.Element(XName.Get("styles", DocX.w.NamespaceName)).Add(styleElement);
if( styleElement != null )
Document.styles.Element(XName.Get("styles", DocX.w.NamespaceName)).Add(styleElement);
}
}
}

+ 6
- 0
DocX/bin/Release/DocX.XML 查看文件

@@ -475,6 +475,12 @@
The custom property to display.
</summary>
</member>
<member name="F:Novacode.HelperFunctions.RestrictedXmlChar">
<summary>
List of restricted character in xml: [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]
See: https://www.w3.org/TR/xml11/#sec-xml11
</summary>
</member>
<member name="M:Novacode.HelperFunctions.ContainsEveryChildOf(System.Xml.Linq.XElement,System.Xml.Linq.XElement,Novacode.MatchFormattingOptions)">
<summary>
Checks whether 'toCheck' has all children that 'desired' has and values of 'val' attributes are the same

二進制
DocX/bin/Release/DocX.dll 查看文件


+ 144
- 1
UnitTests/DocXUnitTests.cs 查看文件

@@ -150,6 +150,28 @@ namespace UnitTests
}
}
[Test]
public void Test_InvalidCharacter()
{
using( var output = File.Open( Path.Combine( _directoryWithFiles, "InvalidCharacters.docx" ), FileMode.Create ) )
{
using( var doc = DocX.Create( output ) )
{
doc.InsertParagraph( "\b" );
Exception ex = null;
try
{
doc.Save();
}
catch( Exception e )
{
ex = e;
}
Assert.IsTrue( ex == null );
}
}
}
/// <summary>
/// TextRemove should not remove empty paragraphs in case the paragraph is alone in the cell.
/// In the rest cases empty paragraph may be removed.
@@ -274,6 +296,29 @@ namespace UnitTests
}
}
[Test]
public void Test_Clone_Table_Twice()
{
using( var input = File.Open( Path.Combine( _directoryWithFiles, "TableSpecifiedHeights.docx" ), FileMode.Open ) )
{
using( var doc = DocX.Load( input ) )
{
// Make sure content of the file is ok for test
Assert.IsTrue( doc.Tables.Count == 1 );
Table tab1 = doc.Tables[ 0 ];
doc.InsertParagraph( "" );
Table tab2 = doc.InsertTable( tab1 );
Assert.IsTrue( doc.Tables.Count == 2 );
doc.InsertParagraph( "" );
Table tab3 = doc.InsertTable( tab2 );
Assert.IsTrue( doc.Tables.Count == 3 );
doc.SaveAs( Path.Combine( _directoryWithFiles, "TwoClonedTables.docx" ) );
}
}
}
public string ReplaceFunc(string findStr)
{
var testPatterns = new Dictionary<string, string>
@@ -803,7 +848,105 @@ namespace UnitTests
}
}
[Test]
/// <summary>
/// This test fills two tables with hyperlinks.
/// </summary>
[Test]
public void Test_Insert_Hyperlink_In_Tables()
{
using( var input = File.Open( Path.Combine( _directoryWithFiles, "TableSpecifiedHeights.docx" ), FileMode.Open ) )
{
using( var doc = DocX.Load( input ) )
{
// Make sure content of the file is ok for test
Assert.IsTrue( doc.Tables.Count > 0 );
Table tab1 = doc.Tables[ 0 ];
Assert.IsTrue( tab1.RowCount > 0 );
Assert.IsTrue( tab1.Rows[0].ColumnCount > 0 );
doc.InsertParagraph( "" );
Table tab2 = doc.InsertTable( tab1 );
Assert.IsTrue( tab2.RowCount > 0 );
Row row1 = tab1.Rows[ 0 ];
Row row2 = tab2.Rows[ 0 ];
// 10 times insert hyperlinks in both tables in tic-tak order
for( int index = 0; index < 10; index++ )
{
Row newRow1 = tab1.InsertRow( row1 );
Row newRow2 = tab2.InsertRow( row2 );
Hyperlink h1 = doc.AddHyperlink(
string.Format( "Table {0}, Row {1}. Google searches for {0} {1}", 1, index + 1 ),
new Uri( string.Format( "https://www.google.com/search?q=Table{0}Row{1}", 1, index + 1 ) ) );
newRow1.Cells[ 0 ].Paragraphs[ 0 ].InsertHyperlink( h1 );
Hyperlink h2 = doc.AddHyperlink(
string.Format( "Table {0}, Row {1}. Google searches for {0} {1}", 2, index + 1 ),
new Uri( string.Format( "https://www.google.com/search?q=Table{0}Row{1}", 2, index + 1 ) ) );
newRow2.Cells[ 0 ].Paragraphs[ 0 ].InsertHyperlink( h2 );
}
//Make sure links are ok and in right order
for( int index = 0; index < doc.Hyperlinks.Count; index++ )
{
Hyperlink h = doc.Hyperlinks[ index ];
string text = string.Format( "Table {0}, Row {1}. Google searches for {0} {1}", ( index / 10 ) + 1, ( index ) % 10 + 1 );
string uri = string.Format( "https://www.google.com/search?q=Table{0}Row{1}", ( index / 10 ) + 1, ( index ) % 10 + 1 );
Assert.IsTrue( string.Compare( h.Text, text ) == 0 );
Assert.IsTrue( h.Uri != null );
Assert.IsTrue( string.Compare( h.Uri.ToString(), uri ) == 0 );
}
doc.SaveAs( Path.Combine( _directoryDocuments, "Test_Insert_Hyperlink_In_Tables.docx" ) );
}
}
}
/// <summary>
/// This test makes 2 file. The first uses InsertHyperlink. The second uses AppendHyperlink.
/// The both hyperlink collections should be equal to each other.
/// We need be sure the bug in InsertHyperlink is fixed (id attribute in hyperlink was empty and order of inserteed hyperlinks was broken).
/// </summary>
[Test]
public void Test_Compare_InsertHyperlink_And_AppendHyperLinks()
{
string fileName1 = Path.Combine( _directoryDocuments, "Test_InsertHyperLinks.docx" );
string fileName2 = Path.Combine( _directoryDocuments, "Test_AppendHyperlinks.docx" );
using( DocX document1 = DocX.Create( fileName1 ) )
{
using( DocX document2 = DocX.Create( fileName2 ) )
{
for( int index = 0; index < 10; index++ )
{
Hyperlink h = document1.AddHyperlink(
string.Format( "Google searches for {0}", index + 1 ),
new Uri( string.Format( "https://www.google.com/search?q={0}", index + 1 ) ) );
document1.InsertParagraph( "" ).InsertHyperlink( h );
}
document1.Save();
for( int index = 0; index < 10; index++ )
{
Hyperlink h = document2.AddHyperlink(
string.Format( "Google searches for {0}", index + 1 ),
new Uri( string.Format( "https://www.google.com/search?q={0}", index + 1 ) ) );
document2.InsertParagraph( "" ).AppendHyperlink( h );
}
document2.Save();
Assert.IsTrue( document1.Hyperlinks.Count == document2.Hyperlinks.Count );
for( int index = 0; index < document1.Hyperlinks.Count; index++ )
{
Hyperlink h1 = document1.Hyperlinks[ index ];
Hyperlink h2 = document2.Hyperlinks[ index ];
Assert.IsTrue( string.Compare( h1.Text, h2.Text ) == 0 );
Assert.IsTrue( string.Compare( h1.Uri.ToString(), h2.Uri.ToString() ) == 0 );
}
}
}
}
[Test]
public void Test_Insert_Hyperlink()
{
// Load test document.

Loading…
取消
儲存