@@ -40,160 +40,166 @@ interface HtmlEscapedMessage {
40
40
} )
41
41
export class HtmlEscapeService {
42
42
escapeDangerousHtml ( html : string ) : EscapeOutput {
43
- const config = {
44
- WHOLE_DOCUMENT : true ,
45
- ALLOWED_TAGS : [
46
- 'a' ,
47
- 'article' ,
48
- 'aside' ,
49
- 'b' ,
50
- 'blockquote' ,
51
- 'br' ,
52
- 'button' ,
53
- 'caption' ,
54
- 'center' ,
55
- 'cite' ,
56
- 'decorator' ,
57
- 'del' ,
58
- 'details' ,
59
- 'div' ,
60
- 'em' ,
61
- 'footer' ,
62
- 'h1' ,
63
- 'h2' ,
64
- 'h3' ,
65
- 'h4' ,
66
- 'h5' ,
67
- 'h6' ,
68
- 'header' ,
69
- 'i' ,
70
- 'img' ,
71
- 'kbd' ,
72
- 'label' ,
73
- 'li' ,
74
- 'ol' ,
75
- 'p' ,
76
- 'pre' ,
77
- 'section' ,
78
- 'select' ,
79
- 'span' ,
80
- 'strong' ,
81
- 'sup' ,
82
- 'table' ,
83
- 'tbody' ,
84
- 'td' ,
85
- 'textarea' ,
86
- 'tfoot' ,
87
- 'th' ,
88
- 'thead' ,
89
- 'tr' ,
90
- 'ul' ,
91
- ] ,
92
- ALLOWED_ATTR : [
93
- 'align' ,
94
- 'class' ,
95
- 'color' ,
96
- 'disabled' ,
97
- 'height' ,
98
- 'hidden' ,
99
- 'href' ,
100
- 'id' ,
101
- 'label' ,
102
- 'size' ,
103
- 'span' ,
104
- 'src' ,
105
- 'srcset' ,
106
- 'style' ,
107
- 'width' ,
108
- ] ,
109
- ALLOWED_STYLE_PROPS : [
110
- 'color' ,
111
- 'background-color' ,
112
- 'font-size' ,
113
- 'font-family' ,
114
- 'text-align' ,
115
- 'margin' ,
116
- 'padding' ,
117
- 'border' ,
118
- 'width' ,
119
- 'height' ,
120
- 'display' ,
121
- 'position' ,
122
- 'top' ,
123
- 'bottom' ,
124
- 'left' ,
125
- 'right' ,
126
- 'overflow' ,
127
- 'float' ,
128
- 'clear' ,
129
- 'z-index' ,
130
- ] ,
131
- } ;
132
-
133
- const removedTags : string [ ] = [ ] ;
134
- const removedAttributes : AttributeOut [ ] = [ ] ;
135
- const removedStyles : StyleRemoved [ ] = [ ] ;
136
- // Sanitize CSS properties (DOMPurify does not support sanitizing of style properties)
137
- addHook ( 'uponSanitizeAttribute' , ( _currentNode , data ) => {
138
- if ( data . attrName !== 'style' ) return ;
139
-
140
- const props = data . attrValue
141
- . split ( ';' )
142
- . map ( ( el ) => el . trim ( ) )
143
- . filter ( ( el ) => el . length > 0 ) ;
144
- for ( let i = 0 ; i < props . length ; i ++ ) {
145
- const prop = props [ i ] ;
146
- let [ name , value ] = prop . split ( ':' ) ;
147
- if ( name === undefined || value === undefined ) continue ;
148
- name = name . trim ( ) ;
149
- value = value . trim ( ) ;
150
-
151
- if ( ! config . ALLOWED_STYLE_PROPS . includes ( name ) ) {
152
- const tagName = _currentNode . localName ;
153
-
154
- removed . push ( {
155
- style : name ,
156
- tag : tagName ,
157
- } ) ;
158
- props [ i ] = '' ;
159
- continue ;
160
- }
161
- props [ i ] = `${ name } :${ value } ;` ;
162
- }
163
- data . attrValue = props . filter ( ( el ) => el . length > 0 ) . join ( ' ' ) ;
164
- } ) ;
165
-
166
- const sanitized = sanitize ( html , config ) ;
167
- // Hacky way to get the sanitized HTML and removed elements
168
- const d = document . createElement ( 'html' ) ;
169
- d . innerHTML = sanitized ;
170
- html = d . getElementsByTagName ( 'body' ) [ 0 ] . innerHTML ;
171
-
172
- for ( const el of removed ) {
173
- if ( 'element' in el ) {
174
- const e = el as ElementRemoved ;
175
- removedTags . push ( e . element . localName ) ;
176
- } else if ( 'attribute' in el ) {
177
- const e = el as AttributeRemoved ;
178
- removedAttributes . push ( {
179
- attribute : e . attribute . localName ,
180
- tag : e . from . localName ,
181
- } ) ;
182
- } else if ( 'style' in el ) {
183
- const e = el as StyleRemoved ;
184
- removedStyles . push ( {
185
- style : e . style ,
186
- tag : e . tag ,
187
- } ) ;
188
- }
189
- }
190
-
191
43
return {
192
44
escapedHtml : html ,
193
- removedTags : removedTags ,
194
- removedAttrs : removedAttributes ,
195
- removedStyleProps : removedStyles ,
45
+ removedTags : [ ] ,
46
+ removedAttrs : [ ] ,
47
+ removedStyleProps : [ ] ,
196
48
} ;
49
+ // const config = {
50
+ // WHOLE_DOCUMENT: true,
51
+ // ALLOWED_TAGS: [
52
+ // 'a',
53
+ // 'article',
54
+ // 'aside',
55
+ // 'b',
56
+ // 'blockquote',
57
+ // 'br',
58
+ // 'button',
59
+ // 'caption',
60
+ // 'center',
61
+ // 'cite',
62
+ // 'decorator',
63
+ // 'del',
64
+ // 'details',
65
+ // 'div',
66
+ // 'em',
67
+ // 'footer',
68
+ // 'h1',
69
+ // 'h2',
70
+ // 'h3',
71
+ // 'h4',
72
+ // 'h5',
73
+ // 'h6',
74
+ // 'header',
75
+ // 'i',
76
+ // 'img',
77
+ // 'kbd',
78
+ // 'label',
79
+ // 'li',
80
+ // 'ol',
81
+ // 'p',
82
+ // 'pre',
83
+ // 'section',
84
+ // 'select',
85
+ // 'span',
86
+ // 'strong',
87
+ // 'sup',
88
+ // 'table',
89
+ // 'tbody',
90
+ // 'td',
91
+ // 'textarea',
92
+ // 'tfoot',
93
+ // 'th',
94
+ // 'thead',
95
+ // 'tr',
96
+ // 'ul',
97
+ // ],
98
+ // ALLOWED_ATTR: [
99
+ // 'align',
100
+ // 'class',
101
+ // 'color',
102
+ // 'disabled',
103
+ // 'height',
104
+ // 'hidden',
105
+ // 'href',
106
+ // 'id',
107
+ // 'label',
108
+ // 'size',
109
+ // 'span',
110
+ // 'src',
111
+ // 'srcset',
112
+ // 'style',
113
+ // 'width',
114
+ // ],
115
+ // ALLOWED_STYLE_PROPS: [
116
+ // 'color',
117
+ // 'background-color',
118
+ // 'font-size',
119
+ // 'font-family',
120
+ // 'text-align',
121
+ // 'margin',
122
+ // 'padding',
123
+ // 'border',
124
+ // 'width',
125
+ // 'height',
126
+ // 'display',
127
+ // 'position',
128
+ // 'top',
129
+ // 'bottom',
130
+ // 'left',
131
+ // 'right',
132
+ // 'overflow',
133
+ // 'float',
134
+ // 'clear',
135
+ // 'z-index',
136
+ // ],
137
+ // };
138
+ //
139
+ // const removedTags: string[] = [];
140
+ // const removedAttributes: AttributeOut[] = [];
141
+ // const removedStyles: StyleRemoved[] = [];
142
+ // // Sanitize CSS properties (DOMPurify does not support sanitizing of style properties)
143
+ // addHook('uponSanitizeAttribute', (_currentNode, data) => {
144
+ // if (data.attrName !== 'style') return;
145
+ //
146
+ // const props = data.attrValue
147
+ // .split(';')
148
+ // .map((el) => el.trim())
149
+ // .filter((el) => el.length > 0);
150
+ // for (let i = 0; i < props.length; i++) {
151
+ // const prop = props[i];
152
+ // let [name, value] = prop.split(':');
153
+ // if (name === undefined || value === undefined) continue;
154
+ // name = name.trim();
155
+ // value = value.trim();
156
+ //
157
+ // if (!config.ALLOWED_STYLE_PROPS.includes(name)) {
158
+ // const tagName = _currentNode.localName;
159
+ //
160
+ // removed.push({
161
+ // style: name,
162
+ // tag: tagName,
163
+ // });
164
+ // props[i] = '';
165
+ // continue;
166
+ // }
167
+ // props[i] = `${name}:${value};`;
168
+ // }
169
+ // data.attrValue = props.filter((el) => el.length > 0).join(' ');
170
+ // });
171
+ //
172
+ // const sanitized = sanitize(html, config);
173
+ // // Hacky way to get the sanitized HTML and removed elements
174
+ // const d = document.createElement('html');
175
+ // d.innerHTML = sanitized;
176
+ // html = d.getElementsByTagName('body')[0].innerHTML;
177
+ //
178
+ // for (const el of removed) {
179
+ // if ('element' in el) {
180
+ // const e = el as ElementRemoved;
181
+ // removedTags.push(e.element.localName);
182
+ // } else if ('attribute' in el) {
183
+ // const e = el as AttributeRemoved;
184
+ // removedAttributes.push({
185
+ // attribute: e.attribute.localName,
186
+ // tag: e.from.localName,
187
+ // });
188
+ // } else if ('style' in el) {
189
+ // const e = el as StyleRemoved;
190
+ // removedStyles.push({
191
+ // style: e.style,
192
+ // tag: e.tag,
193
+ // });
194
+ // }
195
+ // }
196
+ //
197
+ // return {
198
+ // escapedHtml: html,
199
+ // removedTags: removedTags,
200
+ // removedAttrs: removedAttributes,
201
+ // removedStyleProps: removedStyles,
202
+ // };
197
203
}
198
204
199
205
generateErrorTooltip ( errors : EscapeOutput ) : string {
0 commit comments