sanitizer_test.go 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package sanitizer // import "miniflux.app/v2/internal/reader/sanitizer"
  4. import (
  5. "os"
  6. "strings"
  7. "testing"
  8. "golang.org/x/net/html"
  9. "miniflux.app/v2/internal/config"
  10. )
  11. func BenchmarkSanitize(b *testing.B) {
  12. var testCases = map[string][]string{
  13. "miniflux_github.html": {"https://github.com/miniflux/v2", ""},
  14. "miniflux_wikipedia.html": {"https://fr.wikipedia.org/wiki/Miniflux", ""},
  15. }
  16. for filename := range testCases {
  17. data, err := os.ReadFile("testdata/" + filename)
  18. if err != nil {
  19. b.Fatalf(`Unable to read file %q: %v`, filename, err)
  20. }
  21. testCases[filename][1] = string(data)
  22. }
  23. for b.Loop() {
  24. for _, v := range testCases {
  25. SanitizeHTMLWithDefaultOptions(v[0], v[1])
  26. }
  27. }
  28. }
  29. func FuzzSanitizer(f *testing.F) {
  30. f.Fuzz(func(t *testing.T, orig string) {
  31. tok := html.NewTokenizer(strings.NewReader(orig))
  32. i := 0
  33. for tok.Next() != html.ErrorToken {
  34. i++
  35. }
  36. out := SanitizeHTMLWithDefaultOptions("", orig)
  37. tok = html.NewTokenizer(strings.NewReader(out))
  38. j := 0
  39. for tok.Next() != html.ErrorToken {
  40. j++
  41. }
  42. if j > i {
  43. t.Errorf("Got more html tokens in the sanitized html.")
  44. }
  45. })
  46. }
  47. func TestValidInput(t *testing.T) {
  48. input := `<p>This is a <strong>text</strong> with an image: <img src="http://example.org/" alt="Test" loading="lazy">.</p>`
  49. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  50. if input != output {
  51. t.Errorf(`Wrong output: "%s" != "%s"`, input, output)
  52. }
  53. }
  54. func TestImgWithWidthAndHeightAttribute(t *testing.T) {
  55. input := `<img src="https://example.org/image.png" width="10" height="20">`
  56. expected := `<img src="https://example.org/image.png" width="10" height="20" loading="lazy">`
  57. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  58. if output != expected {
  59. t.Errorf(`Wrong output: %s`, output)
  60. }
  61. }
  62. func TestImgWithWidthAttributeLargerThanMinifluxLayout(t *testing.T) {
  63. input := `<img src="https://example.org/image.png" width="1200" height="675">`
  64. expected := `<img src="https://example.org/image.png" loading="lazy">`
  65. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  66. if output != expected {
  67. t.Errorf(`Wrong output: %s`, output)
  68. }
  69. }
  70. func TestImgWithIncorrectWidthAndHeightAttribute(t *testing.T) {
  71. input := `<img src="https://example.org/image.png" width="10px" height="20px">`
  72. expected := `<img src="https://example.org/image.png" loading="lazy">`
  73. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  74. if output != expected {
  75. t.Errorf(`Wrong output: %s`, output)
  76. }
  77. }
  78. func TestImgWithIncorrectWidthAttribute(t *testing.T) {
  79. input := `<img src="https://example.org/image.png" width="10px" height="20">`
  80. expected := `<img src="https://example.org/image.png" height="20" loading="lazy">`
  81. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  82. if output != expected {
  83. t.Errorf(`Wrong output: %s`, output)
  84. }
  85. }
  86. func TestImgWithEmptyWidthAndHeightAttribute(t *testing.T) {
  87. input := `<img src="https://example.org/image.png" width="" height="">`
  88. expected := `<img src="https://example.org/image.png" loading="lazy">`
  89. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  90. if output != expected {
  91. t.Errorf(`Wrong output: %s`, output)
  92. }
  93. }
  94. func TestImgWithIncorrectHeightAttribute(t *testing.T) {
  95. input := `<img src="https://example.org/image.png" width="10" height="20px">`
  96. expected := `<img src="https://example.org/image.png" width="10" loading="lazy">`
  97. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  98. if output != expected {
  99. t.Errorf(`Wrong output: %s`, output)
  100. }
  101. }
  102. func TestImgWithNegativeWidthAttribute(t *testing.T) {
  103. input := `<img src="https://example.org/image.png" width="-10" height="20">`
  104. expected := `<img src="https://example.org/image.png" height="20" loading="lazy">`
  105. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  106. if output != expected {
  107. t.Errorf(`Wrong output: %s`, output)
  108. }
  109. }
  110. func TestImgWithNegativeHeightAttribute(t *testing.T) {
  111. input := `<img src="https://example.org/image.png" width="10" height="-20">`
  112. expected := `<img src="https://example.org/image.png" width="10" loading="lazy">`
  113. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  114. if output != expected {
  115. t.Errorf(`Wrong output: %s`, output)
  116. }
  117. }
  118. func TestImgWithTextDataURL(t *testing.T) {
  119. input := `<img src="data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==" alt="Example">`
  120. expected := ``
  121. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  122. if output != expected {
  123. t.Errorf(`Wrong output: %s`, output)
  124. }
  125. }
  126. func TestImgWithDataURL(t *testing.T) {
  127. input := `<img src="data:image/gif;base64,test" alt="Example">`
  128. expected := `<img src="data:image/gif;base64,test" alt="Example" loading="lazy">`
  129. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  130. if output != expected {
  131. t.Errorf(`Wrong output: %s`, output)
  132. }
  133. }
  134. func TestImgWithSrcsetAttribute(t *testing.T) {
  135. input := `<img srcset="example-320w.jpg, example-480w.jpg 1.5x, example-640w.jpg 2x, example-640w.jpg 640w" src="example-640w.jpg" alt="Example">`
  136. expected := `<img srcset="http://example.org/example-320w.jpg, http://example.org/example-480w.jpg 1.5x, http://example.org/example-640w.jpg 2x, http://example.org/example-640w.jpg 640w" src="http://example.org/example-640w.jpg" alt="Example" loading="lazy">`
  137. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  138. if output != expected {
  139. t.Errorf(`Wrong output: %s`, output)
  140. }
  141. }
  142. func TestImgWithSrcsetAndNoSrcAttribute(t *testing.T) {
  143. input := `<img srcset="example-320w.jpg, example-480w.jpg 1.5x, example-640w.jpg 2x, example-640w.jpg 640w" alt="Example">`
  144. expected := `<img srcset="http://example.org/example-320w.jpg, http://example.org/example-480w.jpg 1.5x, http://example.org/example-640w.jpg 2x, http://example.org/example-640w.jpg 640w" alt="Example" loading="lazy">`
  145. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  146. if output != expected {
  147. t.Errorf(`Wrong output: %s`, output)
  148. }
  149. }
  150. func TestImgWithFetchPriorityAttribute(t *testing.T) {
  151. cases := []struct {
  152. input string
  153. expected string
  154. }{
  155. {
  156. `<img src="https://example.org/image.png" fetchpriority="high">`,
  157. `<img src="https://example.org/image.png" fetchpriority="high" loading="lazy">`,
  158. },
  159. {
  160. `<img src="https://example.org/image.png" fetchpriority="low">`,
  161. `<img src="https://example.org/image.png" fetchpriority="low" loading="lazy">`,
  162. },
  163. {
  164. `<img src="https://example.org/image.png" fetchpriority="auto">`,
  165. `<img src="https://example.org/image.png" fetchpriority="auto" loading="lazy">`,
  166. },
  167. }
  168. for _, tc := range cases {
  169. output := SanitizeHTMLWithDefaultOptions("http://example.org/", tc.input)
  170. if output != tc.expected {
  171. t.Errorf(`Wrong output for input %q: expected %q, got %q`, tc.input, tc.expected, output)
  172. }
  173. }
  174. }
  175. func TestImgWithInvalidFetchPriorityAttribute(t *testing.T) {
  176. input := `<img src="https://example.org/image.png" fetchpriority="invalid">`
  177. expected := `<img src="https://example.org/image.png" loading="lazy">`
  178. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  179. if output != expected {
  180. t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
  181. }
  182. }
  183. func TestNonImgWithFetchPriorityAttribute(t *testing.T) {
  184. input := `<p fetchpriority="high">Text</p>`
  185. expected := `<p>Text</p>`
  186. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  187. if output != expected {
  188. t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
  189. }
  190. }
  191. func TestImgWithDecodingAttribute(t *testing.T) {
  192. cases := []struct {
  193. input string
  194. expected string
  195. }{
  196. {
  197. `<img src="https://example.org/image.png" decoding="sync">`,
  198. `<img src="https://example.org/image.png" decoding="sync" loading="lazy">`,
  199. },
  200. {
  201. `<img src="https://example.org/image.png" decoding="async">`,
  202. `<img src="https://example.org/image.png" decoding="async" loading="lazy">`,
  203. },
  204. {
  205. `<img src="https://example.org/image.png" decoding="auto">`,
  206. `<img src="https://example.org/image.png" decoding="auto" loading="lazy">`,
  207. },
  208. }
  209. for _, tc := range cases {
  210. output := SanitizeHTMLWithDefaultOptions("http://example.org/", tc.input)
  211. if output != tc.expected {
  212. t.Errorf(`Wrong output for input %q: expected %q, got %q`, tc.input, tc.expected, output)
  213. }
  214. }
  215. }
  216. func TestImgWithInvalidDecodingAttribute(t *testing.T) {
  217. input := `<img src="https://example.org/image.png" decoding="invalid">`
  218. expected := `<img src="https://example.org/image.png" loading="lazy">`
  219. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  220. if output != expected {
  221. t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
  222. }
  223. }
  224. func TestNonImgWithDecodingAttribute(t *testing.T) {
  225. input := `<p decoding="async">Text</p>`
  226. expected := `<p>Text</p>`
  227. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  228. if output != expected {
  229. t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
  230. }
  231. }
  232. func TestSourceWithSrcsetAndMedia(t *testing.T) {
  233. input := `<picture><source media="(min-width: 800px)" srcset="elva-800w.jpg"></picture>`
  234. expected := `<picture><source media="(min-width: 800px)" srcset="http://example.org/elva-800w.jpg"></picture>`
  235. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  236. if output != expected {
  237. t.Errorf(`Wrong output: %s`, output)
  238. }
  239. }
  240. func TestMediumImgWithSrcset(t *testing.T) {
  241. input := `<img alt="Image for post" class="t u v ef aj" src="https://miro.medium.com/max/5460/1*aJ9JibWDqO81qMfNtqgqrw.jpeg" srcset="https://miro.medium.com/max/552/1*aJ9JibWDqO81qMfNtqgqrw.jpeg 276w, https://miro.medium.com/max/1000/1*aJ9JibWDqO81qMfNtqgqrw.jpeg 500w" sizes="500px" width="2730" height="3407">`
  242. expected := `<img alt="Image for post" src="https://miro.medium.com/max/5460/1*aJ9JibWDqO81qMfNtqgqrw.jpeg" srcset="https://miro.medium.com/max/552/1*aJ9JibWDqO81qMfNtqgqrw.jpeg 276w, https://miro.medium.com/max/1000/1*aJ9JibWDqO81qMfNtqgqrw.jpeg 500w" sizes="500px" loading="lazy">`
  243. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  244. if output != expected {
  245. t.Errorf(`Wrong output: %s`, output)
  246. }
  247. }
  248. func TestSelfClosingTags(t *testing.T) {
  249. input := `<p>This <br> is a <strong>text</strong> <br/>with an image: <img src="http://example.org/" alt="Test" loading="lazy"/>.</p>`
  250. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  251. if input != output {
  252. t.Errorf(`Wrong output: "%s" != "%s"`, input, output)
  253. }
  254. }
  255. func TestTable(t *testing.T) {
  256. input := `<table><tr><th>A</th><th colspan="2">B</th></tr><tr><td>C</td><td>D</td><td>E</td></tr></table>`
  257. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  258. if input != output {
  259. t.Errorf(`Wrong output: "%s" != "%s"`, input, output)
  260. }
  261. }
  262. func TestRelativeURL(t *testing.T) {
  263. input := `This <a href="/test.html">link is relative</a> and this image: <img src="../folder/image.png"/>`
  264. expected := `This <a href="http://example.org/test.html" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">link is relative</a> and this image: <img src="http://example.org/folder/image.png" loading="lazy"/>`
  265. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  266. if expected != output {
  267. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  268. }
  269. }
  270. func TestProtocolRelativeURL(t *testing.T) {
  271. input := `This <a href="//static.example.org/index.html">link is relative</a>.`
  272. expected := `This <a href="https://static.example.org/index.html" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">link is relative</a>.`
  273. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  274. if expected != output {
  275. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  276. }
  277. }
  278. func TestInvalidTag(t *testing.T) {
  279. input := `<p>My invalid <z>tag</z>.</p>`
  280. expected := `<p>My invalid tag.</p>`
  281. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  282. if expected != output {
  283. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  284. }
  285. }
  286. func TestVideoTag(t *testing.T) {
  287. input := `<p>My valid <video src="videofile.webm" autoplay poster="posterimage.jpg">fallback</video>.</p>`
  288. expected := `<p>My valid <video src="http://example.org/videofile.webm" poster="http://example.org/posterimage.jpg" controls>fallback</video>.</p>`
  289. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  290. if expected != output {
  291. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  292. }
  293. }
  294. func TestAudioAndSourceTag(t *testing.T) {
  295. input := `<p>My music <audio controls="controls"><source src="foo.wav" type="audio/wav"></audio>.</p>`
  296. expected := `<p>My music <audio controls><source src="http://example.org/foo.wav" type="audio/wav"></audio>.</p>`
  297. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  298. if expected != output {
  299. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  300. }
  301. }
  302. func TestUnknownTag(t *testing.T) {
  303. input := `<p>My invalid <unknown>tag</unknown>.</p>`
  304. expected := `<p>My invalid tag.</p>`
  305. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  306. if expected != output {
  307. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  308. }
  309. }
  310. func TestInvalidNestedTag(t *testing.T) {
  311. input := `<p>My invalid <z>tag with some <em>valid</em> tag</z>.</p>`
  312. expected := `<p>My invalid tag with some <em>valid</em> tag.</p>`
  313. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  314. if expected != output {
  315. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  316. }
  317. }
  318. func TestInvalidIFrame(t *testing.T) {
  319. config.Opts = config.NewOptions()
  320. input := `<iframe src="http://example.org/"></iframe>`
  321. expected := ``
  322. output := SanitizeHTMLWithDefaultOptions("http://example.com/", input)
  323. if expected != output {
  324. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  325. }
  326. }
  327. func TestSameDomainIFrame(t *testing.T) {
  328. config.Opts = config.NewOptions()
  329. input := `<iframe src="http://example.com/test"></iframe>`
  330. expected := ``
  331. output := SanitizeHTMLWithDefaultOptions("http://example.com/", input)
  332. if expected != output {
  333. t.Errorf(`Wrong output: %q != %q`, expected, output)
  334. }
  335. }
  336. func TestInvidiousIFrame(t *testing.T) {
  337. config.Opts = config.NewOptions()
  338. input := `<iframe src="https://yewtu.be/watch?v=video_id"></iframe>`
  339. expected := `<iframe src="https://yewtu.be/watch?v=video_id" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  340. output := SanitizeHTMLWithDefaultOptions("http://example.com/", input)
  341. if expected != output {
  342. t.Errorf(`Wrong output: %q != %q`, expected, output)
  343. }
  344. }
  345. func TestCustomYoutubeEmbedURL(t *testing.T) {
  346. os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://www.invidious.custom/embed/")
  347. defer os.Clearenv()
  348. var err error
  349. if config.Opts, err = config.NewParser().ParseEnvironmentVariables(); err != nil {
  350. t.Fatalf(`Parsing failure: %v`, err)
  351. }
  352. input := `<iframe src="https://www.invidious.custom/embed/1234"></iframe>`
  353. expected := `<iframe src="https://www.invidious.custom/embed/1234" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  354. output := SanitizeHTMLWithDefaultOptions("http://example.com/", input)
  355. if expected != output {
  356. t.Errorf(`Wrong output: %q != %q`, expected, output)
  357. }
  358. }
  359. func TestIFrameWithChildElements(t *testing.T) {
  360. config.Opts = config.NewOptions()
  361. input := `<iframe src="https://www.youtube.com/"><p>test</p></iframe>`
  362. expected := `<iframe src="https://www.youtube.com/" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  363. output := SanitizeHTMLWithDefaultOptions("http://example.com/", input)
  364. if expected != output {
  365. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  366. }
  367. }
  368. func TestLinkWithTarget(t *testing.T) {
  369. input := `<p>This link is <a href="http://example.org/index.html">an anchor</a></p>`
  370. expected := `<p>This link is <a href="http://example.org/index.html" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">an anchor</a></p>`
  371. output := SanitizeHTML("http://example.org/", input, &SanitizerOptions{OpenLinksInNewTab: true})
  372. if expected != output {
  373. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  374. }
  375. }
  376. func TestLinkWithNoTarget(t *testing.T) {
  377. input := `<p>This link is <a href="http://example.org/index.html">an anchor</a></p>`
  378. expected := `<p>This link is <a href="http://example.org/index.html" rel="noopener noreferrer" referrerpolicy="no-referrer">an anchor</a></p>`
  379. output := SanitizeHTML("http://example.org/", input, &SanitizerOptions{OpenLinksInNewTab: false})
  380. if expected != output {
  381. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  382. }
  383. }
  384. func TestAnchorLink(t *testing.T) {
  385. input := `<p>This link is <a href="#some-anchor">an anchor</a></p>`
  386. expected := `<p>This link is <a href="#some-anchor">an anchor</a></p>`
  387. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  388. if expected != output {
  389. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  390. }
  391. }
  392. func TestInvalidURLScheme(t *testing.T) {
  393. input := `<p>This link is <a src="file:///etc/passwd">not valid</a></p>`
  394. expected := `<p>This link is not valid</p>`
  395. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  396. if expected != output {
  397. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  398. }
  399. }
  400. func TestAPTURIScheme(t *testing.T) {
  401. input := `<p>This link is <a href="apt:some-package?channel=test">valid</a></p>`
  402. expected := `<p>This link is <a href="apt:some-package?channel=test" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  403. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  404. if expected != output {
  405. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  406. }
  407. }
  408. func TestBitcoinURIScheme(t *testing.T) {
  409. input := `<p>This link is <a href="bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W">valid</a></p>`
  410. expected := `<p>This link is <a href="bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  411. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  412. if expected != output {
  413. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  414. }
  415. }
  416. func TestCallToURIScheme(t *testing.T) {
  417. input := `<p>This link is <a href="callto:12345679">valid</a></p>`
  418. expected := `<p>This link is <a href="callto:12345679" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  419. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  420. if expected != output {
  421. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  422. }
  423. }
  424. func TestFeedURIScheme(t *testing.T) {
  425. input := `<p>This link is <a href="feed://example.com/rss.xml">valid</a></p>`
  426. expected := `<p>This link is <a href="feed://example.com/rss.xml" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  427. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  428. if expected != output {
  429. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  430. }
  431. input = `<p>This link is <a href="feed:https://example.com/rss.xml">valid</a></p>`
  432. expected = `<p>This link is <a href="feed:https://example.com/rss.xml" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  433. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  434. if expected != output {
  435. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  436. }
  437. }
  438. func TestGeoURIScheme(t *testing.T) {
  439. input := `<p>This link is <a href="geo:13.4125,103.8667">valid</a></p>`
  440. expected := `<p>This link is <a href="geo:13.4125,103.8667" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  441. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  442. if expected != output {
  443. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  444. }
  445. }
  446. func TestItunesURIScheme(t *testing.T) {
  447. input := `<p>This link is <a href="itms://itunes.com/apps/my-app-name">valid</a></p>`
  448. expected := `<p>This link is <a href="itms://itunes.com/apps/my-app-name" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  449. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  450. if expected != output {
  451. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  452. }
  453. input = `<p>This link is <a href="itms-apps://itunes.com/apps/my-app-name">valid</a></p>`
  454. expected = `<p>This link is <a href="itms-apps://itunes.com/apps/my-app-name" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  455. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  456. if expected != output {
  457. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  458. }
  459. }
  460. func TestMagnetURIScheme(t *testing.T) {
  461. input := `<p>This link is <a href="magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&amp;xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7">valid</a></p>`
  462. expected := `<p>This link is <a href="magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&amp;xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  463. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  464. if expected != output {
  465. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  466. }
  467. }
  468. func TestMailtoURIScheme(t *testing.T) {
  469. input := `<p>This link is <a href="mailto:jsmith@example.com?subject=A%20Test&amp;body=My%20idea%20is%3A%20%0A">valid</a></p>`
  470. expected := `<p>This link is <a href="mailto:jsmith@example.com?subject=A%20Test&amp;body=My%20idea%20is%3A%20%0A" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  471. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  472. if expected != output {
  473. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  474. }
  475. }
  476. func TestNewsURIScheme(t *testing.T) {
  477. input := `<p>This link is <a href="news://news.server.example/*">valid</a></p>`
  478. expected := `<p>This link is <a href="news://news.server.example/*" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  479. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  480. if expected != output {
  481. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  482. }
  483. input = `<p>This link is <a href="news:example.group.this">valid</a></p>`
  484. expected = `<p>This link is <a href="news:example.group.this" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  485. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  486. if expected != output {
  487. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  488. }
  489. input = `<p>This link is <a href="nntp://news.server.example/example.group.this">valid</a></p>`
  490. expected = `<p>This link is <a href="nntp://news.server.example/example.group.this" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  491. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  492. if expected != output {
  493. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  494. }
  495. }
  496. func TestRTMPURIScheme(t *testing.T) {
  497. input := `<p>This link is <a href="rtmp://mycompany.com/vod/mp4:mycoolvideo.mov">valid</a></p>`
  498. expected := `<p>This link is <a href="rtmp://mycompany.com/vod/mp4:mycoolvideo.mov" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  499. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  500. if expected != output {
  501. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  502. }
  503. }
  504. func TestSIPURIScheme(t *testing.T) {
  505. input := `<p>This link is <a href="sip:+1-212-555-1212:1234@gateway.com;user=phone">valid</a></p>`
  506. expected := `<p>This link is <a href="sip:+1-212-555-1212:1234@gateway.com;user=phone" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  507. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  508. if expected != output {
  509. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  510. }
  511. input = `<p>This link is <a href="sips:alice@atlanta.com?subject=project%20x&amp;priority=urgent">valid</a></p>`
  512. expected = `<p>This link is <a href="sips:alice@atlanta.com?subject=project%20x&amp;priority=urgent" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  513. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  514. if expected != output {
  515. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  516. }
  517. }
  518. func TestSkypeURIScheme(t *testing.T) {
  519. input := `<p>This link is <a href="skype:echo123?call">valid</a></p>`
  520. expected := `<p>This link is <a href="skype:echo123?call" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  521. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  522. if expected != output {
  523. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  524. }
  525. }
  526. func TestSpotifyURIScheme(t *testing.T) {
  527. input := `<p>This link is <a href="spotify:track:2jCnn1QPQ3E8ExtLe6INsx">valid</a></p>`
  528. expected := `<p>This link is <a href="spotify:track:2jCnn1QPQ3E8ExtLe6INsx" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  529. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  530. if expected != output {
  531. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  532. }
  533. }
  534. func TestSteamURIScheme(t *testing.T) {
  535. input := `<p>This link is <a href="steam://settings/account">valid</a></p>`
  536. expected := `<p>This link is <a href="steam://settings/account" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  537. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  538. if expected != output {
  539. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  540. }
  541. }
  542. func TestSubversionURIScheme(t *testing.T) {
  543. input := `<p>This link is <a href="svn://example.org">valid</a></p>`
  544. expected := `<p>This link is <a href="svn://example.org" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  545. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  546. if expected != output {
  547. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  548. }
  549. input = `<p>This link is <a href="svn+ssh://example.org">valid</a></p>`
  550. expected = `<p>This link is <a href="svn+ssh://example.org" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  551. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  552. if expected != output {
  553. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  554. }
  555. }
  556. func TestTelURIScheme(t *testing.T) {
  557. input := `<p>This link is <a href="tel:+1-201-555-0123">valid</a></p>`
  558. expected := `<p>This link is <a href="tel:+1-201-555-0123" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  559. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  560. if expected != output {
  561. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  562. }
  563. }
  564. func TestWebcalURIScheme(t *testing.T) {
  565. input := `<p>This link is <a href="webcal://example.com/calendar.ics">valid</a></p>`
  566. expected := `<p>This link is <a href="webcal://example.com/calendar.ics" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  567. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  568. if expected != output {
  569. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  570. }
  571. }
  572. func TestXMPPURIScheme(t *testing.T) {
  573. input := `<p>This link is <a href="xmpp:user@host?subscribe&amp;type=subscribed">valid</a></p>`
  574. expected := `<p>This link is <a href="xmpp:user@host?subscribe&amp;type=subscribed" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">valid</a></p>`
  575. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  576. if expected != output {
  577. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  578. }
  579. }
  580. func TestBlacklistedLink(t *testing.T) {
  581. input := `<p>This image is not valid <img src="https://stats.wordpress.com/some-tracker"></p>`
  582. expected := `<p>This image is not valid </p>`
  583. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  584. if expected != output {
  585. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  586. }
  587. }
  588. func TestLinkWithTrackers(t *testing.T) {
  589. input := `<p>This link has trackers <a href="https://example.com/page?utm_source=newsletter">Test</a></p>`
  590. expected := `<p>This link has trackers <a href="https://example.com/page" rel="noopener noreferrer" referrerpolicy="no-referrer" target="_blank">Test</a></p>`
  591. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  592. if expected != output {
  593. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  594. }
  595. }
  596. func TestImageSrcWithTrackers(t *testing.T) {
  597. input := `<p>This image has trackers <img src="https://example.org/?id=123&utm_source=newsletter&utm_medium=email&fbclid=abc123"></p>`
  598. expected := `<p>This image has trackers <img src="https://example.org/?id=123" loading="lazy"></p>`
  599. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  600. if expected != output {
  601. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  602. }
  603. }
  604. func Test1x1PixelTracker(t *testing.T) {
  605. input := `<p><img src="https://tracker1.example.org/" height="1" width="1"> and <img src="https://tracker2.example.org/" height="1" width="1"/></p>`
  606. expected := `<p> and </p>`
  607. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  608. if expected != output {
  609. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  610. }
  611. }
  612. func Test0x0PixelTracker(t *testing.T) {
  613. input := `<p><img src="https://tracker1.example.org/" height="0" width="0"> and <img src="https://tracker2.example.org/" height="0" width="0"/></p>`
  614. expected := `<p> and </p>`
  615. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  616. if expected != output {
  617. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  618. }
  619. }
  620. func TestXmlEntities(t *testing.T) {
  621. input := `<pre>echo "test" &gt; /etc/hosts</pre>`
  622. expected := `<pre>echo &#34;test&#34; &gt; /etc/hosts</pre>`
  623. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  624. if expected != output {
  625. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  626. }
  627. }
  628. func TestEspaceAttributes(t *testing.T) {
  629. input := `<td rowspan="<b>test</b>">test</td>`
  630. expected := `<td rowspan="&lt;b&gt;test&lt;/b&gt;">test</td>`
  631. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  632. if expected != output {
  633. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  634. }
  635. }
  636. func TestReplaceYoutubeURL(t *testing.T) {
  637. input := `<iframe src="http://www.youtube.com/embed/test123?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent"></iframe>`
  638. expected := `<iframe src="https://www.youtube-nocookie.com/embed/test123?version=3&amp;rel=1&amp;fs=1&amp;autohide=2&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  639. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  640. if expected != output {
  641. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  642. }
  643. }
  644. func TestReplaceSecureYoutubeURL(t *testing.T) {
  645. input := `<iframe src="https://www.youtube.com/embed/test123"></iframe>`
  646. expected := `<iframe src="https://www.youtube-nocookie.com/embed/test123" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  647. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  648. if expected != output {
  649. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  650. }
  651. }
  652. func TestReplaceSecureYoutubeURLWithParameters(t *testing.T) {
  653. input := `<iframe src="https://www.youtube.com/embed/test123?rel=0&amp;controls=0"></iframe>`
  654. expected := `<iframe src="https://www.youtube-nocookie.com/embed/test123?rel=0&amp;controls=0" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  655. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  656. if expected != output {
  657. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  658. }
  659. }
  660. func TestReplaceYoutubeURLAlreadyReplaced(t *testing.T) {
  661. input := `<iframe src="https://www.youtube-nocookie.com/embed/test123?rel=0&amp;controls=0" sandbox="allow-scripts allow-same-origin"></iframe>`
  662. expected := `<iframe src="https://www.youtube-nocookie.com/embed/test123?rel=0&amp;controls=0" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  663. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  664. if expected != output {
  665. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  666. }
  667. }
  668. func TestReplaceProtocolRelativeYoutubeURL(t *testing.T) {
  669. input := `<iframe src="//www.youtube.com/embed/Bf2W84jrGqs" width="560" height="314" allowfullscreen="allowfullscreen"></iframe>`
  670. expected := `<iframe src="https://www.youtube-nocookie.com/embed/Bf2W84jrGqs" width="560" height="314" allowfullscreen="allowfullscreen" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  671. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  672. if expected != output {
  673. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  674. }
  675. }
  676. func TestReplaceYoutubeURLWithCustomURL(t *testing.T) {
  677. defer os.Clearenv()
  678. os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://invidious.custom/embed/")
  679. var err error
  680. config.Opts, err = config.NewParser().ParseEnvironmentVariables()
  681. if err != nil {
  682. t.Fatalf(`Parsing failure: %v`, err)
  683. }
  684. input := `<iframe src="https://www.youtube.com/embed/test123?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent"></iframe>`
  685. expected := `<iframe src="https://invidious.custom/embed/test123?version=3&amp;rel=1&amp;fs=1&amp;autohide=2&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  686. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  687. if expected != output {
  688. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  689. }
  690. }
  691. func TestVimeoIframeRewriteWithQueryString(t *testing.T) {
  692. input := `<iframe src="https://player.vimeo.com/video/123456?title=0&amp;byline=0"></iframe>`
  693. expected := `<iframe src="https://player.vimeo.com/video/123456?title=0&amp;byline=0&amp;dnt=1" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  694. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  695. if expected != output {
  696. t.Errorf(`Wrong output: %q != %q`, expected, output)
  697. }
  698. }
  699. func TestVimeoIframeRewriteWithoutQueryString(t *testing.T) {
  700. input := `<iframe src="https://player.vimeo.com/video/123456"></iframe>`
  701. expected := `<iframe src="https://player.vimeo.com/video/123456?dnt=1" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" loading="lazy"></iframe>`
  702. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  703. if expected != output {
  704. t.Errorf(`Wrong output: %q != %q`, expected, output)
  705. }
  706. }
  707. func TestReplaceNoScript(t *testing.T) {
  708. input := `<p>Before paragraph.</p><noscript>Inside <code>noscript</code> tag with an image: <img src="http://example.org/" alt="Test" loading="lazy"></noscript><p>After paragraph.</p>`
  709. expected := `<p>Before paragraph.</p><p>After paragraph.</p>`
  710. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  711. if expected != output {
  712. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  713. }
  714. }
  715. func TestReplaceScript(t *testing.T) {
  716. input := `<p>Before paragraph.</p><script type="text/javascript">alert("1");</script><p>After paragraph.</p>`
  717. expected := `<p>Before paragraph.</p><p>After paragraph.</p>`
  718. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  719. if expected != output {
  720. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  721. }
  722. }
  723. func TestReplaceStyle(t *testing.T) {
  724. input := `<p>Before paragraph.</p><style>body { background-color: #ff0000; }</style><p>After paragraph.</p>`
  725. expected := `<p>Before paragraph.</p><p>After paragraph.</p>`
  726. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  727. if expected != output {
  728. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  729. }
  730. }
  731. func TestHiddenParagraph(t *testing.T) {
  732. input := `<p>Before paragraph.</p><p hidden>This should <em>not</em> appear in the <strong>output</strong></p><p>After paragraph.</p>`
  733. expected := `<p>Before paragraph.</p><p>After paragraph.</p>`
  734. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  735. if expected != output {
  736. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  737. }
  738. }
  739. func TestAttributesAreStripped(t *testing.T) {
  740. input := `<p style="color: red;">Some text.<hr style="color: blue"/>Test.</p>`
  741. expected := `<p>Some text.<hr/>Test.</p>`
  742. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  743. if expected != output {
  744. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  745. }
  746. }
  747. func TestMathML(t *testing.T) {
  748. input := `<math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>x</mi><mn>2</mn></msup></math>`
  749. expected := `<math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>x</mi><mn>2</mn></msup></math>`
  750. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  751. if expected != output {
  752. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  753. }
  754. }
  755. func TestInvalidMathMLXMLNamespace(t *testing.T) {
  756. input := `<math xmlns="http://example.org"><msup><mi>x</mi><mn>2</mn></msup></math>`
  757. expected := `<math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>x</mi><mn>2</mn></msup></math>`
  758. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  759. if expected != output {
  760. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  761. }
  762. }
  763. func TestBlockedResourcesSubstrings(t *testing.T) {
  764. input := `<p>Before paragraph.</p><img src="http://stats.wordpress.com/something.php" alt="Blocked Resource"><p>After paragraph.</p>`
  765. expected := `<p>Before paragraph.</p><p>After paragraph.</p>`
  766. output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  767. if expected != output {
  768. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  769. }
  770. input = `<p>Before paragraph.</p><img src="http://twitter.com/share?text=This+is+google+a+search+engine&url=https%3A%2F%2Fwww.google.com" alt="Blocked Resource"><p>After paragraph.</p>`
  771. expected = `<p>Before paragraph.</p><p>After paragraph.</p>`
  772. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  773. if expected != output {
  774. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  775. }
  776. input = `<p>Before paragraph.</p><img src="http://www.facebook.com/sharer.php?u=https%3A%2F%2Fwww.google.com%[title]=This+Is%2C+Google+a+search+engine" alt="Blocked Resource"><p>After paragraph.</p>`
  777. expected = `<p>Before paragraph.</p><p>After paragraph.</p>`
  778. output = SanitizeHTMLWithDefaultOptions("http://example.org/", input)
  779. if expected != output {
  780. t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
  781. }
  782. }