arcgis-html-sanitizer.js 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108
  1. /*!
  2. * @esri/arcgis-html-sanitizer - v3.0.1 - Tue Nov 15 2022 09:46:54 GMT-0800 (Pacific Standard Time)
  3. * Copyright (c) 2022 - Environmental Systems Research Institute, Inc.
  4. * Apache-2.0
  5. *
  6. * js-xss
  7. * Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
  8. * http://ucdok.com
  9. * MIT License, see https://github.com/leizongmin/js-xss/blob/master/LICENSE for details
  10. */
  11. (function (global, factory) {
  12. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  13. typeof define === 'function' && define.amd ? define(factory) :
  14. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Sanitizer = factory());
  15. })(this, (function () { 'use strict';
  16. /**
  17. * Determine if the value is a plain object.
  18. * @param {*} value The value to check.
  19. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
  20. */
  21. var isPlainObject = function (value) {
  22. if (typeof value !== "object" || value === null) {
  23. return false;
  24. }
  25. if (Object.prototype.toString.call(value) !== "[object Object]") {
  26. return false;
  27. }
  28. var proto = Object.getPrototypeOf(value);
  29. if (proto === null) {
  30. return true;
  31. }
  32. while (Object.getPrototypeOf(proto) !== null) {
  33. proto = Object.getPrototypeOf(proto);
  34. }
  35. return Object.getPrototypeOf(value) === proto;
  36. };
  37. var lib$1 = {exports: {}};
  38. var _default$1 = {};
  39. var lib = {exports: {}};
  40. var _default = {};
  41. /**
  42. * cssfilter
  43. *
  44. * @author 老雷<leizongmin@gmail.com>
  45. */
  46. function getDefaultWhiteList$1 () {
  47. // 白名单值说明:
  48. // true: 允许该属性
  49. // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许
  50. // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许
  51. // 除上面列出的值外均表示不允许
  52. var whiteList = {};
  53. whiteList['align-content'] = false; // default: auto
  54. whiteList['align-items'] = false; // default: auto
  55. whiteList['align-self'] = false; // default: auto
  56. whiteList['alignment-adjust'] = false; // default: auto
  57. whiteList['alignment-baseline'] = false; // default: baseline
  58. whiteList['all'] = false; // default: depending on individual properties
  59. whiteList['anchor-point'] = false; // default: none
  60. whiteList['animation'] = false; // default: depending on individual properties
  61. whiteList['animation-delay'] = false; // default: 0
  62. whiteList['animation-direction'] = false; // default: normal
  63. whiteList['animation-duration'] = false; // default: 0
  64. whiteList['animation-fill-mode'] = false; // default: none
  65. whiteList['animation-iteration-count'] = false; // default: 1
  66. whiteList['animation-name'] = false; // default: none
  67. whiteList['animation-play-state'] = false; // default: running
  68. whiteList['animation-timing-function'] = false; // default: ease
  69. whiteList['azimuth'] = false; // default: center
  70. whiteList['backface-visibility'] = false; // default: visible
  71. whiteList['background'] = true; // default: depending on individual properties
  72. whiteList['background-attachment'] = true; // default: scroll
  73. whiteList['background-clip'] = true; // default: border-box
  74. whiteList['background-color'] = true; // default: transparent
  75. whiteList['background-image'] = true; // default: none
  76. whiteList['background-origin'] = true; // default: padding-box
  77. whiteList['background-position'] = true; // default: 0% 0%
  78. whiteList['background-repeat'] = true; // default: repeat
  79. whiteList['background-size'] = true; // default: auto
  80. whiteList['baseline-shift'] = false; // default: baseline
  81. whiteList['binding'] = false; // default: none
  82. whiteList['bleed'] = false; // default: 6pt
  83. whiteList['bookmark-label'] = false; // default: content()
  84. whiteList['bookmark-level'] = false; // default: none
  85. whiteList['bookmark-state'] = false; // default: open
  86. whiteList['border'] = true; // default: depending on individual properties
  87. whiteList['border-bottom'] = true; // default: depending on individual properties
  88. whiteList['border-bottom-color'] = true; // default: current color
  89. whiteList['border-bottom-left-radius'] = true; // default: 0
  90. whiteList['border-bottom-right-radius'] = true; // default: 0
  91. whiteList['border-bottom-style'] = true; // default: none
  92. whiteList['border-bottom-width'] = true; // default: medium
  93. whiteList['border-collapse'] = true; // default: separate
  94. whiteList['border-color'] = true; // default: depending on individual properties
  95. whiteList['border-image'] = true; // default: none
  96. whiteList['border-image-outset'] = true; // default: 0
  97. whiteList['border-image-repeat'] = true; // default: stretch
  98. whiteList['border-image-slice'] = true; // default: 100%
  99. whiteList['border-image-source'] = true; // default: none
  100. whiteList['border-image-width'] = true; // default: 1
  101. whiteList['border-left'] = true; // default: depending on individual properties
  102. whiteList['border-left-color'] = true; // default: current color
  103. whiteList['border-left-style'] = true; // default: none
  104. whiteList['border-left-width'] = true; // default: medium
  105. whiteList['border-radius'] = true; // default: 0
  106. whiteList['border-right'] = true; // default: depending on individual properties
  107. whiteList['border-right-color'] = true; // default: current color
  108. whiteList['border-right-style'] = true; // default: none
  109. whiteList['border-right-width'] = true; // default: medium
  110. whiteList['border-spacing'] = true; // default: 0
  111. whiteList['border-style'] = true; // default: depending on individual properties
  112. whiteList['border-top'] = true; // default: depending on individual properties
  113. whiteList['border-top-color'] = true; // default: current color
  114. whiteList['border-top-left-radius'] = true; // default: 0
  115. whiteList['border-top-right-radius'] = true; // default: 0
  116. whiteList['border-top-style'] = true; // default: none
  117. whiteList['border-top-width'] = true; // default: medium
  118. whiteList['border-width'] = true; // default: depending on individual properties
  119. whiteList['bottom'] = false; // default: auto
  120. whiteList['box-decoration-break'] = true; // default: slice
  121. whiteList['box-shadow'] = true; // default: none
  122. whiteList['box-sizing'] = true; // default: content-box
  123. whiteList['box-snap'] = true; // default: none
  124. whiteList['box-suppress'] = true; // default: show
  125. whiteList['break-after'] = true; // default: auto
  126. whiteList['break-before'] = true; // default: auto
  127. whiteList['break-inside'] = true; // default: auto
  128. whiteList['caption-side'] = false; // default: top
  129. whiteList['chains'] = false; // default: none
  130. whiteList['clear'] = true; // default: none
  131. whiteList['clip'] = false; // default: auto
  132. whiteList['clip-path'] = false; // default: none
  133. whiteList['clip-rule'] = false; // default: nonzero
  134. whiteList['color'] = true; // default: implementation dependent
  135. whiteList['color-interpolation-filters'] = true; // default: auto
  136. whiteList['column-count'] = false; // default: auto
  137. whiteList['column-fill'] = false; // default: balance
  138. whiteList['column-gap'] = false; // default: normal
  139. whiteList['column-rule'] = false; // default: depending on individual properties
  140. whiteList['column-rule-color'] = false; // default: current color
  141. whiteList['column-rule-style'] = false; // default: medium
  142. whiteList['column-rule-width'] = false; // default: medium
  143. whiteList['column-span'] = false; // default: none
  144. whiteList['column-width'] = false; // default: auto
  145. whiteList['columns'] = false; // default: depending on individual properties
  146. whiteList['contain'] = false; // default: none
  147. whiteList['content'] = false; // default: normal
  148. whiteList['counter-increment'] = false; // default: none
  149. whiteList['counter-reset'] = false; // default: none
  150. whiteList['counter-set'] = false; // default: none
  151. whiteList['crop'] = false; // default: auto
  152. whiteList['cue'] = false; // default: depending on individual properties
  153. whiteList['cue-after'] = false; // default: none
  154. whiteList['cue-before'] = false; // default: none
  155. whiteList['cursor'] = false; // default: auto
  156. whiteList['direction'] = false; // default: ltr
  157. whiteList['display'] = true; // default: depending on individual properties
  158. whiteList['display-inside'] = true; // default: auto
  159. whiteList['display-list'] = true; // default: none
  160. whiteList['display-outside'] = true; // default: inline-level
  161. whiteList['dominant-baseline'] = false; // default: auto
  162. whiteList['elevation'] = false; // default: level
  163. whiteList['empty-cells'] = false; // default: show
  164. whiteList['filter'] = false; // default: none
  165. whiteList['flex'] = false; // default: depending on individual properties
  166. whiteList['flex-basis'] = false; // default: auto
  167. whiteList['flex-direction'] = false; // default: row
  168. whiteList['flex-flow'] = false; // default: depending on individual properties
  169. whiteList['flex-grow'] = false; // default: 0
  170. whiteList['flex-shrink'] = false; // default: 1
  171. whiteList['flex-wrap'] = false; // default: nowrap
  172. whiteList['float'] = false; // default: none
  173. whiteList['float-offset'] = false; // default: 0 0
  174. whiteList['flood-color'] = false; // default: black
  175. whiteList['flood-opacity'] = false; // default: 1
  176. whiteList['flow-from'] = false; // default: none
  177. whiteList['flow-into'] = false; // default: none
  178. whiteList['font'] = true; // default: depending on individual properties
  179. whiteList['font-family'] = true; // default: implementation dependent
  180. whiteList['font-feature-settings'] = true; // default: normal
  181. whiteList['font-kerning'] = true; // default: auto
  182. whiteList['font-language-override'] = true; // default: normal
  183. whiteList['font-size'] = true; // default: medium
  184. whiteList['font-size-adjust'] = true; // default: none
  185. whiteList['font-stretch'] = true; // default: normal
  186. whiteList['font-style'] = true; // default: normal
  187. whiteList['font-synthesis'] = true; // default: weight style
  188. whiteList['font-variant'] = true; // default: normal
  189. whiteList['font-variant-alternates'] = true; // default: normal
  190. whiteList['font-variant-caps'] = true; // default: normal
  191. whiteList['font-variant-east-asian'] = true; // default: normal
  192. whiteList['font-variant-ligatures'] = true; // default: normal
  193. whiteList['font-variant-numeric'] = true; // default: normal
  194. whiteList['font-variant-position'] = true; // default: normal
  195. whiteList['font-weight'] = true; // default: normal
  196. whiteList['grid'] = false; // default: depending on individual properties
  197. whiteList['grid-area'] = false; // default: depending on individual properties
  198. whiteList['grid-auto-columns'] = false; // default: auto
  199. whiteList['grid-auto-flow'] = false; // default: none
  200. whiteList['grid-auto-rows'] = false; // default: auto
  201. whiteList['grid-column'] = false; // default: depending on individual properties
  202. whiteList['grid-column-end'] = false; // default: auto
  203. whiteList['grid-column-start'] = false; // default: auto
  204. whiteList['grid-row'] = false; // default: depending on individual properties
  205. whiteList['grid-row-end'] = false; // default: auto
  206. whiteList['grid-row-start'] = false; // default: auto
  207. whiteList['grid-template'] = false; // default: depending on individual properties
  208. whiteList['grid-template-areas'] = false; // default: none
  209. whiteList['grid-template-columns'] = false; // default: none
  210. whiteList['grid-template-rows'] = false; // default: none
  211. whiteList['hanging-punctuation'] = false; // default: none
  212. whiteList['height'] = true; // default: auto
  213. whiteList['hyphens'] = false; // default: manual
  214. whiteList['icon'] = false; // default: auto
  215. whiteList['image-orientation'] = false; // default: auto
  216. whiteList['image-resolution'] = false; // default: normal
  217. whiteList['ime-mode'] = false; // default: auto
  218. whiteList['initial-letters'] = false; // default: normal
  219. whiteList['inline-box-align'] = false; // default: last
  220. whiteList['justify-content'] = false; // default: auto
  221. whiteList['justify-items'] = false; // default: auto
  222. whiteList['justify-self'] = false; // default: auto
  223. whiteList['left'] = false; // default: auto
  224. whiteList['letter-spacing'] = true; // default: normal
  225. whiteList['lighting-color'] = true; // default: white
  226. whiteList['line-box-contain'] = false; // default: block inline replaced
  227. whiteList['line-break'] = false; // default: auto
  228. whiteList['line-grid'] = false; // default: match-parent
  229. whiteList['line-height'] = false; // default: normal
  230. whiteList['line-snap'] = false; // default: none
  231. whiteList['line-stacking'] = false; // default: depending on individual properties
  232. whiteList['line-stacking-ruby'] = false; // default: exclude-ruby
  233. whiteList['line-stacking-shift'] = false; // default: consider-shifts
  234. whiteList['line-stacking-strategy'] = false; // default: inline-line-height
  235. whiteList['list-style'] = true; // default: depending on individual properties
  236. whiteList['list-style-image'] = true; // default: none
  237. whiteList['list-style-position'] = true; // default: outside
  238. whiteList['list-style-type'] = true; // default: disc
  239. whiteList['margin'] = true; // default: depending on individual properties
  240. whiteList['margin-bottom'] = true; // default: 0
  241. whiteList['margin-left'] = true; // default: 0
  242. whiteList['margin-right'] = true; // default: 0
  243. whiteList['margin-top'] = true; // default: 0
  244. whiteList['marker-offset'] = false; // default: auto
  245. whiteList['marker-side'] = false; // default: list-item
  246. whiteList['marks'] = false; // default: none
  247. whiteList['mask'] = false; // default: border-box
  248. whiteList['mask-box'] = false; // default: see individual properties
  249. whiteList['mask-box-outset'] = false; // default: 0
  250. whiteList['mask-box-repeat'] = false; // default: stretch
  251. whiteList['mask-box-slice'] = false; // default: 0 fill
  252. whiteList['mask-box-source'] = false; // default: none
  253. whiteList['mask-box-width'] = false; // default: auto
  254. whiteList['mask-clip'] = false; // default: border-box
  255. whiteList['mask-image'] = false; // default: none
  256. whiteList['mask-origin'] = false; // default: border-box
  257. whiteList['mask-position'] = false; // default: center
  258. whiteList['mask-repeat'] = false; // default: no-repeat
  259. whiteList['mask-size'] = false; // default: border-box
  260. whiteList['mask-source-type'] = false; // default: auto
  261. whiteList['mask-type'] = false; // default: luminance
  262. whiteList['max-height'] = true; // default: none
  263. whiteList['max-lines'] = false; // default: none
  264. whiteList['max-width'] = true; // default: none
  265. whiteList['min-height'] = true; // default: 0
  266. whiteList['min-width'] = true; // default: 0
  267. whiteList['move-to'] = false; // default: normal
  268. whiteList['nav-down'] = false; // default: auto
  269. whiteList['nav-index'] = false; // default: auto
  270. whiteList['nav-left'] = false; // default: auto
  271. whiteList['nav-right'] = false; // default: auto
  272. whiteList['nav-up'] = false; // default: auto
  273. whiteList['object-fit'] = false; // default: fill
  274. whiteList['object-position'] = false; // default: 50% 50%
  275. whiteList['opacity'] = false; // default: 1
  276. whiteList['order'] = false; // default: 0
  277. whiteList['orphans'] = false; // default: 2
  278. whiteList['outline'] = false; // default: depending on individual properties
  279. whiteList['outline-color'] = false; // default: invert
  280. whiteList['outline-offset'] = false; // default: 0
  281. whiteList['outline-style'] = false; // default: none
  282. whiteList['outline-width'] = false; // default: medium
  283. whiteList['overflow'] = false; // default: depending on individual properties
  284. whiteList['overflow-wrap'] = false; // default: normal
  285. whiteList['overflow-x'] = false; // default: visible
  286. whiteList['overflow-y'] = false; // default: visible
  287. whiteList['padding'] = true; // default: depending on individual properties
  288. whiteList['padding-bottom'] = true; // default: 0
  289. whiteList['padding-left'] = true; // default: 0
  290. whiteList['padding-right'] = true; // default: 0
  291. whiteList['padding-top'] = true; // default: 0
  292. whiteList['page'] = false; // default: auto
  293. whiteList['page-break-after'] = false; // default: auto
  294. whiteList['page-break-before'] = false; // default: auto
  295. whiteList['page-break-inside'] = false; // default: auto
  296. whiteList['page-policy'] = false; // default: start
  297. whiteList['pause'] = false; // default: implementation dependent
  298. whiteList['pause-after'] = false; // default: implementation dependent
  299. whiteList['pause-before'] = false; // default: implementation dependent
  300. whiteList['perspective'] = false; // default: none
  301. whiteList['perspective-origin'] = false; // default: 50% 50%
  302. whiteList['pitch'] = false; // default: medium
  303. whiteList['pitch-range'] = false; // default: 50
  304. whiteList['play-during'] = false; // default: auto
  305. whiteList['position'] = false; // default: static
  306. whiteList['presentation-level'] = false; // default: 0
  307. whiteList['quotes'] = false; // default: text
  308. whiteList['region-fragment'] = false; // default: auto
  309. whiteList['resize'] = false; // default: none
  310. whiteList['rest'] = false; // default: depending on individual properties
  311. whiteList['rest-after'] = false; // default: none
  312. whiteList['rest-before'] = false; // default: none
  313. whiteList['richness'] = false; // default: 50
  314. whiteList['right'] = false; // default: auto
  315. whiteList['rotation'] = false; // default: 0
  316. whiteList['rotation-point'] = false; // default: 50% 50%
  317. whiteList['ruby-align'] = false; // default: auto
  318. whiteList['ruby-merge'] = false; // default: separate
  319. whiteList['ruby-position'] = false; // default: before
  320. whiteList['shape-image-threshold'] = false; // default: 0.0
  321. whiteList['shape-outside'] = false; // default: none
  322. whiteList['shape-margin'] = false; // default: 0
  323. whiteList['size'] = false; // default: auto
  324. whiteList['speak'] = false; // default: auto
  325. whiteList['speak-as'] = false; // default: normal
  326. whiteList['speak-header'] = false; // default: once
  327. whiteList['speak-numeral'] = false; // default: continuous
  328. whiteList['speak-punctuation'] = false; // default: none
  329. whiteList['speech-rate'] = false; // default: medium
  330. whiteList['stress'] = false; // default: 50
  331. whiteList['string-set'] = false; // default: none
  332. whiteList['tab-size'] = false; // default: 8
  333. whiteList['table-layout'] = false; // default: auto
  334. whiteList['text-align'] = true; // default: start
  335. whiteList['text-align-last'] = true; // default: auto
  336. whiteList['text-combine-upright'] = true; // default: none
  337. whiteList['text-decoration'] = true; // default: none
  338. whiteList['text-decoration-color'] = true; // default: currentColor
  339. whiteList['text-decoration-line'] = true; // default: none
  340. whiteList['text-decoration-skip'] = true; // default: objects
  341. whiteList['text-decoration-style'] = true; // default: solid
  342. whiteList['text-emphasis'] = true; // default: depending on individual properties
  343. whiteList['text-emphasis-color'] = true; // default: currentColor
  344. whiteList['text-emphasis-position'] = true; // default: over right
  345. whiteList['text-emphasis-style'] = true; // default: none
  346. whiteList['text-height'] = true; // default: auto
  347. whiteList['text-indent'] = true; // default: 0
  348. whiteList['text-justify'] = true; // default: auto
  349. whiteList['text-orientation'] = true; // default: mixed
  350. whiteList['text-overflow'] = true; // default: clip
  351. whiteList['text-shadow'] = true; // default: none
  352. whiteList['text-space-collapse'] = true; // default: collapse
  353. whiteList['text-transform'] = true; // default: none
  354. whiteList['text-underline-position'] = true; // default: auto
  355. whiteList['text-wrap'] = true; // default: normal
  356. whiteList['top'] = false; // default: auto
  357. whiteList['transform'] = false; // default: none
  358. whiteList['transform-origin'] = false; // default: 50% 50% 0
  359. whiteList['transform-style'] = false; // default: flat
  360. whiteList['transition'] = false; // default: depending on individual properties
  361. whiteList['transition-delay'] = false; // default: 0s
  362. whiteList['transition-duration'] = false; // default: 0s
  363. whiteList['transition-property'] = false; // default: all
  364. whiteList['transition-timing-function'] = false; // default: ease
  365. whiteList['unicode-bidi'] = false; // default: normal
  366. whiteList['vertical-align'] = false; // default: baseline
  367. whiteList['visibility'] = false; // default: visible
  368. whiteList['voice-balance'] = false; // default: center
  369. whiteList['voice-duration'] = false; // default: auto
  370. whiteList['voice-family'] = false; // default: implementation dependent
  371. whiteList['voice-pitch'] = false; // default: medium
  372. whiteList['voice-range'] = false; // default: medium
  373. whiteList['voice-rate'] = false; // default: normal
  374. whiteList['voice-stress'] = false; // default: normal
  375. whiteList['voice-volume'] = false; // default: medium
  376. whiteList['volume'] = false; // default: medium
  377. whiteList['white-space'] = false; // default: normal
  378. whiteList['widows'] = false; // default: 2
  379. whiteList['width'] = true; // default: auto
  380. whiteList['will-change'] = false; // default: auto
  381. whiteList['word-break'] = true; // default: normal
  382. whiteList['word-spacing'] = true; // default: normal
  383. whiteList['word-wrap'] = true; // default: normal
  384. whiteList['wrap-flow'] = false; // default: auto
  385. whiteList['wrap-through'] = false; // default: wrap
  386. whiteList['writing-mode'] = false; // default: horizontal-tb
  387. whiteList['z-index'] = false; // default: auto
  388. return whiteList;
  389. }
  390. /**
  391. * 匹配到白名单上的一个属性时
  392. *
  393. * @param {String} name
  394. * @param {String} value
  395. * @param {Object} options
  396. * @return {String}
  397. */
  398. function onAttr (name, value, options) {
  399. // do nothing
  400. }
  401. /**
  402. * 匹配到不在白名单上的一个属性时
  403. *
  404. * @param {String} name
  405. * @param {String} value
  406. * @param {Object} options
  407. * @return {String}
  408. */
  409. function onIgnoreAttr (name, value, options) {
  410. // do nothing
  411. }
  412. var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img;
  413. /**
  414. * 过滤属性值
  415. *
  416. * @param {String} name
  417. * @param {String} value
  418. * @return {String}
  419. */
  420. function safeAttrValue$1(name, value) {
  421. if (REGEXP_URL_JAVASCRIPT.test(value)) return '';
  422. return value;
  423. }
  424. _default.whiteList = getDefaultWhiteList$1();
  425. _default.getDefaultWhiteList = getDefaultWhiteList$1;
  426. _default.onAttr = onAttr;
  427. _default.onIgnoreAttr = onIgnoreAttr;
  428. _default.safeAttrValue = safeAttrValue$1;
  429. var util$1 = {
  430. indexOf: function (arr, item) {
  431. var i, j;
  432. if (Array.prototype.indexOf) {
  433. return arr.indexOf(item);
  434. }
  435. for (i = 0, j = arr.length; i < j; i++) {
  436. if (arr[i] === item) {
  437. return i;
  438. }
  439. }
  440. return -1;
  441. },
  442. forEach: function (arr, fn, scope) {
  443. var i, j;
  444. if (Array.prototype.forEach) {
  445. return arr.forEach(fn, scope);
  446. }
  447. for (i = 0, j = arr.length; i < j; i++) {
  448. fn.call(scope, arr[i], i, arr);
  449. }
  450. },
  451. trim: function (str) {
  452. if (String.prototype.trim) {
  453. return str.trim();
  454. }
  455. return str.replace(/(^\s*)|(\s*$)/g, '');
  456. },
  457. trimRight: function (str) {
  458. if (String.prototype.trimRight) {
  459. return str.trimRight();
  460. }
  461. return str.replace(/(\s*$)/g, '');
  462. }
  463. };
  464. /**
  465. * cssfilter
  466. *
  467. * @author 老雷<leizongmin@gmail.com>
  468. */
  469. var _$3 = util$1;
  470. /**
  471. * 解析style
  472. *
  473. * @param {String} css
  474. * @param {Function} onAttr 处理属性的函数
  475. * 参数格式: function (sourcePosition, position, name, value, source)
  476. * @return {String}
  477. */
  478. function parseStyle$1 (css, onAttr) {
  479. css = _$3.trimRight(css);
  480. if (css[css.length - 1] !== ';') css += ';';
  481. var cssLength = css.length;
  482. var isParenthesisOpen = false;
  483. var lastPos = 0;
  484. var i = 0;
  485. var retCSS = '';
  486. function addNewAttr () {
  487. // 如果没有正常的闭合圆括号,则直接忽略当前属性
  488. if (!isParenthesisOpen) {
  489. var source = _$3.trim(css.slice(lastPos, i));
  490. var j = source.indexOf(':');
  491. if (j !== -1) {
  492. var name = _$3.trim(source.slice(0, j));
  493. var value = _$3.trim(source.slice(j + 1));
  494. // 必须有属性名称
  495. if (name) {
  496. var ret = onAttr(lastPos, retCSS.length, name, value, source);
  497. if (ret) retCSS += ret + '; ';
  498. }
  499. }
  500. }
  501. lastPos = i + 1;
  502. }
  503. for (; i < cssLength; i++) {
  504. var c = css[i];
  505. if (c === '/' && css[i + 1] === '*') {
  506. // 备注开始
  507. var j = css.indexOf('*/', i + 2);
  508. // 如果没有正常的备注结束,则后面的部分全部跳过
  509. if (j === -1) break;
  510. // 直接将当前位置调到备注结尾,并且初始化状态
  511. i = j + 1;
  512. lastPos = i + 1;
  513. isParenthesisOpen = false;
  514. } else if (c === '(') {
  515. isParenthesisOpen = true;
  516. } else if (c === ')') {
  517. isParenthesisOpen = false;
  518. } else if (c === ';') {
  519. if (isParenthesisOpen) ; else {
  520. addNewAttr();
  521. }
  522. } else if (c === '\n') {
  523. addNewAttr();
  524. }
  525. }
  526. return _$3.trim(retCSS);
  527. }
  528. var parser$2 = parseStyle$1;
  529. /**
  530. * cssfilter
  531. *
  532. * @author 老雷<leizongmin@gmail.com>
  533. */
  534. var DEFAULT$1 = _default;
  535. var parseStyle = parser$2;
  536. /**
  537. * 返回值是否为空
  538. *
  539. * @param {Object} obj
  540. * @return {Boolean}
  541. */
  542. function isNull$1 (obj) {
  543. return (obj === undefined || obj === null);
  544. }
  545. /**
  546. * 浅拷贝对象
  547. *
  548. * @param {Object} obj
  549. * @return {Object}
  550. */
  551. function shallowCopyObject$1 (obj) {
  552. var ret = {};
  553. for (var i in obj) {
  554. ret[i] = obj[i];
  555. }
  556. return ret;
  557. }
  558. /**
  559. * 创建CSS过滤器
  560. *
  561. * @param {Object} options
  562. * - {Object} whiteList
  563. * - {Function} onAttr
  564. * - {Function} onIgnoreAttr
  565. * - {Function} safeAttrValue
  566. */
  567. function FilterCSS$2 (options) {
  568. options = shallowCopyObject$1(options || {});
  569. options.whiteList = options.whiteList || DEFAULT$1.whiteList;
  570. options.onAttr = options.onAttr || DEFAULT$1.onAttr;
  571. options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT$1.onIgnoreAttr;
  572. options.safeAttrValue = options.safeAttrValue || DEFAULT$1.safeAttrValue;
  573. this.options = options;
  574. }
  575. FilterCSS$2.prototype.process = function (css) {
  576. // 兼容各种奇葩输入
  577. css = css || '';
  578. css = css.toString();
  579. if (!css) return '';
  580. var me = this;
  581. var options = me.options;
  582. var whiteList = options.whiteList;
  583. var onAttr = options.onAttr;
  584. var onIgnoreAttr = options.onIgnoreAttr;
  585. var safeAttrValue = options.safeAttrValue;
  586. var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) {
  587. var check = whiteList[name];
  588. var isWhite = false;
  589. if (check === true) isWhite = check;
  590. else if (typeof check === 'function') isWhite = check(value);
  591. else if (check instanceof RegExp) isWhite = check.test(value);
  592. if (isWhite !== true) isWhite = false;
  593. // 如果过滤后 value 为空则直接忽略
  594. value = safeAttrValue(name, value);
  595. if (!value) return;
  596. var opts = {
  597. position: position,
  598. sourcePosition: sourcePosition,
  599. source: source,
  600. isWhite: isWhite
  601. };
  602. if (isWhite) {
  603. var ret = onAttr(name, value, opts);
  604. if (isNull$1(ret)) {
  605. return name + ':' + value;
  606. } else {
  607. return ret;
  608. }
  609. } else {
  610. var ret = onIgnoreAttr(name, value, opts);
  611. if (!isNull$1(ret)) {
  612. return ret;
  613. }
  614. }
  615. });
  616. return retCSS;
  617. };
  618. var css = FilterCSS$2;
  619. /**
  620. * cssfilter
  621. *
  622. * @author 老雷<leizongmin@gmail.com>
  623. */
  624. (function (module, exports) {
  625. var DEFAULT = _default;
  626. var FilterCSS = css;
  627. /**
  628. * XSS过滤
  629. *
  630. * @param {String} css 要过滤的CSS代码
  631. * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr
  632. * @return {String}
  633. */
  634. function filterCSS (html, options) {
  635. var xss = new FilterCSS(options);
  636. return xss.process(html);
  637. }
  638. // 输出
  639. exports = module.exports = filterCSS;
  640. exports.FilterCSS = FilterCSS;
  641. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  642. } (lib, lib.exports));
  643. var util = {
  644. indexOf: function (arr, item) {
  645. var i, j;
  646. if (Array.prototype.indexOf) {
  647. return arr.indexOf(item);
  648. }
  649. for (i = 0, j = arr.length; i < j; i++) {
  650. if (arr[i] === item) {
  651. return i;
  652. }
  653. }
  654. return -1;
  655. },
  656. forEach: function (arr, fn, scope) {
  657. var i, j;
  658. if (Array.prototype.forEach) {
  659. return arr.forEach(fn, scope);
  660. }
  661. for (i = 0, j = arr.length; i < j; i++) {
  662. fn.call(scope, arr[i], i, arr);
  663. }
  664. },
  665. trim: function (str) {
  666. if (String.prototype.trim) {
  667. return str.trim();
  668. }
  669. return str.replace(/(^\s*)|(\s*$)/g, "");
  670. },
  671. spaceIndex: function (str) {
  672. var reg = /\s|\n|\t/;
  673. var match = reg.exec(str);
  674. return match ? match.index : -1;
  675. },
  676. };
  677. /**
  678. * default settings
  679. *
  680. * @author Zongmin Lei<leizongmin@gmail.com>
  681. */
  682. var FilterCSS$1 = lib.exports.FilterCSS;
  683. var getDefaultCSSWhiteList = lib.exports.getDefaultWhiteList;
  684. var _$2 = util;
  685. function getDefaultWhiteList() {
  686. return {
  687. a: ["target", "href", "title"],
  688. abbr: ["title"],
  689. address: [],
  690. area: ["shape", "coords", "href", "alt"],
  691. article: [],
  692. aside: [],
  693. audio: [
  694. "autoplay",
  695. "controls",
  696. "crossorigin",
  697. "loop",
  698. "muted",
  699. "preload",
  700. "src",
  701. ],
  702. b: [],
  703. bdi: ["dir"],
  704. bdo: ["dir"],
  705. big: [],
  706. blockquote: ["cite"],
  707. br: [],
  708. caption: [],
  709. center: [],
  710. cite: [],
  711. code: [],
  712. col: ["align", "valign", "span", "width"],
  713. colgroup: ["align", "valign", "span", "width"],
  714. dd: [],
  715. del: ["datetime"],
  716. details: ["open"],
  717. div: [],
  718. dl: [],
  719. dt: [],
  720. em: [],
  721. figcaption: [],
  722. figure: [],
  723. font: ["color", "size", "face"],
  724. footer: [],
  725. h1: [],
  726. h2: [],
  727. h3: [],
  728. h4: [],
  729. h5: [],
  730. h6: [],
  731. header: [],
  732. hr: [],
  733. i: [],
  734. img: ["src", "alt", "title", "width", "height"],
  735. ins: ["datetime"],
  736. li: [],
  737. mark: [],
  738. nav: [],
  739. ol: [],
  740. p: [],
  741. pre: [],
  742. s: [],
  743. section: [],
  744. small: [],
  745. span: [],
  746. sub: [],
  747. summary: [],
  748. sup: [],
  749. strong: [],
  750. strike: [],
  751. table: ["width", "border", "align", "valign"],
  752. tbody: ["align", "valign"],
  753. td: ["width", "rowspan", "colspan", "align", "valign"],
  754. tfoot: ["align", "valign"],
  755. th: ["width", "rowspan", "colspan", "align", "valign"],
  756. thead: ["align", "valign"],
  757. tr: ["rowspan", "align", "valign"],
  758. tt: [],
  759. u: [],
  760. ul: [],
  761. video: [
  762. "autoplay",
  763. "controls",
  764. "crossorigin",
  765. "loop",
  766. "muted",
  767. "playsinline",
  768. "poster",
  769. "preload",
  770. "src",
  771. "height",
  772. "width",
  773. ],
  774. };
  775. }
  776. var defaultCSSFilter = new FilterCSS$1();
  777. /**
  778. * default onTag function
  779. *
  780. * @param {String} tag
  781. * @param {String} html
  782. * @param {Object} options
  783. * @return {String}
  784. */
  785. function onTag(tag, html, options) {
  786. // do nothing
  787. }
  788. /**
  789. * default onIgnoreTag function
  790. *
  791. * @param {String} tag
  792. * @param {String} html
  793. * @param {Object} options
  794. * @return {String}
  795. */
  796. function onIgnoreTag(tag, html, options) {
  797. // do nothing
  798. }
  799. /**
  800. * default onTagAttr function
  801. *
  802. * @param {String} tag
  803. * @param {String} name
  804. * @param {String} value
  805. * @return {String}
  806. */
  807. function onTagAttr(tag, name, value) {
  808. // do nothing
  809. }
  810. /**
  811. * default onIgnoreTagAttr function
  812. *
  813. * @param {String} tag
  814. * @param {String} name
  815. * @param {String} value
  816. * @return {String}
  817. */
  818. function onIgnoreTagAttr(tag, name, value) {
  819. // do nothing
  820. }
  821. /**
  822. * default escapeHtml function
  823. *
  824. * @param {String} html
  825. */
  826. function escapeHtml(html) {
  827. return html.replace(REGEXP_LT, "&lt;").replace(REGEXP_GT, "&gt;");
  828. }
  829. /**
  830. * default safeAttrValue function
  831. *
  832. * @param {String} tag
  833. * @param {String} name
  834. * @param {String} value
  835. * @param {Object} cssFilter
  836. * @return {String}
  837. */
  838. function safeAttrValue(tag, name, value, cssFilter) {
  839. // unescape attribute value firstly
  840. value = friendlyAttrValue(value);
  841. if (name === "href" || name === "src") {
  842. // filter `href` and `src` attribute
  843. // only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#`
  844. value = _$2.trim(value);
  845. if (value === "#") return "#";
  846. if (
  847. !(
  848. value.substr(0, 7) === "http://" ||
  849. value.substr(0, 8) === "https://" ||
  850. value.substr(0, 7) === "mailto:" ||
  851. value.substr(0, 4) === "tel:" ||
  852. value.substr(0, 11) === "data:image/" ||
  853. value.substr(0, 6) === "ftp://" ||
  854. value.substr(0, 2) === "./" ||
  855. value.substr(0, 3) === "../" ||
  856. value[0] === "#" ||
  857. value[0] === "/"
  858. )
  859. ) {
  860. return "";
  861. }
  862. } else if (name === "background") {
  863. // filter `background` attribute (maybe no use)
  864. // `javascript:`
  865. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  866. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  867. return "";
  868. }
  869. } else if (name === "style") {
  870. // `expression()`
  871. REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0;
  872. if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) {
  873. return "";
  874. }
  875. // `url()`
  876. REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0;
  877. if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) {
  878. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  879. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  880. return "";
  881. }
  882. }
  883. if (cssFilter !== false) {
  884. cssFilter = cssFilter || defaultCSSFilter;
  885. value = cssFilter.process(value);
  886. }
  887. }
  888. // escape `<>"` before returns
  889. value = escapeAttrValue(value);
  890. return value;
  891. }
  892. // RegExp list
  893. var REGEXP_LT = /</g;
  894. var REGEXP_GT = />/g;
  895. var REGEXP_QUOTE = /"/g;
  896. var REGEXP_QUOTE_2 = /&quot;/g;
  897. var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim;
  898. var REGEXP_ATTR_VALUE_COLON = /&colon;?/gim;
  899. var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim;
  900. // var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm;
  901. var REGEXP_DEFAULT_ON_TAG_ATTR_4 =
  902. /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi;
  903. // var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi;
  904. // var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi;
  905. var REGEXP_DEFAULT_ON_TAG_ATTR_7 =
  906. /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi;
  907. var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi;
  908. /**
  909. * escape double quote
  910. *
  911. * @param {String} str
  912. * @return {String} str
  913. */
  914. function escapeQuote(str) {
  915. return str.replace(REGEXP_QUOTE, "&quot;");
  916. }
  917. /**
  918. * unescape double quote
  919. *
  920. * @param {String} str
  921. * @return {String} str
  922. */
  923. function unescapeQuote(str) {
  924. return str.replace(REGEXP_QUOTE_2, '"');
  925. }
  926. /**
  927. * escape html entities
  928. *
  929. * @param {String} str
  930. * @return {String}
  931. */
  932. function escapeHtmlEntities(str) {
  933. return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) {
  934. return code[0] === "x" || code[0] === "X"
  935. ? String.fromCharCode(parseInt(code.substr(1), 16))
  936. : String.fromCharCode(parseInt(code, 10));
  937. });
  938. }
  939. /**
  940. * escape html5 new danger entities
  941. *
  942. * @param {String} str
  943. * @return {String}
  944. */
  945. function escapeDangerHtml5Entities(str) {
  946. return str
  947. .replace(REGEXP_ATTR_VALUE_COLON, ":")
  948. .replace(REGEXP_ATTR_VALUE_NEWLINE, " ");
  949. }
  950. /**
  951. * clear nonprintable characters
  952. *
  953. * @param {String} str
  954. * @return {String}
  955. */
  956. function clearNonPrintableCharacter(str) {
  957. var str2 = "";
  958. for (var i = 0, len = str.length; i < len; i++) {
  959. str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i);
  960. }
  961. return _$2.trim(str2);
  962. }
  963. /**
  964. * get friendly attribute value
  965. *
  966. * @param {String} str
  967. * @return {String}
  968. */
  969. function friendlyAttrValue(str) {
  970. str = unescapeQuote(str);
  971. str = escapeHtmlEntities(str);
  972. str = escapeDangerHtml5Entities(str);
  973. str = clearNonPrintableCharacter(str);
  974. return str;
  975. }
  976. /**
  977. * unescape attribute value
  978. *
  979. * @param {String} str
  980. * @return {String}
  981. */
  982. function escapeAttrValue(str) {
  983. str = escapeQuote(str);
  984. str = escapeHtml(str);
  985. return str;
  986. }
  987. /**
  988. * `onIgnoreTag` function for removing all the tags that are not in whitelist
  989. */
  990. function onIgnoreTagStripAll() {
  991. return "";
  992. }
  993. /**
  994. * remove tag body
  995. * specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional)
  996. *
  997. * @param {array} tags
  998. * @param {function} next
  999. */
  1000. function StripTagBody(tags, next) {
  1001. if (typeof next !== "function") {
  1002. next = function () {};
  1003. }
  1004. var isRemoveAllTag = !Array.isArray(tags);
  1005. function isRemoveTag(tag) {
  1006. if (isRemoveAllTag) return true;
  1007. return _$2.indexOf(tags, tag) !== -1;
  1008. }
  1009. var removeList = [];
  1010. var posStart = false;
  1011. return {
  1012. onIgnoreTag: function (tag, html, options) {
  1013. if (isRemoveTag(tag)) {
  1014. if (options.isClosing) {
  1015. var ret = "[/removed]";
  1016. var end = options.position + ret.length;
  1017. removeList.push([
  1018. posStart !== false ? posStart : options.position,
  1019. end,
  1020. ]);
  1021. posStart = false;
  1022. return ret;
  1023. } else {
  1024. if (!posStart) {
  1025. posStart = options.position;
  1026. }
  1027. return "[removed]";
  1028. }
  1029. } else {
  1030. return next(tag, html, options);
  1031. }
  1032. },
  1033. remove: function (html) {
  1034. var rethtml = "";
  1035. var lastPos = 0;
  1036. _$2.forEach(removeList, function (pos) {
  1037. rethtml += html.slice(lastPos, pos[0]);
  1038. lastPos = pos[1];
  1039. });
  1040. rethtml += html.slice(lastPos);
  1041. return rethtml;
  1042. },
  1043. };
  1044. }
  1045. /**
  1046. * remove html comments
  1047. *
  1048. * @param {String} html
  1049. * @return {String}
  1050. */
  1051. function stripCommentTag(html) {
  1052. var retHtml = "";
  1053. var lastPos = 0;
  1054. while (lastPos < html.length) {
  1055. var i = html.indexOf("<!--", lastPos);
  1056. if (i === -1) {
  1057. retHtml += html.slice(lastPos);
  1058. break;
  1059. }
  1060. retHtml += html.slice(lastPos, i);
  1061. var j = html.indexOf("-->", i);
  1062. if (j === -1) {
  1063. break;
  1064. }
  1065. lastPos = j + 3;
  1066. }
  1067. return retHtml;
  1068. }
  1069. /**
  1070. * remove invisible characters
  1071. *
  1072. * @param {String} html
  1073. * @return {String}
  1074. */
  1075. function stripBlankChar(html) {
  1076. var chars = html.split("");
  1077. chars = chars.filter(function (char) {
  1078. var c = char.charCodeAt(0);
  1079. if (c === 127) return false;
  1080. if (c <= 31) {
  1081. if (c === 10 || c === 13) return true;
  1082. return false;
  1083. }
  1084. return true;
  1085. });
  1086. return chars.join("");
  1087. }
  1088. _default$1.whiteList = getDefaultWhiteList();
  1089. _default$1.getDefaultWhiteList = getDefaultWhiteList;
  1090. _default$1.onTag = onTag;
  1091. _default$1.onIgnoreTag = onIgnoreTag;
  1092. _default$1.onTagAttr = onTagAttr;
  1093. _default$1.onIgnoreTagAttr = onIgnoreTagAttr;
  1094. _default$1.safeAttrValue = safeAttrValue;
  1095. _default$1.escapeHtml = escapeHtml;
  1096. _default$1.escapeQuote = escapeQuote;
  1097. _default$1.unescapeQuote = unescapeQuote;
  1098. _default$1.escapeHtmlEntities = escapeHtmlEntities;
  1099. _default$1.escapeDangerHtml5Entities = escapeDangerHtml5Entities;
  1100. _default$1.clearNonPrintableCharacter = clearNonPrintableCharacter;
  1101. _default$1.friendlyAttrValue = friendlyAttrValue;
  1102. _default$1.escapeAttrValue = escapeAttrValue;
  1103. _default$1.onIgnoreTagStripAll = onIgnoreTagStripAll;
  1104. _default$1.StripTagBody = StripTagBody;
  1105. _default$1.stripCommentTag = stripCommentTag;
  1106. _default$1.stripBlankChar = stripBlankChar;
  1107. _default$1.cssFilter = defaultCSSFilter;
  1108. _default$1.getDefaultCSSWhiteList = getDefaultCSSWhiteList;
  1109. var parser$1 = {};
  1110. /**
  1111. * Simple HTML Parser
  1112. *
  1113. * @author Zongmin Lei<leizongmin@gmail.com>
  1114. */
  1115. var _$1 = util;
  1116. /**
  1117. * get tag name
  1118. *
  1119. * @param {String} html e.g. '<a hef="#">'
  1120. * @return {String}
  1121. */
  1122. function getTagName(html) {
  1123. var i = _$1.spaceIndex(html);
  1124. var tagName;
  1125. if (i === -1) {
  1126. tagName = html.slice(1, -1);
  1127. } else {
  1128. tagName = html.slice(1, i + 1);
  1129. }
  1130. tagName = _$1.trim(tagName).toLowerCase();
  1131. if (tagName.slice(0, 1) === "/") tagName = tagName.slice(1);
  1132. if (tagName.slice(-1) === "/") tagName = tagName.slice(0, -1);
  1133. return tagName;
  1134. }
  1135. /**
  1136. * is close tag?
  1137. *
  1138. * @param {String} html 如:'<a hef="#">'
  1139. * @return {Boolean}
  1140. */
  1141. function isClosing(html) {
  1142. return html.slice(0, 2) === "</";
  1143. }
  1144. /**
  1145. * parse input html and returns processed html
  1146. *
  1147. * @param {String} html
  1148. * @param {Function} onTag e.g. function (sourcePosition, position, tag, html, isClosing)
  1149. * @param {Function} escapeHtml
  1150. * @return {String}
  1151. */
  1152. function parseTag$1(html, onTag, escapeHtml) {
  1153. var rethtml = "";
  1154. var lastPos = 0;
  1155. var tagStart = false;
  1156. var quoteStart = false;
  1157. var currentPos = 0;
  1158. var len = html.length;
  1159. var currentTagName = "";
  1160. var currentHtml = "";
  1161. chariterator: for (currentPos = 0; currentPos < len; currentPos++) {
  1162. var c = html.charAt(currentPos);
  1163. if (tagStart === false) {
  1164. if (c === "<") {
  1165. tagStart = currentPos;
  1166. continue;
  1167. }
  1168. } else {
  1169. if (quoteStart === false) {
  1170. if (c === "<") {
  1171. rethtml += escapeHtml(html.slice(lastPos, currentPos));
  1172. tagStart = currentPos;
  1173. lastPos = currentPos;
  1174. continue;
  1175. }
  1176. if (c === ">") {
  1177. rethtml += escapeHtml(html.slice(lastPos, tagStart));
  1178. currentHtml = html.slice(tagStart, currentPos + 1);
  1179. currentTagName = getTagName(currentHtml);
  1180. rethtml += onTag(
  1181. tagStart,
  1182. rethtml.length,
  1183. currentTagName,
  1184. currentHtml,
  1185. isClosing(currentHtml)
  1186. );
  1187. lastPos = currentPos + 1;
  1188. tagStart = false;
  1189. continue;
  1190. }
  1191. if (c === '"' || c === "'") {
  1192. var i = 1;
  1193. var ic = html.charAt(currentPos - i);
  1194. while (ic.trim() === "" || ic === "=") {
  1195. if (ic === "=") {
  1196. quoteStart = c;
  1197. continue chariterator;
  1198. }
  1199. ic = html.charAt(currentPos - ++i);
  1200. }
  1201. }
  1202. } else {
  1203. if (c === quoteStart) {
  1204. quoteStart = false;
  1205. continue;
  1206. }
  1207. }
  1208. }
  1209. }
  1210. if (lastPos < html.length) {
  1211. rethtml += escapeHtml(html.substr(lastPos));
  1212. }
  1213. return rethtml;
  1214. }
  1215. var REGEXP_ILLEGAL_ATTR_NAME = /[^a-zA-Z0-9\\_:.-]/gim;
  1216. /**
  1217. * parse input attributes and returns processed attributes
  1218. *
  1219. * @param {String} html e.g. `href="#" target="_blank"`
  1220. * @param {Function} onAttr e.g. `function (name, value)`
  1221. * @return {String}
  1222. */
  1223. function parseAttr$1(html, onAttr) {
  1224. var lastPos = 0;
  1225. var lastMarkPos = 0;
  1226. var retAttrs = [];
  1227. var tmpName = false;
  1228. var len = html.length;
  1229. function addAttr(name, value) {
  1230. name = _$1.trim(name);
  1231. name = name.replace(REGEXP_ILLEGAL_ATTR_NAME, "").toLowerCase();
  1232. if (name.length < 1) return;
  1233. var ret = onAttr(name, value || "");
  1234. if (ret) retAttrs.push(ret);
  1235. }
  1236. // 逐个分析字符
  1237. for (var i = 0; i < len; i++) {
  1238. var c = html.charAt(i);
  1239. var v, j;
  1240. if (tmpName === false && c === "=") {
  1241. tmpName = html.slice(lastPos, i);
  1242. lastPos = i + 1;
  1243. lastMarkPos = html.charAt(lastPos) === '"' || html.charAt(lastPos) === "'" ? lastPos : findNextQuotationMark(html, i + 1);
  1244. continue;
  1245. }
  1246. if (tmpName !== false) {
  1247. if (
  1248. i === lastMarkPos
  1249. ) {
  1250. j = html.indexOf(c, i + 1);
  1251. if (j === -1) {
  1252. break;
  1253. } else {
  1254. v = _$1.trim(html.slice(lastMarkPos + 1, j));
  1255. addAttr(tmpName, v);
  1256. tmpName = false;
  1257. i = j;
  1258. lastPos = i + 1;
  1259. continue;
  1260. }
  1261. }
  1262. }
  1263. if (/\s|\n|\t/.test(c)) {
  1264. html = html.replace(/\s|\n|\t/g, " ");
  1265. if (tmpName === false) {
  1266. j = findNextEqual(html, i);
  1267. if (j === -1) {
  1268. v = _$1.trim(html.slice(lastPos, i));
  1269. addAttr(v);
  1270. tmpName = false;
  1271. lastPos = i + 1;
  1272. continue;
  1273. } else {
  1274. i = j - 1;
  1275. continue;
  1276. }
  1277. } else {
  1278. j = findBeforeEqual(html, i - 1);
  1279. if (j === -1) {
  1280. v = _$1.trim(html.slice(lastPos, i));
  1281. v = stripQuoteWrap(v);
  1282. addAttr(tmpName, v);
  1283. tmpName = false;
  1284. lastPos = i + 1;
  1285. continue;
  1286. } else {
  1287. continue;
  1288. }
  1289. }
  1290. }
  1291. }
  1292. if (lastPos < html.length) {
  1293. if (tmpName === false) {
  1294. addAttr(html.slice(lastPos));
  1295. } else {
  1296. addAttr(tmpName, stripQuoteWrap(_$1.trim(html.slice(lastPos))));
  1297. }
  1298. }
  1299. return _$1.trim(retAttrs.join(" "));
  1300. }
  1301. function findNextEqual(str, i) {
  1302. for (; i < str.length; i++) {
  1303. var c = str[i];
  1304. if (c === " ") continue;
  1305. if (c === "=") return i;
  1306. return -1;
  1307. }
  1308. }
  1309. function findNextQuotationMark(str, i) {
  1310. for (; i < str.length; i++) {
  1311. var c = str[i];
  1312. if (c === " ") continue;
  1313. if (c === "'" || c === '"') return i;
  1314. return -1;
  1315. }
  1316. }
  1317. function findBeforeEqual(str, i) {
  1318. for (; i > 0; i--) {
  1319. var c = str[i];
  1320. if (c === " ") continue;
  1321. if (c === "=") return i;
  1322. return -1;
  1323. }
  1324. }
  1325. function isQuoteWrapString(text) {
  1326. if (
  1327. (text[0] === '"' && text[text.length - 1] === '"') ||
  1328. (text[0] === "'" && text[text.length - 1] === "'")
  1329. ) {
  1330. return true;
  1331. } else {
  1332. return false;
  1333. }
  1334. }
  1335. function stripQuoteWrap(text) {
  1336. if (isQuoteWrapString(text)) {
  1337. return text.substr(1, text.length - 2);
  1338. } else {
  1339. return text;
  1340. }
  1341. }
  1342. parser$1.parseTag = parseTag$1;
  1343. parser$1.parseAttr = parseAttr$1;
  1344. /**
  1345. * filter xss
  1346. *
  1347. * @author Zongmin Lei<leizongmin@gmail.com>
  1348. */
  1349. var FilterCSS = lib.exports.FilterCSS;
  1350. var DEFAULT = _default$1;
  1351. var parser = parser$1;
  1352. var parseTag = parser.parseTag;
  1353. var parseAttr = parser.parseAttr;
  1354. var _ = util;
  1355. /**
  1356. * returns `true` if the input value is `undefined` or `null`
  1357. *
  1358. * @param {Object} obj
  1359. * @return {Boolean}
  1360. */
  1361. function isNull(obj) {
  1362. return obj === undefined || obj === null;
  1363. }
  1364. /**
  1365. * get attributes for a tag
  1366. *
  1367. * @param {String} html
  1368. * @return {Object}
  1369. * - {String} html
  1370. * - {Boolean} closing
  1371. */
  1372. function getAttrs(html) {
  1373. var i = _.spaceIndex(html);
  1374. if (i === -1) {
  1375. return {
  1376. html: "",
  1377. closing: html[html.length - 2] === "/",
  1378. };
  1379. }
  1380. html = _.trim(html.slice(i + 1, -1));
  1381. var isClosing = html[html.length - 1] === "/";
  1382. if (isClosing) html = _.trim(html.slice(0, -1));
  1383. return {
  1384. html: html,
  1385. closing: isClosing,
  1386. };
  1387. }
  1388. /**
  1389. * shallow copy
  1390. *
  1391. * @param {Object} obj
  1392. * @return {Object}
  1393. */
  1394. function shallowCopyObject(obj) {
  1395. var ret = {};
  1396. for (var i in obj) {
  1397. ret[i] = obj[i];
  1398. }
  1399. return ret;
  1400. }
  1401. function keysToLowerCase(obj) {
  1402. var ret = {};
  1403. for (var i in obj) {
  1404. if (Array.isArray(obj[i])) {
  1405. ret[i.toLowerCase()] = obj[i].map(function (item) {
  1406. return item.toLowerCase();
  1407. });
  1408. } else {
  1409. ret[i.toLowerCase()] = obj[i];
  1410. }
  1411. }
  1412. return ret;
  1413. }
  1414. /**
  1415. * FilterXSS class
  1416. *
  1417. * @param {Object} options
  1418. * whiteList (or allowList), onTag, onTagAttr, onIgnoreTag,
  1419. * onIgnoreTagAttr, safeAttrValue, escapeHtml
  1420. * stripIgnoreTagBody, allowCommentTag, stripBlankChar
  1421. * css{whiteList, onAttr, onIgnoreAttr} `css=false` means don't use `cssfilter`
  1422. */
  1423. function FilterXSS(options) {
  1424. options = shallowCopyObject(options || {});
  1425. if (options.stripIgnoreTag) {
  1426. if (options.onIgnoreTag) {
  1427. console.error(
  1428. 'Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'
  1429. );
  1430. }
  1431. options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll;
  1432. }
  1433. if (options.whiteList || options.allowList) {
  1434. options.whiteList = keysToLowerCase(options.whiteList || options.allowList);
  1435. } else {
  1436. options.whiteList = DEFAULT.whiteList;
  1437. }
  1438. options.onTag = options.onTag || DEFAULT.onTag;
  1439. options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr;
  1440. options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag;
  1441. options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr;
  1442. options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue;
  1443. options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml;
  1444. this.options = options;
  1445. if (options.css === false) {
  1446. this.cssFilter = false;
  1447. } else {
  1448. options.css = options.css || {};
  1449. this.cssFilter = new FilterCSS(options.css);
  1450. }
  1451. }
  1452. /**
  1453. * start process and returns result
  1454. *
  1455. * @param {String} html
  1456. * @return {String}
  1457. */
  1458. FilterXSS.prototype.process = function (html) {
  1459. // compatible with the input
  1460. html = html || "";
  1461. html = html.toString();
  1462. if (!html) return "";
  1463. var me = this;
  1464. var options = me.options;
  1465. var whiteList = options.whiteList;
  1466. var onTag = options.onTag;
  1467. var onIgnoreTag = options.onIgnoreTag;
  1468. var onTagAttr = options.onTagAttr;
  1469. var onIgnoreTagAttr = options.onIgnoreTagAttr;
  1470. var safeAttrValue = options.safeAttrValue;
  1471. var escapeHtml = options.escapeHtml;
  1472. var cssFilter = me.cssFilter;
  1473. // remove invisible characters
  1474. if (options.stripBlankChar) {
  1475. html = DEFAULT.stripBlankChar(html);
  1476. }
  1477. // remove html comments
  1478. if (!options.allowCommentTag) {
  1479. html = DEFAULT.stripCommentTag(html);
  1480. }
  1481. // if enable stripIgnoreTagBody
  1482. var stripIgnoreTagBody = false;
  1483. if (options.stripIgnoreTagBody) {
  1484. stripIgnoreTagBody = DEFAULT.StripTagBody(
  1485. options.stripIgnoreTagBody,
  1486. onIgnoreTag
  1487. );
  1488. onIgnoreTag = stripIgnoreTagBody.onIgnoreTag;
  1489. }
  1490. var retHtml = parseTag(
  1491. html,
  1492. function (sourcePosition, position, tag, html, isClosing) {
  1493. var info = {
  1494. sourcePosition: sourcePosition,
  1495. position: position,
  1496. isClosing: isClosing,
  1497. isWhite: Object.prototype.hasOwnProperty.call(whiteList, tag),
  1498. };
  1499. // call `onTag()`
  1500. var ret = onTag(tag, html, info);
  1501. if (!isNull(ret)) return ret;
  1502. if (info.isWhite) {
  1503. if (info.isClosing) {
  1504. return "</" + tag + ">";
  1505. }
  1506. var attrs = getAttrs(html);
  1507. var whiteAttrList = whiteList[tag];
  1508. var attrsHtml = parseAttr(attrs.html, function (name, value) {
  1509. // call `onTagAttr()`
  1510. var isWhiteAttr = _.indexOf(whiteAttrList, name) !== -1;
  1511. var ret = onTagAttr(tag, name, value, isWhiteAttr);
  1512. if (!isNull(ret)) return ret;
  1513. if (isWhiteAttr) {
  1514. // call `safeAttrValue()`
  1515. value = safeAttrValue(tag, name, value, cssFilter);
  1516. if (value) {
  1517. return name + '="' + value + '"';
  1518. } else {
  1519. return name;
  1520. }
  1521. } else {
  1522. // call `onIgnoreTagAttr()`
  1523. ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr);
  1524. if (!isNull(ret)) return ret;
  1525. return;
  1526. }
  1527. });
  1528. // build new tag html
  1529. html = "<" + tag;
  1530. if (attrsHtml) html += " " + attrsHtml;
  1531. if (attrs.closing) html += " /";
  1532. html += ">";
  1533. return html;
  1534. } else {
  1535. // call `onIgnoreTag()`
  1536. ret = onIgnoreTag(tag, html, info);
  1537. if (!isNull(ret)) return ret;
  1538. return escapeHtml(html);
  1539. }
  1540. },
  1541. escapeHtml
  1542. );
  1543. // if enable stripIgnoreTagBody
  1544. if (stripIgnoreTagBody) {
  1545. retHtml = stripIgnoreTagBody.remove(retHtml);
  1546. }
  1547. return retHtml;
  1548. };
  1549. var xss = FilterXSS;
  1550. /**
  1551. * xss
  1552. *
  1553. * @author Zongmin Lei<leizongmin@gmail.com>
  1554. */
  1555. (function (module, exports) {
  1556. var DEFAULT = _default$1;
  1557. var parser = parser$1;
  1558. var FilterXSS = xss;
  1559. /**
  1560. * filter xss function
  1561. *
  1562. * @param {String} html
  1563. * @param {Object} options { whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml }
  1564. * @return {String}
  1565. */
  1566. function filterXSS(html, options) {
  1567. var xss = new FilterXSS(options);
  1568. return xss.process(html);
  1569. }
  1570. exports = module.exports = filterXSS;
  1571. exports.filterXSS = filterXSS;
  1572. exports.FilterXSS = FilterXSS;
  1573. (function () {
  1574. for (var i in DEFAULT) {
  1575. exports[i] = DEFAULT[i];
  1576. }
  1577. for (var j in parser) {
  1578. exports[j] = parser[j];
  1579. }
  1580. })();
  1581. // using `xss` on the WebWorker, output `filterXSS` to the globals
  1582. function isWorkerEnv() {
  1583. return (
  1584. typeof self !== "undefined" &&
  1585. typeof DedicatedWorkerGlobalScope !== "undefined" &&
  1586. self instanceof DedicatedWorkerGlobalScope
  1587. );
  1588. }
  1589. if (isWorkerEnv()) {
  1590. self.filterXSS = module.exports;
  1591. }
  1592. } (lib$1, lib$1.exports));
  1593. /* Copyright (c) 2020 Environmental Systems Research Institute, Inc.
  1594. * Apache-2.0
  1595. *
  1596. * js-xss
  1597. * Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
  1598. * http://ucdok.com
  1599. * The MIT License, see
  1600. * https://github.com/leizongmin/js-xss/blob/master/LICENSE for details
  1601. * */
  1602. /**
  1603. * The Sanitizer Class
  1604. *
  1605. * @export
  1606. * @class Sanitizer
  1607. */
  1608. var Sanitizer = /** @class */ (function () {
  1609. function Sanitizer(filterOptions, extendDefaults) {
  1610. var _this = this;
  1611. // Supported HTML Spec: https://doc.arcgis.com/en/arcgis-online/reference/supported-html.htm
  1612. this.arcgisWhiteList = {
  1613. a: ["href", "style", "target"],
  1614. abbr: ["title"],
  1615. audio: ["autoplay", "controls", "loop", "muted", "preload"],
  1616. b: [],
  1617. br: [],
  1618. dd: ["style"],
  1619. div: ["align", "style"],
  1620. dl: ["style"],
  1621. dt: ["style"],
  1622. em: [],
  1623. figcaption: ["style"],
  1624. figure: ["style"],
  1625. font: ["color", "face", "size", "style"],
  1626. h1: ["style"],
  1627. h2: ["style"],
  1628. h3: ["style"],
  1629. h4: ["style"],
  1630. h5: ["style"],
  1631. h6: ["style"],
  1632. hr: [],
  1633. i: [],
  1634. img: ["alt", "border", "height", "src", "style", "width"],
  1635. li: [],
  1636. ol: [],
  1637. p: ["style"],
  1638. source: ["media", "src", "type"],
  1639. span: ["style"],
  1640. strong: [],
  1641. sub: ["style"],
  1642. sup: ["style"],
  1643. table: ["border", "cellpadding", "cellspacing", "height", "style", "width"],
  1644. tbody: [],
  1645. tr: ["align", "height", "style", "valign"],
  1646. td: [
  1647. "align",
  1648. "colspan",
  1649. "height",
  1650. "nowrap",
  1651. "rowspan",
  1652. "style",
  1653. "valign",
  1654. "width",
  1655. ],
  1656. th: [
  1657. "align",
  1658. "colspan",
  1659. "height",
  1660. "nowrap",
  1661. "rowspan",
  1662. "style",
  1663. "valign",
  1664. "width",
  1665. ],
  1666. u: [],
  1667. ul: [],
  1668. video: [
  1669. "autoplay",
  1670. "controls",
  1671. "height",
  1672. "loop",
  1673. "muted",
  1674. "poster",
  1675. "preload",
  1676. "width",
  1677. ],
  1678. };
  1679. this.allowedProtocols = [
  1680. "http",
  1681. "https",
  1682. "mailto",
  1683. "iform",
  1684. "tel",
  1685. "flow",
  1686. "lfmobile",
  1687. "arcgis-navigator",
  1688. "arcgis-appstudio-player",
  1689. "arcgis-survey123",
  1690. "arcgis-collector",
  1691. "arcgis-workforce",
  1692. "arcgis-explorer",
  1693. "arcgis-trek2there",
  1694. "arcgis-quickcapture",
  1695. "mspbi",
  1696. "comgooglemaps",
  1697. "pdfefile",
  1698. "pdfehttp",
  1699. "pdfehttps",
  1700. "boxapp",
  1701. "boxemm",
  1702. "awb",
  1703. "awbs",
  1704. "gropen",
  1705. "radarscope",
  1706. ];
  1707. this.arcgisFilterOptions = {
  1708. allowCommentTag: true,
  1709. safeAttrValue: function (tag, name, value, cssFilter) {
  1710. // Take over safe attribute filtering for `a` `href`, `img` `src`,
  1711. // and `source` `src` attributes, otherwise pass onto the
  1712. // default `XSS.safeAttrValue` method.
  1713. if ((tag === "a" && name === "href") ||
  1714. ((tag === "img" || tag === "source") && name === "src")) {
  1715. return _this.sanitizeUrl(value);
  1716. }
  1717. return lib$1.exports.safeAttrValue(tag, name, value, cssFilter);
  1718. },
  1719. };
  1720. this._entityMap = {
  1721. "&": "&#x38;",
  1722. "<": "&#x3C;",
  1723. ">": "&#x3E;",
  1724. '"': "&#x22;",
  1725. "'": "&#x27;",
  1726. "/": "&#x2F;",
  1727. };
  1728. var xssFilterOptions;
  1729. if (filterOptions && !extendDefaults) {
  1730. // Override the defaults
  1731. xssFilterOptions = filterOptions;
  1732. }
  1733. else if (filterOptions && extendDefaults) {
  1734. // Extend the defaults
  1735. xssFilterOptions = Object.create(this.arcgisFilterOptions);
  1736. Object.keys(filterOptions).forEach(function (key) {
  1737. if (key === "whiteList") {
  1738. // Extend the whitelist by concatenating arrays
  1739. xssFilterOptions.whiteList = _this._extendObjectOfArrays([
  1740. _this.arcgisWhiteList,
  1741. filterOptions.whiteList || {},
  1742. ]);
  1743. }
  1744. else {
  1745. xssFilterOptions[key] = filterOptions[key];
  1746. }
  1747. });
  1748. }
  1749. else {
  1750. // Only use the defaults
  1751. xssFilterOptions = Object.create(this.arcgisFilterOptions);
  1752. xssFilterOptions.whiteList = this.arcgisWhiteList;
  1753. }
  1754. this.xssFilterOptions = xssFilterOptions;
  1755. // Make this readable to tests
  1756. this._xssFilter = new lib$1.exports.FilterXSS(xssFilterOptions);
  1757. }
  1758. /**
  1759. * Sanitizes value to remove invalid HTML tags.
  1760. *
  1761. * Note: If the value passed does not contain a valid JSON data type (String,
  1762. * Number, JSON Object, Array, Boolean, or null), the value will be nullified.
  1763. *
  1764. * @param {any} value The value to sanitize.
  1765. * @returns {any} The sanitized value.
  1766. * @memberof Sanitizer
  1767. */
  1768. Sanitizer.prototype.sanitize = function (value, options) {
  1769. if (options === void 0) { options = {}; }
  1770. switch (typeof value) {
  1771. case "number":
  1772. if (isNaN(value) || !isFinite(value)) {
  1773. return null;
  1774. }
  1775. return value;
  1776. case "boolean":
  1777. return value;
  1778. case "string":
  1779. return this._xssFilter.process(value);
  1780. case "object":
  1781. return this._iterateOverObject(value, options);
  1782. default:
  1783. if (options.allowUndefined && typeof value === "undefined") {
  1784. return;
  1785. }
  1786. return null;
  1787. }
  1788. };
  1789. /**
  1790. * Sanitizes a URL string following the allowed protocols and sanitization rules.
  1791. *
  1792. * @param {string} value The URL to sanitize.
  1793. * @param {{ isProtocolRequired: boolean }} options Configuration options for URL checking.
  1794. * @returns {string} The sanitized URL if it's valid, or an empty string if the URL is invalid.
  1795. */
  1796. Sanitizer.prototype.sanitizeUrl = function (value, options) {
  1797. var _a = (options !== null && options !== void 0 ? options : {}).isProtocolRequired, isProtocolRequired = _a === void 0 ? true : _a;
  1798. var protocol = this._trim(value.substring(0, value.indexOf(":")));
  1799. var isRootUrl = value === '/';
  1800. var isUrlFragment = /^#/.test(value);
  1801. var isValidProtocol = protocol && this.allowedProtocols.indexOf(protocol.toLowerCase()) > -1;
  1802. if (isRootUrl || isUrlFragment || isValidProtocol) {
  1803. return lib$1.exports.escapeAttrValue(value);
  1804. }
  1805. if (!protocol && !isProtocolRequired) {
  1806. return lib$1.exports.escapeAttrValue("https://".concat(value));
  1807. }
  1808. return "";
  1809. };
  1810. /**
  1811. * Sanitizes an HTML attribute value.
  1812. *
  1813. * @param {string} tag The tagname of the HTML element.
  1814. * @param {string} attribute The attribute name of the HTML element.
  1815. * @param {string} value The raw value to be used for the HTML attribute value.
  1816. * @param {XSS.ICSSFilter} [cssFilter] The CSS filter to be used.
  1817. * @returns {string} The sanitized attribute value.
  1818. * @memberof Sanitizer
  1819. */
  1820. Sanitizer.prototype.sanitizeHTMLAttribute = function (tag, attribute, value, cssFilter) {
  1821. // use the custom safeAttrValue function if provided
  1822. if (typeof this.xssFilterOptions.safeAttrValue === "function") {
  1823. return this.xssFilterOptions.safeAttrValue(tag, attribute, value,
  1824. // @ts-expect-error safeAttrValue does handle undefined cssFilter
  1825. cssFilter);
  1826. }
  1827. // otherwise use the default
  1828. // @ts-ignore safeAttrValue does handle undefined cssFilter
  1829. return lib$1.exports.safeAttrValue(tag, attribute, value, cssFilter);
  1830. };
  1831. /**
  1832. * Checks if a value only contains valid HTML.
  1833. *
  1834. * @param {any} value The value to validate.
  1835. * @returns {boolean}
  1836. * @memberof Sanitizer
  1837. */
  1838. Sanitizer.prototype.validate = function (value, options) {
  1839. if (options === void 0) { options = {}; }
  1840. var sanitized = this.sanitize(value, options);
  1841. return {
  1842. isValid: value === sanitized,
  1843. sanitized: sanitized,
  1844. };
  1845. };
  1846. /**
  1847. * Encodes the following characters, `& < > \" ' /` to their hexadecimal HTML entity code.
  1848. * Example: "&middot;" => "&#x38;middot;"
  1849. *
  1850. * @param {string} value The value to encode.
  1851. * @returns {string} The encoded string value.
  1852. * @memberof Sanitizer
  1853. */
  1854. Sanitizer.prototype.encodeHTML = function (value) {
  1855. var _this = this;
  1856. return String(value).replace(/[&<>"'\/]/g, function (s) {
  1857. return _this._entityMap[s];
  1858. });
  1859. };
  1860. /**
  1861. * Encodes all non-alphanumeric ASCII characters to their hexadecimal HTML entity codes.
  1862. * Example: "alert(document.cookie)" => "alert&#x28;document&#x2e;cookie&#x29;"
  1863. *
  1864. * @param {string} value The value to encode.
  1865. * @returns {string} The encoded string value.
  1866. * @memberof Sanitizer
  1867. */
  1868. Sanitizer.prototype.encodeAttrValue = function (value) {
  1869. var alphanumericRE = /^[a-zA-Z0-9]$/;
  1870. return String(value).replace(/[\x00-\xFF]/g, function (c, idx) {
  1871. return !alphanumericRE.test(c)
  1872. ? "&#x".concat(Number(value.charCodeAt(idx)).toString(16), ";")
  1873. : c;
  1874. });
  1875. };
  1876. /**
  1877. * Extends an object of arrays by by concatenating arrays of the same object
  1878. * keys. If the if the previous key's value is not an array, the next key's
  1879. * value will replace the previous key. This method is used for extending the
  1880. * whiteList in the XSS filter options.
  1881. *
  1882. * @private
  1883. * @param {Array<{}>} objects An array of objects.
  1884. * @returns {{}} The extended object.
  1885. * @memberof Sanitizer
  1886. */
  1887. Sanitizer.prototype._extendObjectOfArrays = function (objects) {
  1888. var finalObj = {};
  1889. objects.forEach(function (obj) {
  1890. Object.keys(obj).forEach(function (key) {
  1891. if (Array.isArray(obj[key]) && Array.isArray(finalObj[key])) {
  1892. finalObj[key] = finalObj[key].concat(obj[key]);
  1893. }
  1894. else {
  1895. finalObj[key] = obj[key];
  1896. }
  1897. });
  1898. });
  1899. return finalObj;
  1900. };
  1901. /**
  1902. * Iterate over a plain object or array to deeply sanitize each value.
  1903. *
  1904. * @private
  1905. * @param {object} obj The object to iterate over.
  1906. * @returns {(object | null)} The sanitized object.
  1907. * @memberof Sanitizer
  1908. */
  1909. Sanitizer.prototype._iterateOverObject = function (obj, options) {
  1910. var _this = this;
  1911. if (options === void 0) { options = {}; }
  1912. try {
  1913. var hasChanged_1 = false;
  1914. var changedObj = void 0;
  1915. if (Array.isArray(obj)) {
  1916. changedObj = obj.reduce(function (prev, value) {
  1917. var validation = _this.validate(value, options);
  1918. if (validation.isValid) {
  1919. return prev.concat([value]);
  1920. }
  1921. else {
  1922. hasChanged_1 = true;
  1923. return prev.concat([validation.sanitized]);
  1924. }
  1925. }, []);
  1926. }
  1927. else if (!isPlainObject(obj)) {
  1928. if (options.allowUndefined && typeof obj === "undefined") {
  1929. return;
  1930. }
  1931. return null;
  1932. }
  1933. else {
  1934. var keys = Object.keys(obj);
  1935. changedObj = keys.reduce(function (prev, key) {
  1936. var value = obj[key];
  1937. var validation = _this.validate(value, options);
  1938. if (validation.isValid) {
  1939. prev[key] = value;
  1940. }
  1941. else {
  1942. hasChanged_1 = true;
  1943. prev[key] = validation.sanitized;
  1944. }
  1945. return prev;
  1946. }, {});
  1947. }
  1948. if (hasChanged_1) {
  1949. return changedObj;
  1950. }
  1951. return obj;
  1952. }
  1953. catch (err) {
  1954. return null;
  1955. }
  1956. };
  1957. /**
  1958. * Trim whitespace from the start and ends of a string.
  1959. * @param {string} val The string to trim.
  1960. * @returns {string} The trimmed string.
  1961. */
  1962. Sanitizer.prototype._trim = function (val) {
  1963. // @ts-ignore This is used by Jest,
  1964. // but TypeScript errors since it assumes `trim` is always available.
  1965. return String.prototype.trim
  1966. ? val.trim()
  1967. : val.replace(/(^\s*)|(\s*$)/g, "");
  1968. };
  1969. return Sanitizer;
  1970. }());
  1971. return Sanitizer;
  1972. }));