using System; using System.Collections; using System.Collections.Specialized; using System.Text.RegularExpressions; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.macro; using umbraco.cms.businesslogic.media; using umbraco.cms.businesslogic.property; using Content = umbraco.cms.businesslogic.Content; namespace umbraco.editorControls.tinymce.webcontrol { public class TinyMCE : WebControl, IPostBackDataHandler { private string _javascriptLocation = GlobalSettings.ClientPath + "/tinymce"; private string _coreFile = "/tiny_mce.js"; private int _rows = 13; private int _cols = 60; public NameValueCollection config; private string temp; private int _nodeId = -1; private Guid _versionId; public int NodeId { set { _nodeId = value; } } public Guid VersionId { set { _versionId = value; } } public string CoreFile { get { return _coreFile; } } public TinyMCE() { config = new NameValueCollection(); config.Add("mode", "exact"); config.Add("theme", "advanced"); //content_css : "/mycontent.css" temp = string.Empty; //this._config.SetStringParam(TinyMCEConfig.StringParameter.mode, "exact"); //this._config.SetStringParam(TinyMCEConfig.StringParameter.theme, "advanced"); //this._config.SetStringParam(TinyMCEConfig.StringParameter.plugins, "advlink,noneditable,advimage,flash"); //this._config.SetStringParam(TinyMCEConfig.StringParameter.theme_advanced_buttons3_add, "flash"); } // /// The text of the editor /// public string Text { get { return (string)ViewState["text"]; } set { ViewState["text"] = value; } } // /// The number of rows in the textarea that gets converted to the editor. /// This affects the size of the editor. Default is 10 /// public int Rows { get { return _rows; } set { _rows = value; } } // /// The number of columns in the textarea that gets converted to the editor. /// This affects the size of the editor. Default is 40. /// public int Cols { get { return _cols; } set { _cols = value; } } // /// Path to the TinyMCE javascript, default is "jscripts/tiny_mce/tiny_mce.js" /// public string JavascriptLocation { get { return _javascriptLocation; } set { _javascriptLocation = value; } } /// /// Draws the editor /// /// The writer to draw the editor to protected override void Render(HtmlTextWriter writer) { writer.WriteLine("\n"); writer.WriteLine("\n"); writer.WriteLine("\n"); if (Cols > 0) writer.Write(""); } private string formatMedia(string html) { // Local media path string localMediaPath = getLocalMediaPath(); // Find all media images string pattern = "]*src=\"(?/media[^\"]*)\" [^>]*>"; MatchCollection tags = Regex.Matches(html, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); foreach (Match tag in tags) if (tag.Groups.Count > 0) { // Replace /> to ensure we're in old-school html mode string tempTag = "", " >"), "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); foreach (Match attributeSet in m) { if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() != "src") ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), attributeSet.Groups["attributeValue"].Value.ToString()); } // build the element // Build image tag IDictionaryEnumerator ide = ht.GetEnumerator(); while (ide.MoveNext()) tempTag += " " + ide.Key.ToString() + "=\"" + ide.Value.ToString() + "\""; // Find the original filename, by removing the might added width and height orgSrc = orgSrc.Replace( "_" + helper.FindAttribute(ht, "width") + "x" + helper.FindAttribute(ht, "height"), ""). Replace("%20", " "); // Check for either id or guid from media string mediaId = getIdFromSource(orgSrc, localMediaPath); Media imageMedia = null; try { int mId = int.Parse(mediaId); Property p = new Property(mId); imageMedia = new Media(Content.GetContentFromVersion(p.VersionId).Id); } catch { try { imageMedia = new Media(Content.GetContentFromVersion(new Guid(mediaId)).Id); } catch { } } // Check with the database if any media matches this url if (imageMedia != null) { try { // Check extention if (imageMedia.getProperty("umbracoExtension").Value.ToString() != orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1)) orgSrc = orgSrc.Substring(0, orgSrc.LastIndexOf(".") + 1) + imageMedia.getProperty("umbracoExtension").Value.ToString(); // Format the tag tempTag = tempTag + " rel=\"" + imageMedia.getProperty("umbracoWidth").Value.ToString() + "," + imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + orgSrc + "\""; tempTag += "/>"; // Replace the tag html = html.Replace(tag.Value, tempTag); } catch (Exception ee) { Log.Add(LogTypes.Error, User.GetUser(0), -1, "Error reading size data from media: " + imageMedia.Id.ToString() + ", " + ee.ToString()); } } else Log.Add(LogTypes.Error, User.GetUser(0), -1, "Error reading size data from media (not found): " + orgSrc); } return html; } private string getIdFromSource(string src, string localMediaPath) { // important - remove out the umbraco path + media! src = src.Replace(localMediaPath, ""); string _id = ""; // Check for directory id naming if (src.Length - src.Replace("/", "").Length > 0) { string[] dirSplit = src.Split("/".ToCharArray()); string tempId = dirSplit[0]; try { // id _id = int.Parse(tempId).ToString(); } catch { // guid _id = tempId; } } else { string[] fileSplit = src.Replace("/media/", "").Split("-".ToCharArray()); // guid or id if (fileSplit.Length > 3) { for (int i = 0; i < 5; i++) _id += fileSplit[i] + "-"; _id = _id.Substring(0, _id.Length - 1); } else _id = fileSplit[0]; } return _id; } private string getLocalMediaPath() { string[] umbracoPathSplit = GlobalSettings.Path.Split("/".ToCharArray()); string umbracoPath = ""; for (int i = 0; i < umbracoPathSplit.Length - 1; i++) umbracoPath += umbracoPathSplit[i] + "/"; return umbracoPath + "media/"; } private string parseMacrosToHtml(string input) { int nodeId = _nodeId; Guid versionId = _versionId; string content = input; string pattern = @"(<\?UMBRACO_MACRO\W*[^>]*/>)"; MatchCollection tags = Regex.Matches(content, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); // Page for macro rendering page p = new page(nodeId, versionId); HttpContext.Current.Items["macrosAdded"] = 0; HttpContext.Current.Items["pageID"] = nodeId.ToString(); foreach (Match tag in tags) { try { // Create div Hashtable attributes = helper.ReturnAttributes(tag.Groups[1].Value); string div = macro.renderMacroStartTag(attributes, nodeId, versionId).Replace(""", "&quot;"); // Insert macro contents here... macro m; if (helper.FindAttribute(attributes, "macroID") != "") m = new macro(int.Parse(helper.FindAttribute(attributes, "macroID"))); else { // legacy: Check if the macroAlias is typed in lowercasing string macroAlias = helper.FindAttribute(attributes, "macroAlias"); if (macroAlias == "") { macroAlias = helper.FindAttribute(attributes, "macroalias"); attributes.Remove("macroalias"); attributes.Add("macroAlias", macroAlias); } if (macroAlias != "") m = new macro(Macro.GetByAlias(macroAlias).Id); else throw new ArgumentException("umbraco is unable to identify the macro. No id or macroalias was provided for the macro in the macro tag.", tag.Groups[1].Value); } if (helper.FindAttribute(attributes, "macroAlias") == "") attributes.Add("macroAlias", m.Alias); try { div += macro.MacroContentByHttp(nodeId, versionId, attributes); } catch { div += "No macro content available for WYSIWYG editing"; } div += macro.renderMacroEndTag(); content = content.Replace(tag.Groups[1].Value, div); } catch (Exception ee) { Log.Add(LogTypes.Error, this._nodeId, "Macro Parsing Error: " + ee.ToString()); string div = "

umbraco was unable to parse a macro tag, which means that parts of this content might be corrupt.

Best solution is to rollback to a previous version by right clicking the node in the tree and then try to insert the macro again.

Please report this to your system administrator as well - this error has been logged.

"; content = content.Replace(tag.Groups[1].Value, div); } } return content; } private static readonly object TextChangedEvent = new object(); /// /// Raises an event when the text in the editor changes. /// public event EventHandler TextChanged { add { Events.AddHandler(TextChangedEvent, value); } remove { Events.RemoveHandler(TextChangedEvent, value); } } /// /// Event for text change. /// /// protected virtual void OnTextChanged(EventArgs e) { if (Events != null) { EventHandler oEventHandler = (EventHandler)Events[TextChangedEvent]; if (oEventHandler != null) { oEventHandler(this, e); } } } /// /// Called when a postback occurs on the page the control is placed at /// /// The key of the editor data /// All the posted data /// bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { string newText = postCollection[postDataKey]; if (newText != Text) { Text = newText; return true; } return false; } /// /// Raises an event when postback occurs /// void IPostBackDataHandler.RaisePostDataChangedEvent() { OnTextChanged(EventArgs.Empty); } } public enum TinyMceButtons { code, bold, italic, underline, strikethrough, justifyleft, justifycenter, justifyright, justifyfull, bullist, numlist, outdent, indent, cut, copy, pasteword, undo, redo, link, unlink, image, table, hr, removeformat, sub, sup, charmap, anchor, umbracomacro } }