HTML-encoding lost when attribute read from input field

前端 未结 25 3906
时光说笑
时光说笑 2020-11-21 04:04

I’m using JavaScript to pull a value out from a hidden field and display it in a textbox. The value in the hidden field is encoded.

For example,



        
相关标签:
25条回答
  • 2020-11-21 04:42

    The jQuery trick doesn't encode quote marks and in IE it will strip your whitespace.

    Based on the escape templatetag in Django, which I guess is heavily used/tested already, I made this function which does what's needed.

    It's arguably simpler (and possibly faster) than any of the workarounds for the whitespace-stripping issue - and it encodes quote marks, which is essential if you're going to use the result inside an attribute value for example.

    function htmlEscape(str) {
        return str
            .replace(/&/g, '&')
            .replace(/"/g, '"')
            .replace(/'/g, ''')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    }
    
    // I needed the opposite function today, so adding here too:
    function htmlUnescape(str){
        return str
            .replace(/&quot;/g, '"')
            .replace(/&#39;/g, "'")
            .replace(/&lt;/g, '<')
            .replace(/&gt;/g, '>')
            .replace(/&amp;/g, '&');
    }
    

    Update 2013-06-17:
    In the search for the fastest escaping I have found this implementation of a replaceAll method:
    http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
    (also referenced here: Fastest method to replace all instances of a character in a string)
    Some performance results here:
    http://jsperf.com/htmlencoderegex/25

    It gives identical result string to the builtin replace chains above. I'd be very happy if someone could explain why it's faster!?

    Update 2015-03-04:
    I just noticed that AngularJS are using exactly the method above:
    https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

    They add a couple of refinements - they appear to be handling an obscure Unicode issue as well as converting all non-alphanumeric characters to entities. I was under the impression the latter was not necessary as long as you have an UTF8 charset specified for your document.

    I will note that (4 years later) Django still does not do either of these things, so I'm not sure how important they are:
    https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

    Update 2016-04-06:
    You may also wish to escape forward-slash /. This is not required for correct HTML encoding, however it is recommended by OWASP as an anti-XSS safety measure. (thanks to @JNF for suggesting this in comments)

            .replace(/\//g, '&#x2F;');
    
    0 讨论(0)
  • 2020-11-21 04:42
    <script>
    String.prototype.htmlEncode = function () {
        return String(this)
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    
    }
    
    var aString = '<script>alert("I hack your site")</script>';
    console.log(aString.htmlEncode());
    </script>
    

    Will output: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

    .htmlEncode() will be accessible on all strings once defined.

    0 讨论(0)
  • 2020-11-21 04:42

    I ran into some issues with backslash in my Domain\User string.

    I added this to the other escapes from Anentropic's answer

    .replace(/\\/g, '&#92;')
    

    Which I found here: How to escape backslash in JavaScript?

    0 讨论(0)
  • 2020-11-21 04:47

    Here is a simple javascript solution. It extends String object with a method "HTMLEncode" which can be used on an object without parameter, or with a parameter.

    String.prototype.HTMLEncode = function(str) {
      var result = "";
      var str = (arguments.length===1) ? str : this;
      for(var i=0; i<str.length; i++) {
         var chrcode = str.charCodeAt(i);
         result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
       }
       return result;
    }
    // TEST
    console.log("stetaewteaw æø".HTMLEncode());
    console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))
    

    I have made a gist "HTMLEncode method for javascript".

    0 讨论(0)
  • 2020-11-21 04:48

    Here's a non-jQuery version that is considerably faster than both the jQuery .html() version and the .replace() version. This preserves all whitespace, but like the jQuery version, doesn't handle quotes.

    function htmlEncode( html ) {
        return document.createElement( 'a' ).appendChild( 
            document.createTextNode( html ) ).parentNode.innerHTML;
    };
    

    Speed: http://jsperf.com/htmlencoderegex/17

    speed test

    Demo:

    Output:

    output

    Script:

    function htmlEncode( html ) {
        return document.createElement( 'a' ).appendChild( 
            document.createTextNode( html ) ).parentNode.innerHTML;
    };
    
    function htmlDecode( html ) {
        var a = document.createElement( 'a' ); a.innerHTML = html;
        return a.textContent;
    };
    
    document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );
    
    //sanity check
    var html = '<div>   &amp; hello</div>';
    document.getElementById( 'same' ).textContent = 
          'html === htmlDecode( htmlEncode( html ) ): ' 
        + ( html === htmlDecode( htmlEncode( html ) ) );
    

    HTML:

    <input id="hidden" type="hidden" value="chalk    &amp; cheese" />
    <input id="text" value="" />
    <div id="same"></div>
    
    0 讨论(0)
  • 2020-11-21 04:49

    Picking what escapeHTML() is doing in the prototype.js

    Adding this script helps you escapeHTML:

    String.prototype.escapeHTML = function() { 
        return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
    }
    

    now you can call escapeHTML method on strings in your script, like:

    var escapedString = "<h1>this is HTML</h1>".escapeHTML();
    // gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"
    

    Hope it helps anyone looking for a simple solution without having to include the entire prototype.js

    0 讨论(0)
提交回复
热议问题