XmlDsigC14NTransformTest.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. //
  2. // XmlDsigC14NTransformTest.cs - NUnit Test Cases for XmlDsigC14NTransform
  3. //
  4. // Author:
  5. // Sebastien Pouliot <[email protected]>
  6. // Aleksey Sanin ([email protected])
  7. //
  8. // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
  9. // (C) 2003 Aleksey Sanin ([email protected])
  10. // (C) 2004 Novell (http://www.novell.com)
  11. //
  12. using System;
  13. using System.IO;
  14. using System.Security.Cryptography.Xml;
  15. using System.Text;
  16. using System.Xml;
  17. using NUnit.Framework;
  18. namespace MonoTests.System.Security.Cryptography.Xml {
  19. // Note: GetInnerXml is protected in XmlDsigC14NTransform making it
  20. // difficult to test properly. This class "open it up" :-)
  21. public class UnprotectedXmlDsigC14NTransform : XmlDsigC14NTransform {
  22. public XmlNodeList UnprotectedGetInnerXml () {
  23. return base.GetInnerXml ();
  24. }
  25. }
  26. [TestFixture]
  27. public class XmlDsigC14NTransformTest : Assertion {
  28. protected UnprotectedXmlDsigC14NTransform transform;
  29. [SetUp]
  30. protected void SetUp ()
  31. {
  32. transform = new UnprotectedXmlDsigC14NTransform ();
  33. }
  34. [Test]
  35. public void Properties ()
  36. {
  37. AssertEquals ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315", transform.Algorithm);
  38. Type[] input = transform.InputTypes;
  39. Assert ("Input #", (input.Length == 3));
  40. // check presence of every supported input types
  41. bool istream = false;
  42. bool ixmldoc = false;
  43. bool ixmlnl = false;
  44. foreach (Type t in input) {
  45. if (t.ToString () == "System.IO.Stream")
  46. istream = true;
  47. if (t.ToString () == "System.Xml.XmlDocument")
  48. ixmldoc = true;
  49. if (t.ToString () == "System.Xml.XmlNodeList")
  50. ixmlnl = true;
  51. }
  52. Assert ("Input Stream", istream);
  53. Assert ("Input XmlDocument", ixmldoc);
  54. Assert ("Input XmlNodeList", ixmlnl);
  55. Type[] output = transform.OutputTypes;
  56. Assert ("Output #", (output.Length == 1));
  57. // check presence of every supported output types
  58. bool ostream = false;
  59. foreach (Type t in output) {
  60. if (t.ToString () == "System.IO.Stream")
  61. ostream = true;
  62. }
  63. Assert ("Output Stream", ostream);
  64. }
  65. [Test]
  66. public void GetInnerXml ()
  67. {
  68. XmlNodeList xnl = transform.UnprotectedGetInnerXml ();
  69. AssertNull ("Default InnerXml", xnl);
  70. }
  71. private string Stream2String (Stream s)
  72. {
  73. StreamReader sr = new StreamReader (s);
  74. return sr.ReadToEnd ();
  75. }
  76. static string xml = "<Test attrib='at ' xmlns=\"http://www.go-mono.com/\" > \r\n <Toto/> text &amp; </Test >";
  77. // BAD (framework 1.0 result)
  78. static string c14xml1 = "<Test xmlns=\"http://www.go-mono.com/\" attrib=\"at \"> \r\n <Toto></Toto> text &amp; </Test>";
  79. // BAD (framework 1.1 result for Stream)
  80. static string c14xml2 = "<Test xmlns=\"http://www.go-mono.com/\" attrib=\"at \"> \n <Toto></Toto> text &amp; </Test>";
  81. // GOOD (framework 1.1 for XmlDocument and Mono::)
  82. static string c14xml3 = "<Test xmlns=\"http://www.go-mono.com/\" attrib=\"at \"> &#xD;\n <Toto></Toto> text &amp; </Test>";
  83. private XmlDocument GetDoc ()
  84. {
  85. XmlDocument doc = new XmlDocument ();
  86. doc.PreserveWhitespace = true;
  87. doc.LoadXml (xml);
  88. return doc;
  89. }
  90. [Test]
  91. public void LoadInputAsXmlDocument ()
  92. {
  93. XmlDocument doc = GetDoc ();
  94. transform.LoadInput (doc);
  95. Stream s = (Stream) transform.GetOutput ();
  96. string output = Stream2String (s);
  97. #if NET_1_0
  98. // .NET 1.0 keeps the \r\n (0x0D, 0x0A) - bug
  99. AssertEquals("XmlDocument", c14xml1, output);
  100. #else
  101. AssertEquals("XmlDocument", c14xml3, output);
  102. #endif
  103. }
  104. [Test]
  105. [Ignore("FIXME: why doesn't this works with MS ???")]
  106. public void LoadInputAsXmlNodeList ()
  107. {
  108. XmlDocument doc = GetDoc ();
  109. transform.LoadInput (doc.ChildNodes);
  110. Stream s = (Stream) transform.GetOutput ();
  111. string output = Stream2String (s);
  112. // MS returns "<Test></Test>" ??? doesn't makes sense to me
  113. AssertEquals("XmlChildNodes", c14xml3, output);
  114. }
  115. [Test]
  116. public void LoadInputAsStream ()
  117. {
  118. MemoryStream ms = new MemoryStream ();
  119. byte[] x = Encoding.ASCII.GetBytes (xml);
  120. ms.Write (x, 0, x.Length);
  121. ms.Position = 0;
  122. transform.LoadInput (ms);
  123. Stream s = (Stream) transform.GetOutput ();
  124. string output = Stream2String (s);
  125. // ARGH! HOW CAN MS RETURN SOMETHING DIFFERENT IF A
  126. // STREAM IS USED THAN IF A XMLDOCUMENT IS USED :-(
  127. bool result = ((output == c14xml2) || (output == c14xml3));
  128. Assert ("MemoryStream", result);
  129. }
  130. [Test]
  131. public void LoadInputWithUnsupportedType ()
  132. {
  133. byte[] bad = { 0xBA, 0xD };
  134. // LAMESPEC: input MUST be one of InputType - but no exception is thrown (not documented)
  135. transform.LoadInput (bad);
  136. }
  137. [Test]
  138. [ExpectedException (typeof (ArgumentException))]
  139. public void UnsupportedOutput ()
  140. {
  141. XmlDocument doc = new XmlDocument();
  142. object o = transform.GetOutput (doc.GetType ());
  143. }
  144. [Test]
  145. public void C14NSpecExample1 ()
  146. {
  147. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample1Input);
  148. AssertEquals ("Example 1 from c14n spec - PIs, Comments, and Outside of Document Element (without comments)",
  149. C14NSpecExample1Output, res);
  150. }
  151. [Test]
  152. public void C14NSpecExample2 ()
  153. {
  154. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample2Input);
  155. AssertEquals ("Example 2 from c14n spec - Whitespace in Document Content (without comments)",
  156. C14NSpecExample2Output, res);
  157. }
  158. [Test]
  159. public void C14NSpecExample3 ()
  160. {
  161. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample3Input);
  162. AssertEquals ("Example 3 from c14n spec - Start and End Tags (without comments)",
  163. C14NSpecExample3Output, res);
  164. }
  165. [Test]
  166. public void C14NSpecExample4 ()
  167. {
  168. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample4Input);
  169. AssertEquals ("Example 4 from c14n spec - Character Modifications and Character References (without comments)",
  170. C14NSpecExample4Output, res);
  171. }
  172. [Test]
  173. public void C14NSpecExample5 ()
  174. {
  175. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample5Input);
  176. AssertEquals ("Example 5 from c14n spec - Entity References (without comments)",
  177. C14NSpecExample5Output, res);
  178. }
  179. public void C14NSpecExample6 ()
  180. {
  181. string res = ExecuteXmlDSigC14NTransform (C14NSpecExample6Input);
  182. AssertEquals ("Example 6 from c14n spec - UTF-8 Encoding (without comments)",
  183. C14NSpecExample6Output, res);
  184. }
  185. private string ExecuteXmlDSigC14NTransform (string InputXml)
  186. {
  187. XmlDocument doc = new XmlDocument ();
  188. doc.PreserveWhitespace = true;
  189. doc.LoadXml (InputXml);
  190. // Testing default attribute support with
  191. // vreader.ValidationType = ValidationType.None.
  192. //
  193. UTF8Encoding utf8 = new UTF8Encoding ();
  194. byte[] data = utf8.GetBytes (InputXml.ToString ());
  195. Stream stream = new MemoryStream (data);
  196. XmlTextReader reader = new XmlTextReader (stream);
  197. XmlValidatingReader vreader = new XmlValidatingReader (reader);
  198. vreader.ValidationType = ValidationType.None;
  199. vreader.EntityHandling = EntityHandling.ExpandCharEntities;
  200. doc.Load (vreader);
  201. transform.LoadInput (doc);
  202. return Stream2String ((Stream)transform.GetOutput ());
  203. }
  204. //
  205. // Example 1 from C14N spec - PIs, Comments, and Outside of Document Element:
  206. // http://www.w3.org/TR/xml-c14n#Example-OutsideDoc
  207. //
  208. // Aleksey:
  209. // removed reference to an empty external DTD
  210. //
  211. static string C14NSpecExample1Input =
  212. "<?xml version=\"1.0\"?>\n" +
  213. "\n" +
  214. "<?xml-stylesheet href=\"doc.xsl\"\n" +
  215. " type=\"text/xsl\" ?>\n" +
  216. "\n" +
  217. // "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n" +
  218. "\n" +
  219. "<doc>Hello, world!<!-- Comment 1 --></doc>\n" +
  220. "\n" +
  221. "<?pi-without-data ?>\n\n" +
  222. "<!-- Comment 2 -->\n\n" +
  223. "<!-- Comment 3 -->\n";
  224. static string C14NSpecExample1Output =
  225. "<?xml-stylesheet href=\"doc.xsl\"\n" +
  226. " type=\"text/xsl\" ?>\n" +
  227. "<doc>Hello, world!</doc>\n" +
  228. "<?pi-without-data?>";
  229. //
  230. // Example 2 from C14N spec - Whitespace in Document Content:
  231. // http://www.w3.org/TR/xml-c14n#Example-WhitespaceInContent
  232. //
  233. static string C14NSpecExample2Input =
  234. "<doc>\n" +
  235. " <clean> </clean>\n" +
  236. " <dirty> A B </dirty>\n" +
  237. " <mixed>\n" +
  238. " A\n" +
  239. " <clean> </clean>\n" +
  240. " B\n" +
  241. " <dirty> A B </dirty>\n" +
  242. " C\n" +
  243. " </mixed>\n" +
  244. "</doc>\n";
  245. static string C14NSpecExample2Output =
  246. "<doc>\n" +
  247. " <clean> </clean>\n" +
  248. " <dirty> A B </dirty>\n" +
  249. " <mixed>\n" +
  250. " A\n" +
  251. " <clean> </clean>\n" +
  252. " B\n" +
  253. " <dirty> A B </dirty>\n" +
  254. " C\n" +
  255. " </mixed>\n" +
  256. "</doc>";
  257. //
  258. // Example 3 from C14N spec - Start and End Tags:
  259. // http://www.w3.org/TR/xml-c14n#Example-SETags
  260. //
  261. static string C14NSpecExample3Input =
  262. "<!DOCTYPE doc [<!ATTLIST e9 attr CDATA \"default\">]>\n" +
  263. "<doc>\n" +
  264. " <e1 />\n" +
  265. " <e2 ></e2>\n" +
  266. " <e3 name = \"elem3\" id=\"elem3\" />\n" +
  267. " <e4 name=\"elem4\" id=\"elem4\" ></e4>\n" +
  268. " <e5 a:attr=\"out\" b:attr=\"sorted\" attr2=\"all\" attr=\"I\'m\"\n" +
  269. " xmlns:b=\"http://www.ietf.org\" \n" +
  270. " xmlns:a=\"http://www.w3.org\"\n" +
  271. " xmlns=\"http://www.uvic.ca\"/>\n" +
  272. " <e6 xmlns=\"\" xmlns:a=\"http://www.w3.org\">\n" +
  273. " <e7 xmlns=\"http://www.ietf.org\">\n" +
  274. " <e8 xmlns=\"\" xmlns:a=\"http://www.w3.org\">\n" +
  275. " <e9 xmlns=\"\" xmlns:a=\"http://www.ietf.org\"/>\n" +
  276. " </e8>\n" +
  277. " </e7>\n" +
  278. " </e6>\n" +
  279. "</doc>\n";
  280. static string C14NSpecExample3Output =
  281. "<doc>\n" +
  282. " <e1></e1>\n" +
  283. " <e2></e2>\n" +
  284. " <e3 id=\"elem3\" name=\"elem3\"></e3>\n" +
  285. " <e4 id=\"elem4\" name=\"elem4\"></e4>\n" +
  286. " <e5 xmlns=\"http://www.uvic.ca\" xmlns:a=\"http://www.w3.org\" xmlns:b=\"http://www.ietf.org\" attr=\"I\'m\" attr2=\"all\" b:attr=\"sorted\" a:attr=\"out\"></e5>\n" +
  287. " <e6 xmlns:a=\"http://www.w3.org\">\n" +
  288. " <e7 xmlns=\"http://www.ietf.org\">\n" +
  289. " <e8 xmlns=\"\">\n" +
  290. " <e9 xmlns:a=\"http://www.ietf.org\" attr=\"default\"></e9>\n" +
  291. // " <e9 xmlns:a=\"http://www.ietf.org\"></e9>\n" +
  292. " </e8>\n" +
  293. " </e7>\n" +
  294. " </e6>\n" +
  295. "</doc>";
  296. //
  297. // Example 4 from C14N spec - Character Modifications and Character References:
  298. // http://www.w3.org/TR/xml-c14n#Example-Chars
  299. //
  300. // Aleksey:
  301. // This test does not include "normId" element
  302. // because it has an invalid ID attribute "id" which
  303. // should be normalized by XML parser. Currently Mono
  304. // does not support this (see comment after this example
  305. // in the spec).
  306. static string C14NSpecExample4Input =
  307. "<!DOCTYPE doc [<!ATTLIST normId id ID #IMPLIED>]>\n" +
  308. "<doc>\n" +
  309. " <text>First line&#x0d;&#10;Second line</text>\n" +
  310. " <value>&#x32;</value>\n" +
  311. " <compute><![CDATA[value>\"0\" && value<\"10\" ?\"valid\":\"error\"]]></compute>\n" +
  312. " <compute expr=\'value>\"0\" &amp;&amp; value&lt;\"10\" ?\"valid\":\"error\"\'>valid</compute>\n" +
  313. " <norm attr=\' &apos; &#x20;&#13;&#xa;&#9; &apos; \'/>\n" +
  314. // " <normId id=\' &apos; &#x20;&#13;&#xa;&#9; &apos; \'/>\n" +
  315. "</doc>\n";
  316. static string C14NSpecExample4Output =
  317. "<doc>\n" +
  318. " <text>First line&#xD;\n" +
  319. "Second line</text>\n" +
  320. " <value>2</value>\n" +
  321. " <compute>value&gt;\"0\" &amp;&amp; value&lt;\"10\" ?\"valid\":\"error\"</compute>\n" +
  322. " <compute expr=\"value>&quot;0&quot; &amp;&amp; value&lt;&quot;10&quot; ?&quot;valid&quot;:&quot;error&quot;\">valid</compute>\n" +
  323. " <norm attr=\" \' &#xD;&#xA;&#x9; \' \"></norm>\n" +
  324. // " <normId id=\"\' &#xD;&#xA;&#x9; \'\"></normId>\n" +
  325. "</doc>";
  326. //
  327. // Example 5 from C14N spec - Entity References:
  328. // http://www.w3.org/TR/xml-c14n#Example-Entities
  329. //
  330. static string C14NSpecExample5Input =
  331. "<!DOCTYPE doc [\n" +
  332. "<!ATTLIST doc attrExtEnt ENTITY #IMPLIED>\n" +
  333. "<!ENTITY ent1 \"Hello\">\n" +
  334. "<!ENTITY ent2 SYSTEM \"world.txt\">\n" +
  335. "<!ENTITY entExt SYSTEM \"earth.gif\" NDATA gif>\n" +
  336. "<!NOTATION gif SYSTEM \"viewgif.exe\">\n" +
  337. "]>\n" +
  338. "<doc attrExtEnt=\"entExt\">\n" +
  339. " &ent1;, &ent2;!\n" +
  340. "</doc>\n" +
  341. "\n" +
  342. "<!-- Let world.txt contain \"world\" (excluding the quotes) -->\n";
  343. static string C14NSpecExample5Output =
  344. "<doc attrExtEnt=\"entExt\">\n" +
  345. " Hello, world!\n" +
  346. "</doc>";
  347. //
  348. // Example 6 from C14N spec - UTF-8 Encoding:
  349. // http://www.w3.org/TR/xml-c14n#Example-UTF8
  350. //
  351. static string C14NSpecExample6Input =
  352. "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" +
  353. "<doc>&#169;</doc>\n";
  354. static string C14NSpecExample6Output =
  355. "<doc>\xC2\xA9</doc>";
  356. //
  357. // Example 7 from C14N spec - Document Subsets:
  358. // http://www.w3.org/TR/xml-c14n#Example-DocSubsets
  359. //
  360. // Aleksey:
  361. // Well, XPath support in Mono is far from complete....
  362. // I was not able to simplify the xpath expression from this test
  363. // so it runs on Mono and still makes sense for testing this feature.
  364. // Thus this test is not included in the suite now.
  365. static string C14NSpecExample7Input =
  366. "<!DOCTYPE doc [\n" +
  367. "<!ATTLIST e2 xml:space (default|preserve) \'preserve\'>\n" +
  368. "<!ATTLIST e3 id ID #IMPLIED>\n" +
  369. "]>\n" +
  370. "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n" +
  371. " <e1>\n" +
  372. " <e2 xmlns=\"\">\n" +
  373. " <e3 id=\"E3\"/>\n" +
  374. " </e2>\n" +
  375. " </e1>\n" +
  376. "</doc>\n";
  377. static string C14NSpecExample7Xpath =
  378. "(//.|//@*|//namespace::*)\n" +
  379. "[\n" +
  380. "self::ietf:e1\n" +
  381. " or\n" +
  382. "(parent::ietf:e1 and not(self::text() or self::e2))\n" +
  383. " or\n" +
  384. "count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n" +
  385. "]";
  386. static string C14NSpecExample7Output =
  387. "<e1 xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\"><e3 xmlns=\"\" id=\"E3\" xml:space=\"preserve\"></e3></e1>";
  388. }
  389. }