Files
Umbraco-CMS/components/editorControls/wysiwyg/editor.cs
Shandem f6d0d043b5 DO NOT DOWNLOAD. DOWNLOAT LATEST STABLE FROM RELEASE TAB
Created 4.1.0 branch

[TFS Changeset #55082]
2009-06-19 07:39:16 +00:00

577 lines
20 KiB
C#

using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using umbraco.BusinessLogic;
using umbraco.interfaces;
using umbraco.uicontrols;
namespace umbraco.editorControls.wysiwyg
{
/// <summary>
/// Generates a field for typing numeric data
/// </summary>
public class editor : HiddenField, IDataFieldWithButtons
{
private ArrayList _buttons = new ArrayList();
private bool _isInitialized = false;
private String _text;
private ArrayList _menuIcons = new ArrayList();
private bool _browserIsCompatible = false;
private cms.businesslogic.datatype.DefaultData _data;
public editor(cms.businesslogic.datatype.DefaultData Data)
{
_data = Data;
if (HttpContext.Current.Request.Browser.Win32 &&
HttpContext.Current.Request.Browser.Browser == "IE")
_browserIsCompatible = true;
}
public virtual bool TreatAsRichTextEditor
{
get { return true; }
}
public bool ShowLabel
{
get { return false; }
}
public Control Editor
{
get { return this; }
}
public String Text
{
get
{
if (_text == null) return "";
HttpContext.Current.Trace.Warn("return text", _text);
return _text;
}
set
{
_text = " " + value + " ";
if (_text.Trim() != "")
{
// Check for umbraco tags
string pattern = @"[^'](<\?UMBRACO_MACRO\W*[^>]*/>)[^']";
MatchCollection tags =
Regex.Matches(_text, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match tag in tags)
{
_text =
_text.Replace(tag.Groups[1].Value,
"<IMG alt='" + tag.Groups[1].Value + "' src=\"/imagesmacroo.gif\">");
}
// Clean urls
// _text = _text.Replace("http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"], "").Replace("HTTP://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"], "");
}
base.Value = _text.Trim();
}
}
public virtual object[] MenuIcons
{
get
{
initButtons();
object[] tempIcons = new object[_menuIcons.Count];
for (int i = 0; i < _menuIcons.Count; i++)
tempIcons[i] = _menuIcons[i];
return tempIcons;
}
}
public override string Value
{
get { return base.Value; }
set
{
base.Value = " " + value + " ";
// Check for umbraco tags
string pattern = @"[^'](<\?UMBRACO_MACRO\W*[^>]*/>)[^']";
MatchCollection tags =
Regex.Matches(base.Value + " ", pattern,
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match tag in tags)
{
base.Value =
base.Value.Replace(tag.Groups[1].Value,
"<IMG alt='" + tag.Groups[1].Value + "' src=\"/imagesmacroo.gif\">");
}
Text = base.Value.Trim();
}
}
private string cleanImages(string html)
{
string[] allowedAttributes = UmbracoSettings.ImageAllowedAttributes.ToLower().Split(',');
string pattern = @"<img [^>]*>";
MatchCollection tags =
Regex.Matches(html + " ", pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match tag in tags)
{
if (tag.Value.ToLower().IndexOf("umbraco_macro") == -1)
{
string cleanTag = "<img";
// gather all attributes
// TODO: This should be replaced with a general helper method - but for now we'll wanna leave umbraco.dll alone for this patch
Hashtable ht = new Hashtable();
MatchCollection m =
Regex.Matches(tag.Value.Replace(">", " >"),
"(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"|(?<attributeName>\\S*)=(?<attributeValue>[^\"|\\s]*)\\s",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match attributeSet in m)
ht.Add(attributeSet.Groups["attributeName"].Value.ToString().ToLower(),
attributeSet.Groups["attributeValue"].Value.ToString());
// Build image tag
foreach (string attr in allowedAttributes)
{
if (helper.FindAttribute(ht, attr) != "")
cleanTag += " " + attr + "=\"" + helper.FindAttribute(ht, attr) + "\"";
}
// If umbracoResizeImage attribute exists we should resize the image!
if (helper.FindAttribute(ht, "umbracoresizeimage") != "")
{
try
{
cleanTag += doResize(ht);
}
catch (Exception err)
{
cleanTag += " src=\"" + helper.FindAttribute(ht, "src") + "\"";
if (helper.FindAttribute(ht, "width") != "")
{
cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\"";
cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\"";
}
Log.Add(LogTypes.Error, User.GetUser(0), -1,
"Error resizing image in editor: " + err.ToString());
}
}
else
{
// Add src, width and height properties
cleanTag += " src=\"" + helper.FindAttribute(ht, "src") + "\"";
if (helper.FindAttribute(ht, "width") != "")
{
cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\"";
cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\"";
}
}
if (bool.Parse(GlobalSettings.EditXhtmlMode))
cleanTag += "/";
cleanTag += ">";
html = html.Replace(tag.Value, cleanTag);
}
}
return html;
}
private string doResize(Hashtable attributes)
{
string resizeDim = helper.FindAttribute(attributes, "umbracoresizeimage");
string[] resizeDimSplit = resizeDim.Split(',');
string orgSrc = helper.FindAttribute(attributes, "src").Replace("%20", " ");
int orgHeight = int.Parse(helper.FindAttribute(attributes, "umbracoorgheight"));
int orgWidth = int.Parse(helper.FindAttribute(attributes, "umbracoorgwidth"));
string beforeWidth = helper.FindAttribute(attributes, "umbracobeforeresizewidth");
string beforeHeight = helper.FindAttribute(attributes, "umbracobeforeresizeheight");
string newSrc = "";
if (orgHeight > 0 && orgWidth > 0 && resizeDim != "" && orgSrc != "")
{
// Check filename
if (beforeHeight != "" && beforeWidth != "")
{
orgSrc = orgSrc.Replace("_" + beforeWidth + "x" + beforeHeight, "");
}
string ext = orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1);
newSrc = orgSrc.Replace("." + ext, "_" + resizeDimSplit[0] + "x" + resizeDimSplit[1] + ".jpg");
string fullSrc = HttpContext.Current.Server.MapPath(orgSrc);
string fullSrcNew = HttpContext.Current.Server.MapPath(newSrc);
// Load original image
System.Drawing.Image image = System.Drawing.Image.FromFile(fullSrc);
// Create new image with best quality settings
Bitmap bp = new Bitmap(int.Parse(resizeDimSplit[0]), int.Parse(resizeDimSplit[1]));
Graphics g = Graphics.FromImage(bp);
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// Copy the old image to the new and resized
Rectangle rect = new Rectangle(0, 0, int.Parse(resizeDimSplit[0]), int.Parse(resizeDimSplit[1]));
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
// Copy metadata
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codec = null;
for (int i = 0; i < codecs.Length; i++)
{
if (codecs[i].MimeType.Equals("image/jpeg"))
codec = codecs[i];
}
// Set compresion ratio to 90%
EncoderParameters ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
// Save the new image
bp.Save(fullSrcNew, codec, ep);
orgSrc = newSrc;
}
return " src=\"" + newSrc + "\" width=\"" + resizeDimSplit[0] + "\" height=\"" + resizeDimSplit[1] + "\"";
}
public void Save()
{
if (Text.Trim() != "")
{
// Parse for servername
if (HttpContext.Current.Request.ServerVariables != null)
{
_text = _text.Replace(helper.GetBaseUrl(HttpContext.Current) + GlobalSettings.Path + "/", "");
_text = _text.Replace(helper.GetBaseUrl(HttpContext.Current), "");
}
// Parse for editing scriptname
string pattern2 = GlobalSettings.Path + "/richTextHolder.aspx?[^#]*#";
MatchCollection tags2 =
Regex.Matches(_text, pattern2, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match tag in tags2)
{
_text = _text.Replace(tag.Value, "");
HttpContext.Current.Trace.Warn("editor-match", tag.Value);
}
// Parse for macros inside images
string pattern = @"<IMG\W*alt='(<?[^>]*>)'[^>]*>";
MatchCollection tags =
Regex.Matches(_text, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match tag in tags)
if (tag.Groups.Count > 0)
{
string umbTag = tag.Groups[1].Value;
// Check for backwards compliance with old macro-tag format (<?UMBRACO_MACRO xxxx> vs. new format with closed tags: <?UMBRACO_MACRO xxxx/>)
if (umbTag.IndexOf("/>") < 0)
umbTag = umbTag.Substring(0, umbTag.Length - 1) + "/>";
_text = _text.Replace(tag.Value, umbTag);
}
// check for image tags
_text = cleanImages(_text);
_text = replaceMacroTags(_text).Trim();
// clean macros and add paragraph element for tidy
bool removeParagraphs = false;
if (_text.Length > 15 && _text.ToLower().Substring(0, 17) == "|||?umbraco_macro")
{
removeParagraphs = true;
_text = "<p>" + _text + "</p>";
}
// tidy html
if (UmbracoSettings.TidyEditorContent)
{
string tidyTxt = library.Tidy(_text, false);
if (tidyTxt != "[error]")
{
// compensate for breaking macro tags by tidy
_text = tidyTxt.Replace("/?>", "/>");
if (removeParagraphs)
{
if (_text.Length - _text.Replace("<", "").Length == 2)
_text = _text.Replace("<p>", "").Replace("</p>", "");
}
}
else
Log.Add(LogTypes.Error, User.GetUser(0), _data.NodeId,
"Error tidying txt from property: " + _data.PropertyId.ToString());
}
// rescue umbraco tags
_text = _text.Replace("|||?", "<?").Replace("/|||", "/>").Replace("|*|", "\"");
// if text is an empty parargraph, make it all empty
if (_text.ToLower() == "<p></p>")
_text = "";
}
// cms.businesslogic.Content.GetContentFromVersion(_version).getProperty(_alias).Value = Text;
_data.Value = Text;
}
private string replaceMacroTags(string text)
{
while (findStartTag(text) > -1)
{
string result = text.Substring(findStartTag(text), findEndTag(text) - findStartTag(text));
text = text.Replace(result, generateMacroTag(result));
}
return text;
}
private string generateMacroTag(string macroContent)
{
string macroAttr = macroContent.Substring(5, macroContent.IndexOf(">") - 5);
string macroTag = "|||?UMBRACO_MACRO ";
Hashtable attributes = ReturnAttributes(macroAttr);
IDictionaryEnumerator ide = attributes.GetEnumerator();
while (ide.MoveNext())
{
if (ide.Key.ToString().IndexOf("umb_") != -1)
macroTag += ide.Key.ToString().Substring(4, ide.Key.ToString().Length - 4) + "=|*|" +
ide.Value.ToString() + "|*| ";
}
macroTag += "/|||";
return macroTag;
}
public static Hashtable ReturnAttributes(String tag)
{
Hashtable ht = new Hashtable();
MatchCollection m =
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match attributeSet in m)
ht.Add(attributeSet.Groups["attributeName"].Value.ToString(),
attributeSet.Groups["attributeValue"].Value.ToString());
return ht;
}
private int findStartTag(string text)
{
string temp = "";
text = text.ToLower();
if (text.IndexOf("ismacro=\"true\"") > -1)
{
temp = text.Substring(0, text.IndexOf("ismacro=\"true\""));
return temp.LastIndexOf("<");
}
return -1;
}
private int findEndTag(string text)
{
string find = "<!-- endumbmacro --></div>";
return text.ToLower().IndexOf("<!-- endumbmacro --></div>") + find.Length;
}
private void initButtons()
{
if (!_isInitialized)
{
_isInitialized = true;
// Test for browser compliance
if (_browserIsCompatible)
{
// Add icons for the editor control:
// Html
// Preview
// Style picker, showstyles
// Bold, italic, Text Gen
// Align: left, center, right
// Lists: Bullet, Ordered, indent, undo indent
// Link, Anchor
// Insert: Image, macro, table, formular
_buttons.Add(
new editorButton("html", ui.Text("buttons", "htmlEdit", null),
GlobalSettings.Path + "/images/editor/html.gif", "viewHTML('" + ClientID + "')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("showstyles", ui.Text("buttons", "styleShow", null) + " (CTRL+SHIFT+V)",
GlobalSettings.Path + "/images/editor/showStyles.gif",
"umbracoShowStyles('" + ClientID + "')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("bold", ui.Text("buttons", "bold", null) + " (CTRL+B)",
GlobalSettings.Path + "/images/editor/bold.gif",
"umbracoEditorCommand('" + ClientID + "', 'bold', '')"));
_buttons.Add(
new editorButton("italic", ui.Text("buttons", "italic", null) + " (CTRL+I)",
GlobalSettings.Path + "/images/editor/italic.gif",
"umbracoEditorCommand('" + ClientID + "', 'italic', '')"));
_buttons.Add(
new editorButton("graphicheadline", ui.Text("buttons", "graphicHeadline", null) + "(CTRL+B)",
GlobalSettings.Path + "/images/editor/umbracoTextGen.gif",
"umbracoTextGen('" + ClientID + "')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("justifyleft", ui.Text("buttons", "justifyLeft", null),
GlobalSettings.Path + "/images/editor/left.gif",
"umbracoEditorCommand('" + ClientID + "', 'justifyleft', '')"));
_buttons.Add(
new editorButton("justifycenter", ui.Text("buttons", "justifyCenter", null),
GlobalSettings.Path + "/images/editor/center.gif",
"umbracoEditorCommand('" + ClientID + "', 'justifycenter', '')"));
_buttons.Add(
new editorButton("justifyright", ui.Text("buttons", "justifyRight", null),
GlobalSettings.Path + "/images/editor/right.gif",
"umbracoEditorCommand('" + ClientID + "', 'justifyright', '')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("listBullet", ui.Text("buttons", "listBullet", null),
GlobalSettings.Path + "/images/editor/bullist.gif",
"umbracoEditorCommand('" + ClientID + "', 'insertUnorderedList', '')"));
_buttons.Add(
new editorButton("listNumeric", ui.Text("buttons", "listNumeric", null),
GlobalSettings.Path + "/images/editor/numlist.gif",
"umbracoEditorCommand('" + ClientID + "', 'insertOrderedList', '')"));
_buttons.Add(
new editorButton("deindent", ui.Text("buttons", "deindent", null),
GlobalSettings.Path + "/images/editor/deindent.gif",
"umbracoEditorCommand('" + ClientID + "', 'Outdent', '')"));
_buttons.Add(
new editorButton("indent", ui.Text("buttons", "indent", null),
GlobalSettings.Path + "/images/editor/inindent.gif",
"umbracoEditorCommand('" + ClientID + "', 'Indent', '')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("linkInsert", ui.Text("buttons", "linkInsert", null),
GlobalSettings.Path + "/images/editor/link.gif",
"umbracoLink('" + ClientID + "')"));
_buttons.Add(
new editorButton("linkLocal", ui.Text("buttons", "linkLocal", null),
GlobalSettings.Path + "/images/editor/anchor.gif",
"umbracoAnchor('" + ClientID + "')"));
_buttons.Add("split");
_buttons.Add(
new editorButton("pictureInsert", ui.Text("buttons", "pictureInsert", null),
GlobalSettings.Path + "/images/editor/image.gif",
"umbracoImage('" + ClientID + "')"));
_buttons.Add(
new editorButton("macroInsert", ui.Text("buttons", "macroInsert", null),
GlobalSettings.Path + "/images/editor/insMacro.gif",
"umbracoInsertMacro('" + ClientID + "', '" + GlobalSettings.Path + "')"));
_buttons.Add(
new editorButton("tableInsert", ui.Text("buttons", "tableInsert", null),
GlobalSettings.Path + "/images/editor/instable.gif",
"umbracoInsertTable('" + ClientID + "', '" + GlobalSettings.Path + "')"));
_buttons.Add(
new editorButton("formFieldInsert", ui.Text("buttons", "formFieldInsert", null),
GlobalSettings.Path + "/images/editor/form.gif",
"umbracoInsertForm('" + ClientID + "', '" + GlobalSettings.Path + "')"));
// add save icon
foreach (object o in _buttons)
{
try
{
MenuIconI menuItem = new MenuIconClass();
editorButton e = (editorButton)o;
menuItem.OnClickCommand = e.onClickCommand;
menuItem.ImageURL = e.imageUrl;
menuItem.AltText = e.alttag;
menuItem.ID = e.id;
_menuIcons.Add(menuItem);
}
catch
{
_menuIcons.Add("|");
}
}
}
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Page.ClientScript.RegisterClientScriptInclude(Page.GetType(), "UMBRACO_EDITOR", GlobalSettings.Path + "/js/editorBarFunctions.js");
}
/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{
if (_browserIsCompatible)
{
base.Render(output);
output.Write("<iframe name=\"" + ClientID + "_holder\" id=\"" + ClientID +
"_holder\" style=\"border: 0px; width: 100%; height: 100%\" frameborder=\"0\" src=\"" +
GlobalSettings.Path + "/richTextHolder.aspx?nodeId=" + _data.NodeId.ToString() +
"&versionId=" + _data.Version.ToString() + "&propertyId=" + _data.PropertyId.ToString() +
"\"></iframe>");
output.Write("<input type=\"hidden\" name=\"" + ClientID + "_source\" value=\"\">");
string strScript = "function umbracoRichTextSave" + ClientID + "() {\nif (document.frames[\"" +
ClientID + "_holder\"].document.getElementById(\"holder\")) document.getElementById(\"" +
ClientID + "\").value = document.frames[\"" + ClientID +
"_holder\"].document.getElementById(\"holder\").innerHTML;\n}" +
"addSaveHandler('umbracoRichTextSave" + ClientID + "();');";
try
{
if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true);
else
Page.ClientScript.RegisterStartupScript(this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true);
}
catch
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true);
}
}
else
{
output.WriteLine("<textarea name=\"" + ClientID + "\" style=\"width: 100%; height: 95%\">" +
HttpContext.Current.Server.HtmlEncode(base.Value.Trim()) +
"</textarea>");
output.WriteLine(
"<p class=\"guiDialogTiny\"><i>(Unfortunately WYSIWYG editing is only useLiveEditing in Internet Explorer on Windows. <a href=\"http://umbraco.org/various/cross-platform.aspx\" target=\"_blank\">More info</a>)</i></p>");
}
}
}
internal class editorButton
{
public string imageUrl;
public string onClickCommand;
public string alttag;
public string id;
public editorButton(string Id, string AltTag, string ImageUrl, string OnClickCommand)
{
id = Id;
alttag = AltTag;
imageUrl = ImageUrl;
onClickCommand = OnClickCommand;
}
}
}