1

enter image description here

In the console..

enter image description here

This is the code I use to convert the sent remote object data to be properly formatted.

var AccountEntity = function() {

}


AccountEntity.fromRemoteObjectModel = function(model) {
    var entity = new AccountEntity();

    /*
    model is an instance of a Remote Object. You can use .get() to retrieve the field value by the API name or the jsShorthand you specified.
    */
    entity.id = model.get('Id');
    entity.name = model.get('Name');

    return entity;
}

AccountEntity.prototype.toRemoteObjectModelDetails = function() {
    var details = {};

    if (this.id) {
        details.Id = this.id;
    }

    details.Name = this.name;


    return details;
}

AccountEntity.prototype.id = '';
AccountEntity.prototype.name = '';
1

You'll have to decode the values; they're encoded for your protection. That would probably look like this:

var textarea = document.createElement('textarea');
textarea.innerHTML = model.get('Name');
entity.name = textarea.textContent;

Keep in mind that if you're rendering them to some other element, then that script should instead just use innerHTML, as demonstrated here.

|improve this answer|||||
  • Fwiw, using textarea is marginally more secure than div, apparently. – Adrian Larson Nov 4 '16 at 22:01
  • @AdrianLarson Yeah, I just found out about that exploit as you mentioned it. I'll edit. – sfdcfox Nov 4 '16 at 22:11
  • It's a pretty quick search. The relevant question on Stack Overflow was asked 6 years ago and has >100k views. – Adrian Larson Nov 4 '16 at 22:16
  • 1
    @AdrianLarson Yeah, I'm not surprised. I've (re-?)learned something new today :D – sfdcfox Nov 4 '16 at 22:18
0

You may want to consult Stack Overflow here, specifically Decode & back to & in JavaScript. You can simply unescape html in the names, but that is probably a security vulnerability. It may be best to take the first recommended approach, specifically replacing the ampersands.

If you take that approach, replace:

entity.name = model.get('Name');

with:

entity.name = (model.get('Name') || "").replace(/&/g, '&');

If you want to escape more than just this one character, I would take a more cautious approach and at least replace < with &lt; and > with &gt; to minimize injection risk.

var elem = document.createElement('textarea');
elem.innerHTML = model.get('Name');
entity.name = elem.value.replace(/</g, '&lt;').replace(/>/g, '&gt;');
|improve this answer|||||
  • This is nice, but what if there is a user with the name O'Brien? 😕 – Tyler Zika Nov 4 '16 at 21:55
  • Or a account that's called O'Brien & Smith Inc. 😵 – Tyler Zika Nov 4 '16 at 21:55
  • @TylerZika Well, then you would need to go down door number two. If you decode wholesale, you may wish to replace < with &lt; and > with &gt; to at least minimize the security risk. – Adrian Larson Nov 4 '16 at 21:59
  • My problem I'm having seems like an issue that shouldn't happen. This should be an out of the box feature of converting between secure and proper characters involving JavaScript remoting.... – Tyler Zika Nov 4 '16 at 22:12
  • @TylerZika I agree this behavior is crap. Ironically, the JavaScript library they give us is just doing extra work. The data comes over the wire normally as you'd expect, but they force the data to be escaped with their current API wrapper. See my new answer for a better solution. – jon_wu Feb 26 '17 at 9:19
0

I came across the same issue, but wasn't happy with the answers here.

While some secure defaults can be helpful to protect new developers, it's pretty horrible to force us to HTML escape strings within our JavaScript with no way around this. Having to decode every value that comes back clearly add code and processing that we'd rather skip.

Since there's an escape option for JavaScript Remoting, it would be logical that we could do the same here. After inspecting the network requests and confirming that the backend isn't returning HTML encoded JSON (and is therefore being encoded on the frontend), I decided to dig deeper. I formatted the Salesforce JavaScript for JavaScript Remoting and Visualforce Remote Objects to look at what's happening behind the scenes.

I found that the Visualforce Remote Objects just uses the same remoting code behind the scenes, but it doesn't give us any ability to pass parameters through to it. That's a bummer and hopefully they'll add this in the future.

In the meantime, we can patch the Visualforce.remoting.Manager.invokeAction to detect a retrieve call and inject the escape: false parameter in so that htmlEncode isn't called on the result.

Just add this code to your page before your Visualforce Remote Objects code runs.

CAUTION: While this is overriding a documented method, it may break if the internals change. Use at your own risk! It's working well for me as of v39.

<script>
 // Override invokeAction so we can inject extra parameters in when we detect a Visualforce Remote Object retrieve.
(function() {
  // `VFSObjectCrud.js` calls `$VFRM.Manager`, which `=== Visualforce.remoting.Manager`.
  // It seems more likely that `Visualforce.remoting.Manager` will be a stable name vs `$VFRM`,
  // since it's documented:
  // https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_js_remoting_configuring_request.htm
  var invokeAction = Visualforce.remoting.Manager.invokeAction;
  Visualforce.remoting.Manager.invokeAction = function() {
    // Ensure this is a retrieve with the callback as the last parameter (without any options).
    if (arguments[0] === 'JavaScriptSObjectBaseController.retrieve'
        && typeof arguments[arguments.length - 1] === 'function') {
      // We've detected that this Visualforce Remoting call is for a Visualforce Remote Objects retrieve call.

      // Turn arguments into a real Array so we can add one.
      var args = Array.from(arguments);
      // Add an escape parameter so the remoting library skips calling htmlEncode on the result.
      // This is the same parameter available for JavaScript Remoting.
      // https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_js_remoting_configuring_request.htm
      args.push({escape: false});
      invokeAction.apply(this, args);
    } else {
      // This isn't a Visualforce Remote Object retrieve so just pass the arguments through untouched.
      invokeAction.apply(this, arguments);
    }
  };
})();
</script>
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.