Tuesday, 28 August 2012

And... one for the road...

Media Picker not found:
System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/dialogs/treepicker.aspx
Replace treepicker.aspx with treePicker.aspx

Monday, 27 August 2012

XPathNodeIterator MoveNext() issue, and more Razor

Upon trying to save a file under Scripting Files, you get 'Scripting file could not be saved'
But the file is saved,
And, there is an extra temporary script file left behind.
This does not happen when 'skip file testing' is checked.
Error occurs in SaveDLRScript(codeEditorSave.asmx.cs 291) and new Node(id) yields null, and breaks things.


This highlights another mono subtlety: in mono, usage for an XPathNodeIterator is:
('MoveNext' issue)


			XPathNodeIterator iter = Select (expression);
if (iter.MoveNext ())
return iter.Current;
else
return null;

Where the return type is 'XPathNavigator'. We need to update this for all relevant cases in umbraco.
This is because initially the XpathNodeIterator's Position is at '0', and the 'Current' property is always at null.


And, therefore any immediate reference to iter.Current is always null.


First add a function to .../umbraco/businesslogic/xmlHelper.cs:


		//this is very mono specific at the moment
public static XmlNode GetCurrentNodeFromIterator(XPathNodeIterator xpi)
{
if (xpi != null)
{
if (xpi.MoveNext())
return ((IHasXmlNode)xpi.Current).GetNode();
}

return null;
}

Next use the following examples for the replacement.
** Loading razor script into rich text editor yields (insert macro):
'Error loading MacroEngine script (file: TestRazorSiteMap.cshtml)'
So, in .../umbraco/presentation/umbraco/nodeFactory/Page.cs replace, line 593,


 
XmlNode n = ((IHasXmlNode)library.GetXmlNodeCurrent().Current).GetNode();
with
XmlNode n = xmlHelper.GetCurrentNodeFromIterator(library.GetXmlNodeCurrent());

** Above saveDLRScript error. So, in .../umbraco/presentation/umbraco/nodeFactory/Page.cs replace, line 298,


 _pageXmlNode = ((IHasXmlNode)library.GetXmlNodeById(NodeId.ToString()).Current).GetNode();		
with
_pageXmlNode = xmlHelper.GetCurrentNodeFromIterator(library.GetXmlNodeById(NodeId.ToString()));

** Total Changes: 14
p.aspx.cs, 42, 46
library.cs, 96, 1207, 1266, 1340
baseHttpModule.cs, 182
UmbracoPage.cs, 22
Page_Legacy.cs, 219, 269, 510
Page.cs, 247, 298, 591


** RAZOR RELATED: **


ExamineBackedMedia.cs
48:51, from,
var media = umbraco.library.GetMedia(id, true);
if (media != null && media.Current != null)
{
media.MoveNext();
return new ExamineBackedMedia(media.Current);
}
to
XPathNodeIterator media = umbraco.library.GetMedia(id, true);
if (media != null)
{
if (media.MoveNext())
return new ExamineBackedMedia(media.Current);
}
Note: we need to type media, otherwise 'MoveNext()' will return false.

62:76, from,
XPathNodeIterator result = xpath.SelectChildren(XPathNodeType.Element);
//add the attributes e.g. id, parentId etc
if (result.Current.HasAttributes)
{
if (result.Current.MoveToFirstAttribute())
{
Values.Add(result.Current.Name, result.Current.Value);
while (result.Current.MoveToNextAttribute())
{
Values.Add(result.Current.Name, result.Current.Value);
}
result.Current.MoveToParent();
}
}
while (result.MoveNext())
to
XPathNodeIterator xpi = xpath.Select(".");
//add the attributes e.g. id, parentId etc
if (xpi.MoveNext())
if (xpi.Current.HasAttributes)
{
if (xpi.Current.MoveToFirstAttribute())
{
Values.Add(xpi.Current.Name, xpi.Current.Value);
while (xpi.Current.MoveToNextAttribute())
{
Values.Add(xpi.Current.Name, xpi.Current.Value);
}
}
}
XPathNodeIterator result = xpath.SelectChildren(XPathNodeType.Element);
while (result.MoveNext())

108:110, from, 
if (media != null && media.Current != null)
{
media.MoveNext();
XPathNavigator xpath = media.Current;
to
if (media != null && media.MoveNext())
{
XPathNavigator xpath = media.Current;

370:373, from,
if (media != null && media.Current != null)
{
media.MoveNext();
var children = media.Current.SelectChildren(XPathNodeType.Element);
to
if (media != null && media.MoveNext())
{
var children = media.Current.SelectChildren(XPathNodeType.Element);


                               
DynamicXml.cs, 31:33
from,
if (xpni.Current != null)
{
var xml = xpni.Current.OuterXml;
to
if (xpni.MoveNext())
{
var xml = xpni.Current.OuterXml;

Sunday, 26 August 2012

Adding Razor Support


RAZOR: Earlier this year, Microsoft made ASP.NET MVC, Web API, and Razor open source, and this source is now also used by mono. However, since we are using the .NET4 implementation, we still need the original MS dlls. Make sure the following dlls are in the bin folder of .../umbraco/presentation/bin (and in the bin folder of the binary app distro)
External: System.Web.Razor.dll, System.Web.WebPages.dll, System.Web.WebPages.Razor.dll, Microsoft.Web.Helpers.dll .NET 4 versions Umbraco: From the folder, umbraco.MacroEngines.dll (mono develop will not set a refernce to this to avoid circular references, so you can copy it manually or add a post build step)


Note: If you do not have the 4 external, and umbraco macro dll's in the bin folder, you will get a variety of errors:
No umbraco.MacroEngines.dll - language selection is create script dialog is empty
No Syste.Web.Razor, System.Web.WebPages, Sysem.Web.WebPages.Razor - error language extension file is not recognised
No Microsoft.Web.Helpers - File build failed message (due to CS0234: The type or namespace name `Web' does not exist in the namespace `Microsoft'), this error will only report after applying the 'MoveNext' fix below.


Adding Razor to Scripting:
To .../umbraco/presentation/config/umbracoSettings.config,
after the developer section, add


<scripting>
<razor>
<!-- razor DynamicNode typecasting detects XML and returns DynamicXml - Root elements that won't convert to DynamicXml -->
<notDynamicXmlDocumentElements>
<element>p</element>
<element>div</element>
<element>ul</element>
<element>span</element>
</notDynamicXmlDocumentElements>
<dataTypeModelStaticMappings>
<!--
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping documentTypeAlias="textPage" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" documentTypeAlias="textPage" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" documentTypeAlias="textPage">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping dataTypeGuid="00000000-0000-0000-0000-000000000000" nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
<mapping nodeTypeAlias="propertyAlias">Fully.Qualified.Type.Name.For.ModelBinder,Assembly.Name.Excluding.Dot.Dll</mapping>
-->
</dataTypeModelStaticMappings>
</razor>
</scripting>


This is enough to get you to create Razor scripts. Making them run, however, requires more work

Saturday, 25 August 2012

And now... For a mono bug

Content > Any Document > RTE (Rich Text Editor) > enter any text and publish:
...Content is not in a correct format
Empty Multiline Textboxes are pre-appended with '\t' everytime an editor control with a Textbox
loads, this leads to corrupted RegEx filters, etc. upon saving.

This is a mono rendering bug. After the textbox opening tag is rendered, a new line is issued, and then,
System.Web/System.Web.UI/HtmlTextWriter.cs > OutputTabs() renders a single tab leading to corruption.
The TextBox, MultiLine generated <textarea> tag increases the Indent count by one. However, this is wrong and
when the opening <textarea> tag is closed a tab is issued inside the textarea which is of course rendered.

The culprit is line 214 in .../mono/mcs/class/System.Web/System.Web.UI.WebControls/Textbox.cs.
The simple fix is to comment out the line, and re-compile mono. There are also workarounds using a client side
script that scrubs the textboxes.

For now, I have locally re-compiled mono.
But in the alpha 4.7.2 linux release I will probably be doing either a client side script, or a wrapper class that overrides the
mono textbox (multiline) behaviour.

Friday, 24 August 2012

An Umbraco bug that affects Linux

due to casing...
In web.config setting, umbracoUseDirectoryUrls to true, produces errors like this: System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/webservices/legacyajaxcalls.asmx
Note: the url is in all lower-case.
In, .../umbraco/presentation/requestModule.cs lines 127:130, replace occurences of
'path' with 'requestPath' to get this:
	if (asmxPos >= 0)
context.RewritePath(requestPath.Substring(0, asmxPos + 5),
requestPath.Substring(asmxPos + 5),
context.Request.QueryString.ToString());

And... another Umbraco minority:
Content > Any Document > Publish > Publish completes with:
System.Configuration.Provider.ProviderException
Unrecognized attribute: securityTrimmingEnabled
At .../umbraco/presentation/umbraco/nodeFactory/UmbracoSiteMapProvider.cs:47
In file, .../umbraco/presentation/umbraco/nodeFactory/UmbracoSiteMapProvider.cs,
after line 38 add:
config.Remove("securityTrimmingEnabled");

Thursday, 23 August 2012

A quick update

I will be putting up the next iteration changes soon. Things have gone a bit slower than expected. There jave been a few Umbraco bugs, and also one old Mono bug, that has been lingering about since a couple of years or so. Also, there are differences in how mono handles XPathNodeIterator. In particular, one must call MoveNext() prior to dereferencing 'Current' - otherwise, Current is always null. This has necessitated touching up large areas of code - in particular with Razor, and library.cs, and it is not quite finished yet. Still working towards the alpha release. Ok that's it for now...

Another list of small fixes

I ll close off tonight's set with another list of small fixes:


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/WebServices/NodeSorter.asmx
Replace WebServices/NodeSorter.asmx with webservices/nodeSorter.asmx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco_client/tableSorting/img/bg.gif
Replace tableSorting/img/bg.gif with tablesorting/img/bg.gif


System.Web.HttpException
The resource cannot be found.
Replace webservices/cmsnode.asmx with webservices/CMSNode.asmx


System.Web.HttpException
The resource cannot be found.
Replace dialogs/assignDomain.aspx with dialogs/AssignDomain.aspx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/dialogs/rollback.aspx
Replace dialogs/rollback.aspx with dialogs/rollBack.aspx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco_client/propertyPane/images/propertyBackground.gif
Replace propertyPane/images/propertyBackground.gif with propertypane/images/propertyBackground.gif


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/dialogs/preview.aspx
Replace dialogs/preview.aspx with dialogs/Preview.aspx


Settings > Stylesheets > Save
[cssErrorHandler] make sure that you have permissions set correctly.
In .../umbraco/presentation/, create the 'css'.
Make sure the user (running the web server) has write permissions to it.

Wednesday, 22 August 2012

Dealing with dynamic checkboxlists losing their state after postback

This is probably the biggest mono oddity that we have. It could be a bug, but I am classifying it as an oddity. As far as I have found out in the MS specifications, the checkbox state of dynamic checkbox list controls is set during the prerender phase. Hence technically speaking the state of the controls is not available during Page_Load, or validation, which follows page load. While the state is not directly available in the controls, it is available in the viewstate, and can be accessed in the Request collection. We use this principle to provide a fix for lost checkboxlist states during postback. The following examples will illustrate.

(1)
Users > Users > Save
Error saving user (check log)
This error occurs because the "Sections" Checkbox list items lose their selected state.
I think this is a mono oddity. In fact, the checkbox list state is intact during
postback in Page_Load but is lost during validation, and during page rendering.
Here's the fix: it is a little clunky but it does work.
In .../umbraco/presentation/umbraco/users/EditUser.aspx.cs, modify sectionValidator_ServerValidate(...), and add after line 218,
setCheckBoxStates(lapps);

Then also add these:
        //mono fix for lost checkboxlist states
        private void setCheckBoxStates(CheckBoxList cbl)
        {
            if (IsPostBack)
            {
                string cblFormID = cbl.ClientID.Replace("_","$");
                int i = 0;
                foreach (var item in cbl.Items)
                {
                    string itemSelected = Request.Form[cblFormID + "$" + i];
                    if (itemSelected != null && itemSelected != String.Empty)
                        ((ListItem)item).Selected = true;
                    i++;
                }
            }
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            setCheckBoxStates(lapps);
        }

(2)
Settings > Document Types > Structure > Allowed child nodetypes Checkboxes state is not retained during save. This is the same issue as above. In .../umbraco/presentation/umbraco/controls/ContentTypeControlNew.aspx insert before line 285,
                        setCheckBoxStates(lstAllowedContentTypes);

and also add
        //mono fix for lost checkboxlist states
        private void setCheckBoxStates(CheckBoxList cbl)
        {
            if (IsPostBack)
            {
                string cblFormID = cbl.ClientID.Replace("_","$");
                int i = 0;
                foreach (var item in cbl.Items)
                {
                    string itemSelected = Request.Form[cblFormID + "$" + i];
                    if (itemSelected != null && itemSelected != String.Empty)
                        ((ListItem)item).Selected = true;
                    i++;
                }
            }
        }

(3)
Settings > Document Types > Info > Allowed Templates
Checkboxes state is not retained during save.
This looks like a mono oddity. When OnBubbleSave fires in
.../umbraco/presentation/umbraco/settings/EditNodeTypeNew.aspx,
the state of the checkbox is not available. We use the setCheckBoxStates(CheckBoxList cbl) fix.
In .../umbraco/presentation/umbraco/settings/EditNodeTypeNew.aspx insert before line 120,
setCheckBoxStates(templateList);

and also add
        //mono fix for lost checkboxlist states
                private void setCheckBoxStates(CheckBoxList cbl)
                {
                        if (IsPostBack)
                        {
                                string cblFormID = cbl.ClientID.Replace("_","$");
                                int i = 0;
                                foreach (var item in cbl.Items)
                                {
                                        string itemSelected = Request.Form[cblFormID + "$" + i];
                                        if (itemSelected != null && itemSelected != String.Empty)
                                                ((ListItem)item).Selected = true;
                                        i++;
                                }
                        }
                }

Monday, 20 August 2012

More casing fixes

And another set of smaller fixes follow:


Umbraco > Members
Could not load control: '/umbraco/Members/MemberSearch.ascx
replace Members/MemberSearch.ascx with members/MemberSearch.ascx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/settings/editMediaType.aspx
Replace settings/editMediaType.aspx with settings/EditMediaType.aspx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/members/editMemberType.aspx
Replace members/editMemberType.aspx with members/EditMemberType.aspx


Umbraco > Member Group > Save
[editMemberGroupSaved] key is not not config/lang/en.xml
Deferred for now.


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/
Replace settings/editDictionaryItem.aspx with settings/EditDictionaryItem.aspx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/settings/stylesheet/editStylesheet.aspx
Replace stylesheet/editStylesheet.aspx with stylesheet/editstylesheet.aspx


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/images/developer/userControlIcon.png
Replace developer/userControlIcon.png with developer/usercontrolIcon.png


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/users/editUser.aspx
Replace users/editUser.aspx with users/editUser.aspx

Two important changes

There are a couple of other important changes, Here they are:


 Umbraco > Members > EditMembers > Save 
Umbraco > Media > editMedia > Save
System.MethodAccessException
Method `umbraco.cms.businesslogic.web.Document:FireBeforeSave (umbraco.cms.businesslogic.SaveEventArgs)' is inaccessible from method `umbraco.controls.ContentControl:saveClick (object,System.Web.UI.ImageClickEventArgs)
The error originates in line 236 of .../umbraco/presentation/umbraco/controls/ContentControl.cs


doc.FireBeforeSave(docArgs);

this indeed breaks protection. In .../umbraco/cms/businesslogic/web/Document.cs line 1884, we have,


protected internal new virtual void FireBeforeSave(SaveEventArgs e)

change this to,


public new virtual void FireBeforeSave(SaveEventArgs e)

We may need to revisit this.


The other issue involves the '¤' character, which is used as a string splitter.Mono is quite fussy about how this string is defined. Here's what works in mono.


Settings > Scripts > Create Folder
Index out of bounds error
This is due to issues with "¤" string splitting.
In file .../umbraco/presentation/umbraco/create/script.ascx.cs, modify line 40 as:


	char c = '\u00A4';
string returnUrl = presentation.create.dialogHandler_temp.Create(
helper.Request("nodeType"),
createFolder,
relativepath + c.ToString() + rename.Text + c.ToString() + scriptType.SelectedValue);

and in file .../umbraco/presentation/umbraco/create/ScriptTasks.cs, modify line 44 as:


	char c = '\u00A4'; 
string[] scriptFileAr = _alias.Split(c);

 

Sunday, 19 August 2012

Resolving an IOHelper.MapPath issue

We are continuing right on... In the last set of posts, I had made some changes to IOHelper.MapPath(...).  


After the IOHelper.MapPath modification, .../umbraco/presentation/umbraco/dashboard/FeedProxy.aspx no longer loads feeds.


Modify line 27 from,


var feedProxyXml = xmlHelper.OpenAsXmlDocument(IOHelper.MapPath(SystemFiles.FeedProxyConfig));

to


var feedProxyXml = xmlHelper.OpenAsXmlDocument(SystemFiles.FeedProxyConfig);

The xmlHelper class already uses IOHelper.MapPath, and calling it twice produces an incorect path.


This probably can be fixed in other ways as well. But we will do this for now.

Saturday, 11 August 2012

"\" and "\\" character issues

Now we are ready to look at the "/" and "\\" character issues. As we know, the path separator in Linux is "/", while in windows it is "\\".

Mono has two built-in mechanisms for dealing with these differences:

(1) When mono is compiled with IS_PORTABILITY_SET, then in the mono CLR, for a unix system, AltDirectorySeparatorChar is defined as "\\". (Otherwise AltDirectorySeparatorChar is defined as "/")

(2) Running the mono app with the MONO_IOMAP=all environment variable set also sets the AltDirectorySeparatorChar to "\\" on Unix systems. However, running Umbraco with this environment variable set is slow and prone to crashes.

I am going to go for a third option, where I make the path character issues explicit in code (with help from the MultiPlatformHelper class):

(3) Resolving path separator character issues in the Umbraco code itself.

The changes so far impact the downloading and installation of packages.

Preliminaries

Developer > Packages
System.IO.DirectoryNotFoundException
Could not find a part of the path ".../umbraco/presentation/App_Data/packages/created/createdPackages.config".
If this directory / file is missing get it from a working install

Developer > Packages
You get this error after clicking "OK" to install a package
System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/developer/packages/proxy.htm
Why? Umbraco referrer url is:
http://our.umbraco.org/repo_viewproject?repoguid=65194810-1f85-11dd-bd0b-0800200c9a66&callback=127.0.0.1:8080/umbraco/developer/packages/proxy.htm?/umbraco/developer/packages/installer.aspx?repoguid=65194810-1f85-11dd-bd0b-0800200c9a66&version=v45&fullversion=4.7.2&uselegacyschema=false&dotnetversion=4.0.30319.17020&trustlevel=unrestricted&project_id=8189
Notice the casing.
Solutions: rename local Packages folder to packages, or set a symbolic link.
We ll do the symbolic link for now:
cd umbraco/presentation/umbraco/developer
ln -s Packages packages

Developer > Packages
System.Exception
Error - file not found. Could not find file named '.../umbraco/presentation/App_Data/packages\...
In .../umbraco/cms/businesslogic/Packager/Repositories/Repository.cs line 209,
Replace
"packages\\" + packageGuid + ".umb"

with
return String.Format ("packages{0}{0}{1}.umb", Path.DirectorySeparatorChar, packageGuid);

Now we are ready to proceed with the alterations:

Developer > Packages
System.IO.FileNotFoundException
Could not find file ".../umbraco/presentation/App_Data/fc9f3959-3764-4678-a14e-139974cbfe30/package.xml
Decompressed File names look like: 09b6762e-67b1-4cba-b0d9-14652ddcbb30\package

Replace .../umbraco/cms/businesslogic/Packager/Installer.cs line 963:964 with:
      string entryName = theEntry.Name;

      if (Path.DirectorySeparatorChar.ToString() == MultiPlatformHelper.UNIX_DIRSEP)
entryName = entryName.Replace(MultiPlatformHelper.WIN_DIRSEP, Path.DirectorySeparatorChar.ToString());

      string directoryName = Path.GetDirectoryName(entryName);
      string fileName = Path.GetFileName(entryName);

Developer > Packages
After installation we find under .../umbraco/presentation, a directory called:
...\umbraco\presentation\, which contains the package files.

In .../umbraco/cms/businesslogic/Packager/Installer.cs
Alter lines 814:815 to
if (Path.DirectorySeparatorChar.ToString() == MultiPlatformHelper.WIN_DIRSEP)
{
path = MultiPlatformHelper.ConvertPathFromUnixToWin(path);
fileName = MultiPlatformHelper.ConvertPathFromUnixToWin(fileName);
}

Friday, 10 August 2012

Intermission

Before moving on to the "/" and "\\" characters, let's also fix this error:


System.Web.HttpException
The resource cannot be found.
Details: Requested URL: /umbraco/~/umbraco/js/umbracoUpgradeChecker.js
Path error: should say - /umbraco/js/umbracoUpgradeChecker.js


Solution: in .../umbraco/presentation/umbraco/umbraco.aspx.cs line 104 change



sm.Scripts.Add(new ScriptReference(SystemDirectories.Umbraco + "/js/umbracoUpgradeChecker.js"));

to



string scriptPath = SystemDirectories.Umbraco + "/js/umbracoUpgradeChecker.js";
scriptPath = IOHelper.ResolveUrl(scriptPath);
ScriptReference scriptReference = new ScriptReference(scriptPath);

sm.Scripts.Add(scriptReference);

 

Thursday, 9 August 2012

A tale of three paths...

This installment is entitled:

"A tale of three paths..."


Of course, we are not talking about an Oscar winning movie, rather our three paths simply are "~", "/", and "\\", the last one also known as @"\".
All of these three (path) characters play a signifcant role in our linux port.

Let's start with "~"


Changing .../umbraco/businesslogic/IO/IOHelpers.cs line 114: path[1] to path[0] got us going but it also introduced
a subtle bug. Here it is:

System.Exception
Could not locate TinyMCE by URI:/umbraco_client/tinymce3/tiny_mce_src.js, Physical path:/umbraco_client/tinymce3/tiny_mce_src.js. Make sure that you configured the installPath to a valid location in your web.config. This path should be an relative or site absolute URI to where TinyMCE is located.
.../umbraco/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs:219

Because we had effectively stripped the ~, the above was not mapped properly.

In fact going from path[1] to path[0] changes application behaviour significantly. As "~" in Linux is resolved as the value of $HOME, stripping the "~" character for any IO operation involving the file system makes sense. In windows, .NET operations which involve e.g. loading a file path with "~" in it resolve well. Not so under Linux.

Going from path[1] to path[0], however, did not work in this case:

Content > Trying to load a content page with a rich text editor
System.Exception
Could not locate TinyMCE by URI:/umbraco_client/tinymce3/tiny_mce_src.js, Physical path:/umbraco_client/tinymce3/tiny_mce_src.js. Make sure that you configured the installPath to a valid location in your web.config. This path should be an relative or site absolute URI to where TinyMCE is located.
.../umbraco/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs:219

So, now we apply a better fix

(1) In .../umbraco/businesslogic/IO, we have add a new MultiPlatformHelper class:
using System;
using System.Text;

namespace umbraco.IO
{
public static class MultiPlatformHelper
{

public const string PLATFORM_UNIX = "UNIX";
public const string PLATFORM_WIN = "WIN";

public const string WIN_DIRSEP = "\\";
public const string UNIX_DIRSEP = "/";

public static string OSPlatform
{
get
{
return System.Environment.OSVersion.Platform.ToString().ToUpper();
}
}

public static bool IsWindows()
{
return OSPlatform.Contains(PLATFORM_WIN);
}

public static bool IsUnix()
{
return OSPlatform.Contains(PLATFORM_UNIX);
}

public static string MapUnixPath(string path)
{
string filePath = path;

if (filePath.StartsWith("~"))
filePath = IOHelper.ResolveUrl(filePath);

filePath = IOHelper.MapPath(filePath, true);

return filePath;
}

public static string ConvertPathFromUnixToWin(string path)
{
return path.Replace(MultiPlatformHelper.UNIX_DIRSEP, MultiPlatformHelper.WIN_DIRSEP);
}

}
}

(2) Then in .../umbraco/businesslogic/IOHelper.cs, modify MapPath as:
        public static string MapPath(string path)

{

if (IO.MultiPlatformHelper.IsWindows())

return MapPath(path, true);

return IO.MultiPlatformHelper.MapUnixPath(path);

}

This fixes the tinyMCE load error and also makes the "~" path issues clear.

Again, this will keep us for now, but we will probably re-visit it in the future.