You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
8.9KB

  1. <?php
  2. class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
  3. {
  4. /**
  5. * Entity lookup table to help for a few tests.
  6. */
  7. private $_entity_lookup;
  8. public function __construct()
  9. {
  10. parent::__construct();
  11. $this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
  12. }
  13. public function setUp()
  14. {
  15. parent::setUp();
  16. $this->config->set('Output.Newline', "\n");
  17. }
  18. /**
  19. * Creates a generator based on config and context member variables.
  20. */
  21. protected function createGenerator()
  22. {
  23. return new HTMLPurifier_Generator($this->config, $this->context);
  24. }
  25. protected function assertGenerateFromToken($token, $html)
  26. {
  27. $generator = $this->createGenerator();
  28. $result = $generator->generateFromToken($token);
  29. $this->assertIdentical($result, $html);
  30. }
  31. public function test_generateFromToken_text()
  32. {
  33. $this->assertGenerateFromToken(
  34. new HTMLPurifier_Token_Text('Foobar.<>'),
  35. 'Foobar.&lt;&gt;'
  36. );
  37. }
  38. public function test_generateFromToken_startWithAttr()
  39. {
  40. $this->assertGenerateFromToken(
  41. new HTMLPurifier_Token_Start('a',
  42. array('href' => 'dyn?a=foo&b=bar')
  43. ),
  44. '<a href="dyn?a=foo&amp;b=bar">'
  45. );
  46. }
  47. public function test_generateFromToken_end()
  48. {
  49. $this->assertGenerateFromToken(
  50. new HTMLPurifier_Token_End('b'),
  51. '</b>'
  52. );
  53. }
  54. public function test_generateFromToken_emptyWithAttr()
  55. {
  56. $this->assertGenerateFromToken(
  57. new HTMLPurifier_Token_Empty('br',
  58. array('style' => 'font-family:"Courier New";')
  59. ),
  60. '<br style="font-family:&quot;Courier New&quot;;" />'
  61. );
  62. }
  63. public function test_generateFromToken_startNoAttr()
  64. {
  65. $this->assertGenerateFromToken(
  66. new HTMLPurifier_Token_Start('asdf'),
  67. '<asdf>'
  68. );
  69. }
  70. public function test_generateFromToken_emptyNoAttr()
  71. {
  72. $this->assertGenerateFromToken(
  73. new HTMLPurifier_Token_Empty('br'),
  74. '<br />'
  75. );
  76. }
  77. public function test_generateFromToken_error()
  78. {
  79. $this->expectError('Cannot generate HTML from non-HTMLPurifier_Token object');
  80. $this->assertGenerateFromToken( null, '' );
  81. }
  82. public function test_generateFromToken_unicode()
  83. {
  84. $theta_char = $this->_entity_lookup->table['theta'];
  85. $this->assertGenerateFromToken(
  86. new HTMLPurifier_Token_Text($theta_char),
  87. $theta_char
  88. );
  89. }
  90. public function test_generateFromToken_backtick()
  91. {
  92. $this->assertGenerateFromToken(
  93. new HTMLPurifier_Token_Start('img', array('alt' => '`foo')),
  94. '<img alt="`foo ">'
  95. );
  96. }
  97. public function test_generateFromToken_backtickDisabled()
  98. {
  99. $this->config->set('Output.FixInnerHTML', false);
  100. $this->assertGenerateFromToken(
  101. new HTMLPurifier_Token_Start('img', array('alt' => '`')),
  102. '<img alt="`">'
  103. );
  104. }
  105. public function test_generateFromToken_backtickNoChange()
  106. {
  107. $this->assertGenerateFromToken(
  108. new HTMLPurifier_Token_Start('img', array('alt' => '`foo` bar')),
  109. '<img alt="`foo` bar">'
  110. );
  111. }
  112. public function assertGenerateAttributes($attr, $expect, $element = false)
  113. {
  114. $generator = $this->createGenerator();
  115. $result = $generator->generateAttributes($attr, $element);
  116. $this->assertIdentical($result, $expect);
  117. }
  118. public function test_generateAttributes_blank()
  119. {
  120. $this->assertGenerateAttributes(array(), '');
  121. }
  122. public function test_generateAttributes_basic()
  123. {
  124. $this->assertGenerateAttributes(
  125. array('href' => 'dyn?a=foo&b=bar'),
  126. 'href="dyn?a=foo&amp;b=bar"'
  127. );
  128. }
  129. public function test_generateAttributes_doubleQuote()
  130. {
  131. $this->assertGenerateAttributes(
  132. array('style' => 'font-family:"Courier New";'),
  133. 'style="font-family:&quot;Courier New&quot;;"'
  134. );
  135. }
  136. public function test_generateAttributes_singleQuote()
  137. {
  138. $this->assertGenerateAttributes(
  139. array('style' => 'font-family:\'Courier New\';'),
  140. 'style="font-family:\'Courier New\';"'
  141. );
  142. }
  143. public function test_generateAttributes_multiple()
  144. {
  145. $this->assertGenerateAttributes(
  146. array('src' => 'picture.jpg', 'alt' => 'Short & interesting'),
  147. 'src="picture.jpg" alt="Short &amp; interesting"'
  148. );
  149. }
  150. public function test_generateAttributes_specialChar()
  151. {
  152. $theta_char = $this->_entity_lookup->table['theta'];
  153. $this->assertGenerateAttributes(
  154. array('title' => 'Theta is ' . $theta_char),
  155. 'title="Theta is ' . $theta_char . '"'
  156. );
  157. }
  158. public function test_generateAttributes_minimized()
  159. {
  160. $this->config->set('HTML.Doctype', 'HTML 4.01 Transitional');
  161. $this->assertGenerateAttributes(
  162. array('compact' => 'compact'), 'compact', 'menu'
  163. );
  164. }
  165. public function test_generateFromTokens()
  166. {
  167. $this->assertGeneration(
  168. array(
  169. new HTMLPurifier_Token_Start('b'),
  170. new HTMLPurifier_Token_Text('Foobar!'),
  171. new HTMLPurifier_Token_End('b')
  172. ),
  173. '<b>Foobar!</b>'
  174. );
  175. }
  176. protected function assertGeneration($tokens, $expect)
  177. {
  178. $generator = new HTMLPurifier_Generator($this->config, $this->context);
  179. $result = $generator->generateFromTokens($tokens);
  180. $this->assertIdentical($expect, $result);
  181. }
  182. public function test_generateFromTokens_Scripting()
  183. {
  184. $this->assertGeneration(
  185. array(
  186. new HTMLPurifier_Token_Start('script'),
  187. new HTMLPurifier_Token_Text('alert(3 < 5);'),
  188. new HTMLPurifier_Token_End('script')
  189. ),
  190. "<script><!--//--><![CDATA[//><!--\nalert(3 < 5);\n//--><!]]></script>"
  191. );
  192. }
  193. public function test_generateFromTokens_Scripting_missingCloseTag()
  194. {
  195. $this->assertGeneration(
  196. array(
  197. new HTMLPurifier_Token_Start('script'),
  198. new HTMLPurifier_Token_Text('alert(3 < 5);'),
  199. ),
  200. "<script>alert(3 &lt; 5);"
  201. );
  202. }
  203. public function test_generateFromTokens_Scripting_doubleBlock()
  204. {
  205. $this->assertGeneration(
  206. array(
  207. new HTMLPurifier_Token_Start('script'),
  208. new HTMLPurifier_Token_Text('alert(3 < 5);'),
  209. new HTMLPurifier_Token_Text('foo();'),
  210. new HTMLPurifier_Token_End('script')
  211. ),
  212. "<script>alert(3 &lt; 5);foo();</script>"
  213. );
  214. }
  215. public function test_generateFromTokens_Scripting_disableWrapper()
  216. {
  217. $this->config->set('Output.CommentScriptContents', false);
  218. $this->assertGeneration(
  219. array(
  220. new HTMLPurifier_Token_Start('script'),
  221. new HTMLPurifier_Token_Text('alert(3 < 5);'),
  222. new HTMLPurifier_Token_End('script')
  223. ),
  224. "<script>alert(3 &lt; 5);</script>"
  225. );
  226. }
  227. public function test_generateFromTokens_XHTMLoff()
  228. {
  229. $this->config->set('HTML.XHTML', false);
  230. // omit trailing slash
  231. $this->assertGeneration(
  232. array( new HTMLPurifier_Token_Empty('br') ),
  233. '<br>'
  234. );
  235. // there should be a test for attribute minimization, but it is
  236. // impossible for something like that to happen due to our current
  237. // definitions! fix it later
  238. // namespaced attributes must be dropped
  239. $this->assertGeneration(
  240. array( new HTMLPurifier_Token_Start('p', array('xml:lang'=>'fr')) ),
  241. '<p>'
  242. );
  243. }
  244. public function test_generateFromTokens_TidyFormat()
  245. {
  246. // abort test if tidy isn't loaded
  247. if (!extension_loaded('tidy')) return;
  248. // just don't test; Tidy is exploding on me.
  249. return;
  250. $this->config->set('Core.TidyFormat', true);
  251. $this->config->set('Output.Newline', "\n");
  252. // nice wrapping please
  253. $this->assertGeneration(
  254. array(
  255. new HTMLPurifier_Token_Start('div'),
  256. new HTMLPurifier_Token_Text('Text'),
  257. new HTMLPurifier_Token_End('div')
  258. ),
  259. "<div>\n Text\n</div>\n"
  260. );
  261. }
  262. public function test_generateFromTokens_sortAttr()
  263. {
  264. $this->config->set('Output.SortAttr', true);
  265. $this->assertGeneration(
  266. array( new HTMLPurifier_Token_Start('p', array('b'=>'c', 'a'=>'d')) ),
  267. '<p a="d" b="c">'
  268. );
  269. }
  270. }
  271. // vim: et sw=4 sts=4