Steps to reproduce: 1. Create StyleSheet.css file containing the following style: p { color: red; } 2. Set the following markup: <telerik:RadWindow ID="RadWindow1" runat="server" VisibleOnPageLoad="true"> <ContentTemplate> <telerik:RadEditor ID="RadEditor1" runat="server"> <CssFiles> <telerik:EditorCssFile Value="StyleSheet.css" /> </CssFiles> <Content> <p>test</p> <p>test</p> </Content> </telerik:RadEditor> </ContentTemplate> </telerik:RadWindow> 3. Make sure RadEditor's EditorCssFile property points to the created StyleSheet.css file Result: The red color is not applied to the paragraphs in the content area. Workaround: <script> (function (utils) { var addStyleSheet = utils.addStyleSheet; utils.addStyleSheet = function (url, doc, id) { if ($telerik.isFirefox) { if (!url) return; doc = doc || document; var link = doc.createElement("link"); link.setAttribute("href", url, 0); link.setAttribute("type", "text/css"); link.setAttribute("rel", "stylesheet", 0); if (id) link.setAttribute("id", id); var headElement = doc.getElementsByTagName("head")[0]; var addSheet = function () { headElement.appendChild(link); }; window.setTimeout(addSheet, 200); } else { addStyleSheet.call(this, url, doc, id); } } })(Telerik.Web.UI.Editor.Utils); </script>
Update:
For securing the RadEditor content and preventing XSS attacks we advise enabling the RemoveScripts, EncodeScripts, StripCssExpressions and StripDomEventAttributes content filters to sanitize the content. For more information please check the following help article and blog post on the matter:
Original message:
It is possible to conduct a successful XSS attack by injecting a specific malicious content in the RadEditor content. This attack targets Internet explorer browsers. It takes advantage of a security vulnerability related to the CSS expression rule in Legacy IE browsers, where arbitrary JavaScript code embedded in the style attribute of a DOM element can be run on the page. There is a workaround that is strongly recommended to be used in order to make such attack attempts unsuccessful. The idea is to strip the expression declaration from the style attribute value of DOM elements in the RadEditor Content. Following is a sample implementation Usage: protected void Page_Load(object sender, EventArgs e) { var sanitizer = new CssExpressionSanitizer(); theEditor.Content = sanitizer.Sanitize(theEditor.Content); } Content of the CssExpressionSanitizer class: public class CssExpressionSanitizer { private static readonly Regex expressionPattern = new Regex(@"<[a-zA-Z0-9]+[^>]*?style=['""]?.*?(?<cssRule>[^;""]+: expression(?<bracket>\())", RegexOptions.Compiled); public string Sanitize(string input) { var matches = expressionPattern.Matches(input); for (int i = matches.Count - 1; i >= 0; i--) { input = SanitizeExpression(input, matches[i]); } return input; } private string SanitizeExpression(string input, Match m) { var cssRuleIndex = m.Groups["cssRule"].Index; var expressionIndex = m.Groups["bracket"].Index; input = StripMatchingBracketsWithContent(input, expressionIndex); input = input.Remove(cssRuleIndex, expressionIndex - cssRuleIndex); if (input[cssRuleIndex] == ';') { input = input.Remove(cssRuleIndex, 1); } return input; } private string StripMatchingBracketsWithContent(string input, int startIndex) { var openBrackets = 0; do { char currentChar = input[startIndex]; if (currentChar == '"' || currentChar == '\'' || currentChar == '/') { //strip within quotation marks making sure brackets appearing in string constructs do not interfere with the counting var parser = new InPairStringParser(currentChar); input = parser.Sanitize(input, startIndex); currentChar = input[startIndex]; } input = input.Remove(startIndex, 1); if (currentChar == '(') openBrackets++; else if (currentChar == ')') openBrackets--; } while (openBrackets > 0 && input.Length > startIndex); return input; } public class InPairStringParser { public InPairStringParser(char pairChar) { this.pattern = new Regex(String.Format("{0}.*?(?<!\\\\){0}", pairChar)); } public string Sanitize(string input, int startIndex) { var subinput = input.Substring(startIndex); return input.Substring(0, startIndex) + pattern.Replace(subinput, "", 1); } private readonly Regex pattern; } }
When using the Flash Manager to add a flash object into the content, causes the HTML mode to be non editable. The following example code is a possible workaround for this behavior: <telerik:RadEditor ID="RadEditor1" runat="server" OnClientModeChange="OnClientModeChange"> </telerik:RadEditor> <script type="text/javascript"> function OnClientModeChange(editor, args) { var $ = $telerik.$, mode = editor.get_mode(), contentAreaElement = editor.get_contentArea(), editorModes = Telerik.Web.UI.EditModes; if (mode === editorModes.Html) { $(contentAreaElement).hide(); } else { $(contentAreaElement).show(); } } </script>
If the user insert an Iframe in the Html mode of RadEditor, switch to Design mode and then switch back to Html mode, the HTML content becomes non-editable. The issue is reproducible in Chrome. Possible workaround: Use the RadEditor control in Div content mode: http://demos.telerik.com/aspnet-ajax/editor/examples/contentareamodediv/defaultcs.aspx
Here is the simplest sample we have managed to isolate this issue to: <iframe id="Iframe1" runat="server" src="http://bing.com"></iframe> <telerik:RadEditor ID="RadEditor1" runat="server"> </telerik:RadEditor> 1. Run this code in Chrome 2. Click anywhere on the page except for the iframe. Please check the attached workaround (chrome_editor_iframe_workaround.js) and add the script to the end of the page. An official fix will be available in the Q3 2014 release.
For the time being you can use either approach: 1) Disable ConvertToXhtml filter: C#: protected void Page_Load(object sender, EventArgs e) { RadEditor1.DisableFilter(EditorFilters.ConvertToXhtml); } ASPX: <telerik:RadEditor ID="RadEditor1" runat="server"> <Content> <p> <h2></h2> <h2></h2> </p> </Content> </telerik:RadEditor> <script type="text/javascript"> Telerik.Web.UI.Editor.NestedElementsFix.prototype._shouldRemoveBlockElement = function (element, elementChanged) { var utils = Telerik.Web.UI.Editor.Utils; if (!elementChanged || !element) return false; if (!/^li|td|th$/.test(element.nodeName) && utils.isNodeEmptyRecursive(element) && !$telerik.$(element).find("ol,ul,table,h1,h2,h3,h4,h5,h6").length) { return true; } return false; } </script>
Steps to reproduce the issue: 1) Run the code below in IE11 2) Set background color to the "some text" cell by right clicking and then selecting cell property through the context menu. 3) Switch to design - there are many nbps's added. ASPX: <telerik:RadEditor ID="RadEditor1" runat="server"> <Content> <table> <tbody> <tr> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> <table> <tbody> <tr> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> </td> <td>some text </td> <td> </td> </tr> <tr> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table> </td> <td> </td> </tr> <tr> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table> </Content> </telerik:RadEditor> For the time being you can place the following JavaScript workaround below the editor's declaration: <script type="text/javascript"> if ($telerik.isIE) { Telerik.Web.UI.Editor.CommandList.SetCellProperties = function (commandName, editor, commandArgs) { var $ECL = Telerik.Web.UI.Editor.CommandList; var argument = $ECL._getTableArgument(editor, 2, false, true); if (!argument) { alert(editor.getLocalizedString("cellwarning")); return false; } $ECL._getDialogArguments(argument, "TABLE", editor, commandName); var previousTable = $ECL._getParentTable(editor); var callbackFunction = $ECL.getCallbackFunction(commandArgs, function (sender, args) { $telerik.$(args.tableToModify).insertAfter(previousTable); $telerik.$(previousTable).remove(); if (args.styleSheetToImport) $telerik.$(args.styleSheetToImport).insertAfter(args.tableToModify); if (args.styleSheetToRemove) $telerik.$(args.styleSheetToRemove).remove(); }); editor.showDialog("TableWizard", argument, callbackFunction); return false; } } </script>
Using an MS Word file with an inline image or an carriage return (<br/>) to paste the content in the editor, the ConvertWordList StripFormatting option removes the <img /> and <br /> elements.
When a link is highlighted in the content, the RadEditor does not seem to recognize it as an anchor element. Due to that the the properties inspection module do not show the expected properties and the Hyperlink Manager do not work also.
Adding some initial, plain text (no HTML <p> tag wraps the text) and e.g., bolding the last word, pressing enter after it removes a white space. The easiest workaround is changing the NewLineMode property to Br. Example: <telerik:RadEditor runat="server" ID="RadEditor1" NewLineMode="Br"> </telerik:RadEditor> More complex solution that will enable you continue using the paragraphs as new lines is by incorporating the following JavaScript code: <telerik:RadEditor runat="server" ID="RadEditor1"> </telerik:RadEditor> <script type="text/javascript"> Telerik.Web.UI.Editor.Utils.trimWhitespaceTextNodes = function () { }; </script> Note that the script should be put right after the RadEditor declaration to ensure that the RadEditor scripts are loaded.
Running the Word formatting tool on a plain HTML text with underline decoration, strips the style formatting. This tool should only affect the specific MS Word markup fetched from pasting.
classes are being applied to <p> when you do a return in the design view, sometimes. This one's a bit harder to explain so I apologize if this get's confusing. If you go into the HTML view and wrap some text in a <div> with a class on it then switch over to the design view and add a return and some more text the editor will add the div class to the paragraph tag, it might also strip out the paragrah line and place it after the closing div. If the content within the <div> is already formatted in <p> tags then the editor behaves properly when you do a return in the design view. See Screencast: http://screencast.com/t/pmcayQrO
Commonly, plain words are listed in a an MS Word document and full stops are added. Pasting such a list in the editor will cause them to appear with upper-alpha type list and no text in the list item. The following code snippet further modifies the convert() method of the ConvertWordLists logic to encode and decode such full stops. You can use it as a temporary workaround to resolve this issue. <telerik:RadEditor runat="server" ID="RadEditor1"></telerik:RadEditor> <script type="text/javascript"> var originalConvert = Telerik.Web.UI.Editor.WordListConverter.prototype.convert; Telerik.Web.UI.Editor.WordListConverter.prototype.convert = function (htmlText) { // Encode the full stops only if they are after words with 2 or more characters. htmlText = htmlText.replace(/(\w{2,})[.]/gim, "$1_TELERIK_DOT_"); htmlText = originalConvert.call(this, htmlText); // Decode the full stops. htmlText = htmlText.replace(/_TELERIK_DOT_/gm, "."); return htmlText; } </script> Make sure that this script block is placed right after the RadEditor declaration, so that the WordListConverter is properly created.
RadEditor Find/Replace functionalities are not working in IE. The following workaround could be used temporarily: <script type="text/javascript"> var $T = Telerik.Web.UI; Telerik.Web.UI.RadEditor.prototype.setActive = function () { if (this._emptyMessageContainer) this._hideEmptyMessage(); if ($telerik.isIE && this.getSelection().isControl()) return; var curArea = this.get_mode() == $T.EditModes.Html ? this._getTextArea() : this.get_contentArea(); if (curArea && curArea.setActive) curArea.setActive(); }; Telerik.Web.UI.RadEditor.prototype.setActiveIfElementIsNotInContent = function () { if (this._emptyMessageContainer) this._hideEmptyMessage(); if ($telerik.isIE && this.getSelection().isControl()) return; var curArea = this.get_mode() == $T.EditModes.Html ? this._getTextArea() : this.get_contentArea(); var activeElement = this.get_document().activeElement; var activeElementIsInContent = (activeElement && activeElement === curArea) || $.contains(curArea, activeElement); if (curArea && curArea.setActive && !activeElementIsInContent) { curArea.setActive(); } }; </script>
The JS error also causes the tool to break, and all table-related tools are not available in RibbonBar mode.
When pasting a list element in the editor via the pasteHtml method, the cursor is positioned in the beginning of the first possible list element. The expected behavior should be to be placed right after the last list item.
Currently, if a paragraph has altered line-height in MS Word, pasting it into the RadEditor results to a normal paragraph with not affection to the line-height CSS property.
A div element is considered as a new line and can be transformed to a list item, although the reverse logic does not work. When NewLineMode is set to Div, the list item is transformed to paragraph instead div element.