private static void encodeURIQuery()

in impl/src/main/java/org/apache/myfaces/renderkit/html/util/HTMLEncoder.java [1222:1340]


    private static void encodeURIQuery(Writer writer, final String string, int offset, final String characterEncoding)
            throws IOException
    {
        int start = offset;
        int length = string.length();
        int realLength = length-offset;
        String app;
        char c;

        for (int i = offset; i < length; ++i)
        {
            app = null;
            c = string.charAt(i);
            
            // - From %00 to %20 (' ' %20 could encode as +, but %20 also works, so we keep %20)
            // - <"> %22 (If there is encode of "%", there is a risk of duplicate encoding, so 
            //            we make easier and omit this one)
            // - "<" %3C, ">" %3E,
            // - "\" %5C, "^" %5E, "`" %60 
            // - "{" %7B, "|" %7C, "}" %7D
            // - From %7F ad infinitum (each character as many bytes as necessary but take into account
            //   that a single char should contain 2,3 or more bytes!. This data should be encoded 
            //   translating from the document character encoding to percent encoding)
            //
            // "&" should be encoded as "&amp;" because this link is inside an html page, and 
            // put & is invalid in this context   
            
            if (   (c <= (char)0x20) || (c >= (char)0x7F) || 
                    c == '"' || c == '<' ||
                    c == '>' || c == '\\' || c == '^' || c == '`' ||
                    c == '{' || c == '|' || c == '}')
            {
                // The percent encoding on this part should be done using UTF-8 charset
                // as RFC 3986 Section 3.2.2 says
                if (start < i)
                {
                    writer.write(string, start, i-start);
                }
                start = i+1;
                percentEncode(writer, c, characterEncoding);
            }
            else if (c == '%')
            {
                if (i + 2 < length)
                {
                    char c1 = string.charAt(i+1);
                    char c2 = string.charAt(i+2);
                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                    {
                        // do not percent encode, because it could be already encoded
                    }
                    else
                    {
                        if (start < i)
                        {
                            writer.write(string, start, i-start);
                        }
                        start = i+1;
                        percentEncode(writer, c, characterEncoding);
                    }
                }
                else
                {
                    //app = percentEncode(c, characterEncoding);
                    if (start < i)
                    {
                        writer.write(string, start, i-start);
                    }
                    start = i+1;
                    percentEncode(writer, c, characterEncoding);
                }
            }
            else if (c == '&')
            {
                if (i+4 < length )
                {
                    if ('a' == string.charAt(i+1) &&
                        'm' == string.charAt(i+2) &&
                        'p' == string.charAt(i+3) &&
                        ';' == string.charAt(i+4))
                    {
                        //Skip
                    }
                    else
                    {
                        app = "&amp;";
                    }
                }
                else
                {
                    app = "&amp;";
                }
            }
            else
            {
                //No encoding, just do nothing, char will be added later.
            }
                        
            if (app != null)
            {
                if (start < i)
                {
                    writer.write(string, start, i-start);
                }
                start = i+1;
                writer.write(app);
            }
        }

        if (start == offset)
        {
            writer.write(string, offset, realLength);
        }
        else if (start < length)
        {
            writer.write(string,start,length-start);
        }
    }