2017-10-18 13:39 GMT+03:00  <ma...@apache.org>:
> Author: markt
> Date: Wed Oct 18 10:39:54 2017
> New Revision: 1812489
>
> URL: http://svn.apache.org/viewvc?rev=1812489&view=rev
> Log:
> Refactor XML and HTML escaping to a single location
>
> Added:
>     tomcat/trunk/java/org/apache/tomcat/util/security/Escape.java   (with 
> props)
> Modified:
...

Good. It's more than I hoped for. Several comments below.

> Added: tomcat/trunk/java/org/apache/tomcat/util/security/Escape.java
> URL: 
> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/security/Escape.java?rev=1812489&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/tomcat/util/security/Escape.java (added)
> +++ tomcat/trunk/java/org/apache/tomcat/util/security/Escape.java Wed Oct 18 
> 10:39:54 2017
> @@ -0,0 +1,160 @@
> +/* ...
> + */
> +package org.apache.tomcat.util.security;
> +
> +/**
> + * Provides utility methods to escape content for different contexts. It is
> + * critical that the escaping used is correct for the context in which the 
> data
> + * is to be used.
> + */
> +public class Escape {
> +
> +    /**
> +     * Escape content for use in HTML. This escaping is suitable for the
> +     * following uses:
> +     * <ul>
> +     * <li>Element content when the escaped data will be placed directly 
> inside
> +     *     tags such as &lt;p&gt;, &lt;td&gt; etc.</li>
> +     * <li>Attribute values when the attribute value is quoted with &quot; or
> +     *     &#x27;.</li>
> +     * </ul>
> +     *
> +     * @param content   The content to escape
> +     *
> +     * @return  The escaped content or {@code null} if the content was
> +     *          {@code null}
> +     */
> +    public static String htmlElementContent(String content) {
> +        if (content == null) {
> +            return null;
> +        }
> +
> +        StringBuilder sb = new StringBuilder();
> +
> +        for (int i = 0; i < content.length(); i++) {
> +            char c = content.charAt(i);
> +            if (c == '<') {
> +                sb.append("&lt;");
> +            } else if (c == '>') {
> +                sb.append("&gt;");
> +            } else if (c == '\'') {
> +                sb.append("&#x27;");

Writing the above as decimal number will save one character. 'x'

sb.append("&#39;");

(Also I wondered whether HTML spec supports hex notation here. In [1]
-> 5.3.1 Numeric character references
-> Hex numerals are supported.
-> a "Note" says that original spec did not have it, but it was added
later (in a document dating year 1998)
)

[1] https://www.w3.org/TR/1999/REC-html401-19991224/charset.html#h-5.3.1


> +            } else if (c == '&') {
> +                sb.append("&amp;");
> +            } else if (c == '"') {
> +                sb.append("&quot;");
> +            } else if (c == '/') {
> +                sb.append("&#x2F;");

sb.append("&#47;");

> +            } else {
> +                sb.append(c);
> +            }
> +        }
> +
> +        return sb.toString();
> +    }
> +
> +
> +    /**
> +     * Convert the object to a string via {@link Object#toString()} and HTML
> +     * escape the resulting string for use in HTMl content.

s/HTMl/HTML/

> +     *
> +     * @param obj       The object to convert to String and then escape
> +     *
> +     * @return The escaped content or <code>&quot;?&quot;</code> if obj is
> +     *         {@code null}
> +     */
> +    public static String htmlElementContext(Object obj) {
> +        if (obj == null) {
> +            return "?";
> +        }
> +
> +        try {
> +            return xml(obj.toString());

I think that the above was supposed to be a call to
"htmlElementContext()", according to the method name.

> +        } catch (Exception e) {
> +            return null;
> +        }
> +    }
> +
> +
> +    /**
> +     * Escape content for use in XML.
> +     *
> +     * @param content   The content to escape
> +     *
> +     * @return  The escaped content or {@code null} if the content was
> +     *          {@code null}
> +     */
> +    public static String xml(String content) {
> +        return xml(null, content);
> +    }
> +
> +
> +    /**
> +     * Escape content for use in XML.
> +     *
> +     * @param ifNull    The value to return if content is {@code null}
> +     * @param content   The content to escape
> +     *
> +     * @return  The escaped content or the value of ifNull if the content was
> +     *          {@code null}
> +     */
> +    public static String xml(String ifNull, String content) {
> +        return xml(ifNull, false, content);
> +    }
> +
> +
> +    /**
> +     * Escape content for use in XML.
> +     *
> +     * @param ifNull        The value to return if content is {@code null}
> +     * @param escapeCRLF    Should CR and LF also be escaped?
> +     * @param content       The content to escape
> +     *
> +     * @return  The escaped content or the value of ifNull if the content was

{@code ifNull}

> +     *          {@code null}
> +     */
> +    public static String xml(String ifNull, boolean escapeCRLF, String 
> content) {
> +        if (content == null) {
> +            return ifNull;
> +        }
> +
> +        StringBuilder sb = new StringBuilder();
> +
> +        for (int i = 0; i < content.length(); i++) {
> +            char c = content.charAt(i);
> +            if (c == '<') {
> +                sb.append("&lt;");
> +            } else if (c == '>') {
> +                sb.append("&gt;");
> +            } else if (c == '\'') {
> +                sb.append("&apos;");
> +            } else if (c == '&') {
> +                sb.append("&amp;");
> +            } else if (c == '"') {
> +                sb.append("&quot;");
> +            } else if (escapeCRLF && c == '\r') {
> +                sb.append("&#13;");
> +            } else if (escapeCRLF && c == '\n') {
> +                sb.append("&#10;");
> +            } else {
> +                sb.append(c);
> +            }
> +        }
> +
> +        return sb.toString();

Maybe
sb.length() > content.length() ? sb.toString() : content

> +    }
> +}

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to