Revolution: An Open angle bracket < in custom field within Manager Form crashes the save process

Created on 4 Dec 2017  路  21Comments  路  Source: modxcms/revolution

An open angle bracket < in custom field (from MODx.onDocFormRender or however) within Manager Form crashes the save process, but the content is still saved on the server without error

MODX 2.6.0 and below

To Reproduce

  1. Please insert custom field using this tut
    https://docs.modx.com/revolution/2.x/case-studies-and-tutorials/adding-custom-fields-to-manager-forms
  2. Then alter the content of said field to have an open angle bracket.
  3. Then save the resource

Quick Reproduce

  1. Open a native MODX resource in the Manager
  2. Run code in browser's JS dev console
  3. Save the resource
 var modxForm = document.getElementsByTagName('form')[0];
  var newTextarea = document.createElement("textarea");
  newTextarea.setAttribute('id', 'mynewTextArea');
  newTextarea.setAttribute('name', 'mynewTextArea');
  newTextarea.value='<THIS__WILL__CRASH'; //crashes when you save the resource
  modxForm.appendChild(newTextarea);
bug

Most helpful comment

I _may_ have found a simpler fix than #13810 for this.

The problem remains that ExtJS uses an iframe to submit requests. The response in that iframe is processed by the browser, causing HTML to break the (otherwise valid) JSON response. JSON can contain HTML, even invalid HTML, just fine, it's only ExtJS' iframe-based request handling that breaks it.

I found this post about ext4 and how it has a new check for pre tags that the browser inserts when the response has a content type of text/json.

That code looked remarkably close to what @Finetuned tried to do in #13810, by wrapping the result in a textarea, which unfortunately would break a lot of things. However, setting a Content-Type header would not be quite as invasive to extras/non-mgr usage of connectors, as only really silly ways of submitting a request (like an iframe) would get a slightly different response.

So, back-porting that ext4 change into our ancient ext3, and updating modConnectorResponse to issue a text/json (or application/json) content type header, solves the problem!

I reformatted ext-all.js as a quick test and added

if ((contentNode = A.body.firstChild) && /pre/i.test(contentNode.tagName)) {
       w.responseText = z.textContent;
}

before the handling for textarea.

In modConnectorResponse there's some logic that only sets an application/json header when the request came from an xmlhttprequest. I just added header("Content-Type: application/json; charset=UTF-8"); before that if to always set it as a test.

And voila, my test case for this bug was fixed! :D

I think this would be a safer fix than #13810 as it doesn't change the actual content, just a header, but still fixes it. Would need some cleaning up and more testing, but this may be a way for us to get proper json support...

All 21 comments

My current solution is

JS

document.getElementById("myEl").value = content.replace(/(?:<)/g, "&lt++;");
 //snuff out all opening angle brackets with custom entity

PHP

$content = str_replace("&lt++;", "<", $content);
//remove your custom entity before saving resource

After looking into this in modxbughunt#3, the issue is due to Ext.data.Connection truncating the json which arrives intact from modconnectorresponseclass->outputContent().

So it is already invalid _before_ it arrives into utilities.js -> Ext.override(Ext.form.Action.Submit.... handleResponse() where the error is raised.

The ExtJS docs for Ext.data.Connection state that:

Characters which are significant to an HTML parser must be sent as HTML entities...

So the content from custom fields must be processed before it gets sent to the server.

The error is not encountered if a closing bracket is present.

Nice detective work. Is there any way to solve this issue, or is the issue in Extjs itself?

It's in Ext. It creates a iframe and drops the response text into the body. I am thinking to override the class to add a