sleemanj / xinha

WYSIWYG HTML Editor Component (turns <textarea> into HTML editors)
http://trac.xinha.org/
Other
13 stars 2 forks source link

Patch to make javascript safe (not execute) in Xinha (Trac #685) #685

Closed sleemanj closed 4 years ago

sleemanj commented 18 years ago

In htmlarea.js, just below the line that says:

  // external stylesheets to load (REFERENCE THESE ABSOLUTELY)
  this.pageStyleSheets = ["this.css"];

add:

  // external js file to link content to (REFERENCE THIS ABSOLUTELY)
  // example:   utilityjs = "flashobject.js";
  utilityjs = "";

Replace:

  // Set up event listeners for saving the iframe content to the textarea
  if (textarea.form)
  {
    // onsubmit get the HTMLArea content and update original textarea.
    HTMLArea.prependDom0Event
    (
      this._textArea.form,
      'submit',
      function() {editor._textArea.value = editor.outwardHtml(editor.getHTML()); return true;}
    );

with:

  // Set up event listeners for saving the iframe content to the textarea
  if (textarea.form)
  {
    // onsubmit get the HTMLArea content and update original textarea.
    HTMLArea.prependDom0Event
    (
      this._textArea.form,
      'submit',
      function() {editor._textArea.value = editor.outwardHtml(editor.getHTML()).replace(/freezescript/ig, "javascript"); return true;}
    );

Replace:

      html += "</head>\n";
      html += "<body>\n";
      html +=   editor.inwardHtml(editor._textArea.value);
      html += "</body>\n";
      html += "</html>";
    } else {
      var html = editor.inwardHtml(editor._textArea.value);
      if (html.match(HTMLArea.RE_doctype)) {
        editor.setDoctype(RegExp.$1);
        html = html.replace(HTMLArea.RE_doctype, "");
      }
    }
    doc.write(html);
    doc.close();

with:

      html += "</head>\n";
      html += "<body>\n";
      html +=   editor.inwardHtml(editor._textArea.value);
      html += "</body>\n";
      html += "</html>";
    } else {
      var html = editor.inwardHtml(editor._textArea.value);
      if(utilityjs){
      html = "<script type=\"text/javascript\" src=\""+utilityjs+"\"></script>\n" + html;
      }
      html = html.replace(/<script>/ig, "<script type=\"text/freezescript\">");
      html = html.replace(/javascript/ig, "freezescript");
      if (html.match(HTMLArea.RE_doctype)) {
        editor.setDoctype(RegExp.$1);
        html = html.replace(HTMLArea.RE_doctype, "");
      }
    }
    doc.write(html);
    doc.close();

This provides the config option of creating a link to an external js file such as flashobject.js, and also allows javascript document.writes to be in the content without executing.

Please add this capability to core Xinha so the Flash plugin can be used by any Xinha user.

Reported by mharrisonline, migrated from http://trac.xinha.org/ticket/685

sleemanj commented 18 years ago
sleemanj commented 18 years ago

mharrisonline commented:

If this capability was added to Xinha, it would make possible a powerful new type of plugin which could insert Javascript to write in dynamic content, such as RSS feeds.

sleemanj commented 18 years ago

mharrisonline commented:

So, after this patch is added, if you want to insert new JavaScript while using the editor, just replace the word javascript with freezescript, and the script language will revert to javascript upon save.

sleemanj commented 18 years ago

mharrisonline commented:

I updated the patch, and will attach a revised htmlarea.js and a simplified example page to demonstrate this.

Add to line 291, or after the config "this.pageStyleSheets = [];"

  // external js file to link content to (REFERENCE THIS ABSOLUTELY)
  // example:   utilityjs = "flashobject.js";
  utilityjs = "";

line 1603 changes from:

editor._textArea.value = editor.outwardHtml(editor.getHTML());

to:

editor._textArea.value = editor.outwardHtml(editor.getHTML()).replace(/freezescript/ig, "javascript");

Replace the function HTMLArea.prototype.initIframe

with:

HTMLArea.prototype.initIframe = function()
{
  this.setLoadingMessage('Init IFrame');
  this.disableToolbar();
  var doc = null;
  var editor = this;
  try
  {
    if ( editor._iframe.contentDocument )
    {
      this._doc = editor._iframe.contentDocument;        
    }
    else
    {
      this._doc = editor._iframe.contentWindow.document;
    }
    doc = this._doc;
    // try later
    if ( !doc )
    {
      if ( HTMLArea.is_gecko )
      {
        setTimeout(function() { editor.initIframe(); }, 50);
        return false;
      }
      else
      {
        alert("ERROR: IFRAME can't be initialized.");
      }
    }
  }
  catch(ex)
  { // try later
    setTimeout(function() { editor.initIframe(); }, 50);
  }

  HTMLArea.freeLater(this, '_doc');

  doc.open();
  var html = '';
  if ( !editor.config.fullPage )
  {
    html = "<html>\n";
    html += "<head>\n";
    html += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + editor.config.charSet + "\">\n";
    if ( typeof editor.config.baseHref != 'undefined' && editor.config.baseHref !== null )
    {
      html += "<base href=\"" + editor.config.baseHref + "\"/>\n";
    }
    html += "<style title=\"table borders\">";
    html += ".htmtableborders, .htmtableborders td, .htmtableborders th {border : 1px dashed lightgrey ! important;} \n";
    html += "</style>\n";
    html += "<style type=\"text/css\">";
    html += "html, body { border: 0px;  background-color: #ffffff; } \n";
    html += "span.macro, span.macro ul, span.macro div, span.macro p {background : #CCCCCC;}\n";
    html += "</style>\n";

    if ( editor.config.pageStyle )
    {
      html += "<style type=\"text/css\">\n" + editor.config.pageStyle + "\n</style>";
    }

    if ( typeof editor.config.pageStyleSheets !== 'undefined' )
    {
      for ( var i = 0; i < editor.config.pageStyleSheets.length; i++ )
      {
        if ( editor.config.pageStyleSheets[i].length > 0 )
        {
          html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + editor.config.pageStyleSheets[i] + "\">";
          //html += "<style> @import url('" + editor.config.pageStyleSheets[i] + "'); </style>\n";
        }
      }
    }
if(utilityjs){
    html = "<script type=\"text/freezescript\" src=\""+utilityjs+"\"></script>\n" + html;
}
    html += "</head>\n";
    html += "<body>\n";
    html +=   editor.inwardHtml(editor._textArea.value);
    html += "</body>\n";
    html += "</html>";
  }
  else
  {
    html = editor.inwardHtml(editor._textArea.value);
    if(utilityjs){
    html = "<script type=\"text/freezescript\" src=\""+utilityjs+"\"></script>\n" + html;
    }
    if ( html.match(HTMLArea.RE_doctype) )
    {
      editor.setDoctype(RegExp.$1);
      html = html.replace(HTMLArea.RE_doctype, "");
    }
  }
      html = html.replace(/<script>/ig, "<script type=\"text/freezescript\">");
  html = html.replace(/javascript/ig, "freezescript");
  doc.write(html);
  doc.close();

  this.setEditorEvents();
};
sleemanj commented 18 years ago

htmlarea.js with patch applied to make Xinha safe to use with content containing JavaScript Attachment: htmlarea.js

sleemanj commented 18 years ago

place in the examples folder in xinha instance with the patched htmlare.js patch, this will demonstrate preloaded js with document.write statements being prevented from executing in the editor. Attachment: simple_example.html

sleemanj commented 18 years ago

Geoffrey commented:

This is very useful. Could it perhaps be implemented (initially) as a FreezeScript plugin, a bit like the GetHTML plugin, which replaces core functions without actually meddling with Xinha's internal code?

sleemanj commented 18 years ago

mharrisonline commented:

On our Website numerous pages have javascript functions to load Flash videos using a modified SWFObject script. All the JavaScript gets entered through Xinha with the FreezeSccript fix. There are even AJAX tabs that are left intact by Xinha.

http://www.jiu.edu/

sleemanj commented 18 years ago

koto commented:

Is there anything against commiting this to Xinha? Seems very useful, especially for Flash-related plugins described in [http://xinha.python-hosting.com/ticket/669]

sleemanj commented 18 years ago

ray commented:

Hello, in rev 620 I have added the freezescript functionality with some differences:

  • using HTMLArea.prototype.outwardHtml()/HTMLArea.prototype.inwardHtml() it works transparently in the background in all relevant places, also you don't have to use "freezescript" in text mode
  • I have not yet taken over the changes in HTMLArea.prototype.initIframe(), because I didn't quite understand them:
    • in non-FullPage mode it brings just about nothing. It isn't executed because of freezescript, neither is it saved with the document as it's in the head section
    • in FullPage mode I found it a bit strange to enter content through a config variable. What if you open the document once again? I think the utilityjs is added once again and again... Also it is placed before the

Pls comment if I got something wrong

Furthermore this changeset enables the use of script tags with the "old" getHTML() and introduces a new config option to control whether you want to allow or deny Githubissues.

  • Githubissues is a development platform for aggregating issues.