|
42 | 42 | // it up and apply the filter.
|
43 | 43 | data = protectSource( data, editor );
|
44 | 44 |
|
| 45 | + // Protect content of textareas. (#9995) |
| 46 | + // Do this before protecting attributes to avoid breaking: |
| 47 | + // <textarea><img src="..." /></textarea> |
| 48 | + data = protectElements( data, protectTextareaRegex ); |
| 49 | + |
45 | 50 | // Before anything, we must protect the URL attributes as the
|
46 | 51 | // browser may changing them when setting the innerHTML later in
|
47 | 52 | // the code.
|
48 | 53 | data = protectAttributes( data );
|
49 | 54 |
|
50 | 55 | // Protect elements than can't be set inside a DIV. E.g. IE removes
|
51 | 56 | // style tags from innerHTML. (#3710)
|
52 |
| - data = protectElements( data ); |
| 57 | + data = protectElements( data, protectElementsRegex ); |
53 | 58 |
|
54 | 59 | // Certain elements has problem to go through DOM operation, protect
|
55 | 60 | // them by prefixing 'cke' namespace. (#3591)
|
|
646 | 651 | break;
|
647 | 652 | }
|
648 | 653 | }
|
649 |
| - // Disable form elements editing mode provided by some browers. (#5746) |
| 654 | + // Disable form elements editing mode provided by some browsers. (#5746) |
650 | 655 | for ( var i in { input:1,textarea:1 } ) {
|
651 | 656 | defaultDataFilterRules.elements[ i ] = protectReadOnly;
|
652 | 657 | defaultHtmlFilterRules.elements[ i ] = unprotectReadyOnly;
|
|
655 | 660 | var protectElementRegex = /<(a|area|img|input|source)\b([^>]*)>/gi,
|
656 | 661 | protectAttributeRegex = /\b(on\w+|href|src|name)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi;
|
657 | 662 |
|
658 |
| - var protectElementsRegex = /(?:<style(?=[ >])[^>]*>[\s\S]*<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi, |
| 663 | + // Note: we use lazy star '*?' to prevent eating everything up to the last occurrence of </style> or </textarea>. |
| 664 | + var protectElementsRegex = /(?:<style(?=[ >])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi, |
| 665 | + protectTextareaRegex = /(<textarea(?=[ >])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi, |
659 | 666 | encodedElementsRegex = /<cke:encoded>([^<]*)<\/cke:encoded>/gi;
|
660 | 667 |
|
661 | 668 | var protectElementNamesRegex = /(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,
|
|
676 | 683 | });
|
677 | 684 | }
|
678 | 685 |
|
679 |
| - function protectElements( html ) { |
680 |
| - return html.replace( protectElementsRegex, function( match ) { |
| 686 | + function protectElements( html, regex ) { |
| 687 | + return html.replace( regex, function( match, tag, content ) { |
| 688 | + // Encode < and > in textarea because this won't be done by a browser, since |
| 689 | + // textarea will be protected during passing data through fix bin. |
| 690 | + if ( match.indexOf( '<textarea' ) == 0 ) |
| 691 | + match = tag + unprotectRealComments( content ).replace( /</g, '<' ).replace( />/g, '>' ) + '</textarea>'; |
| 692 | + |
681 | 693 | return '<cke:encoded>' + encodeURIComponent( match ) + '</cke:encoded>';
|
682 | 694 | });
|
683 | 695 | }
|
|
0 commit comments