Skip to content

Commit f35bd1f

Browse files
committed
Merge branch 't/10089' into major
2 parents 3ba4d62 + da3e31d commit f35bd1f

File tree

1 file changed

+56
-7
lines changed

1 file changed

+56
-7
lines changed

core/filter.js

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,20 +198,31 @@
198198
var toBeRemoved = [],
199199
rules = this._.rules,
200200
transformations = this._.transformations,
201-
filterFn = getFilterFunction( this );
201+
filterFn = getFilterFunction( this ),
202+
protectedRegexs = this.editor && this.editor.config.protectedSource;
202203

203204
// Filter all children, skip root (fragment or editable-like wrapper used by data processor).
204205
fragment.forEach( function( el ) {
205-
filterFn( el, rules, transformations, toBeRemoved, toHtml );
206-
}, CKEDITOR.NODE_ELEMENT, true );
206+
if ( el.type == CKEDITOR.NODE_ELEMENT )
207+
filterFn( el, rules, transformations, toBeRemoved, toHtml );
208+
else if ( el.type == CKEDITOR.NODE_COMMENT && el.value.match( /^{cke_protected}(?!{C})/ ) ) {
209+
if ( !filterProtectedElement( el, protectedRegexs, filterFn, rules, transformations, toHtml ) )
210+
toBeRemoved.push( el );
211+
}
212+
}, null, true );
207213

208-
var element, check,
214+
var node, element, check,
209215
toBeChecked = [],
210216
enterTag = [ 'p', 'br', 'div' ][ this.enterMode - 1 ];
211217

212218
// Remove elements in reverse order - from leaves to root, to avoid conflicts.
213-
while ( ( element = toBeRemoved.pop() ) )
214-
removeElement( element, enterTag, toBeChecked );
219+
while ( ( node = toBeRemoved.pop() ) ) {
220+
if ( node.type == CKEDITOR.NODE_ELEMENT )
221+
removeElement( node, enterTag, toBeChecked );
222+
// This is a comment securing rejected element - remove it completely.
223+
else
224+
node.remove();
225+
}
215226

216227
// Check elements that have been marked as possibly invalid.
217228
while ( ( check = toBeChecked.pop() ) ) {
@@ -661,6 +672,36 @@
661672
return props;
662673
}
663674

675+
// Filter element protected with a comment.
676+
// Returns true if protected content is ok, false otherwise.
677+
function filterProtectedElement( comment, protectedRegexs, filterFn, rules, transformations, toHtml ) {
678+
var source = decodeURIComponent( comment.value.replace( /^{cke_protected}/, '' ) ),
679+
protectedFrag,
680+
toBeRemoved = [],
681+
node, i, match;
682+
683+
// Protected element's and protected source's comments look exactly the same.
684+
// Check if what we have isn't a protected source instead of protected script/noscript.
685+
if ( protectedRegexs ) {
686+
for ( i = 0; i < protectedRegexs.length; ++i ) {
687+
if ( ( match = source.match( protectedRegexs[ i ] ) ) &&
688+
match[ 0 ].length == source.length // Check whether this pattern matches entire source
689+
// to avoid '<script>alert("<? 1 ?>")</script>' matching
690+
// the PHP's protectedSource regexp.
691+
)
692+
return true;
693+
}
694+
}
695+
696+
protectedFrag = CKEDITOR.htmlParser.fragment.fromHtml( source );
697+
698+
if ( protectedFrag.children.length == 1 && ( node = protectedFrag.children[ 0 ] ).type == CKEDITOR.NODE_ELEMENT )
699+
filterFn( node, rules, transformations, toBeRemoved, toHtml );
700+
701+
// If protected element has been marked to be removed, return 'false' - comment was rejected.
702+
return !toBeRemoved.length;
703+
}
704+
664705
// Returns function that accepts {@link CKEDITOR.htmlParser.element}
665706
// and filters it basing on allowed content rules registered by
666707
// {@link #allow} method.
@@ -1197,11 +1238,19 @@
11971238

11981239
element.remove();
11991240
}
1200-
} else if ( DTD.$block[ name ] || name == 'tr' )
1241+
} else if ( DTD.$block[ name ] || name == 'tr' ) {
12011242
if ( enterTag == 'br' )
12021243
stripBlockBr( element, toBeChecked );
12031244
else
12041245
stripBlock( element, enterTag, toBeChecked );
1246+
}
1247+
// Special case - elements that may contain CDATA
1248+
// should be removed completely. <script> is handled
1249+
// by filterProtectedElement().
1250+
else if ( name == 'style' )
1251+
element.remove();
1252+
// The rest of inline elements. May also be the last resort
1253+
// for some special elements.
12051254
else {
12061255
// Parent might become an empty inline specified in $removeEmpty or empty a[href].
12071256
if ( element.parent )

0 commit comments

Comments
 (0)