2014-08-15 16:47 GMT+04:00  <ma...@apache.org>:
> Author: markt
> Date: Fri Aug 15 12:47:56 2014
> New Revision: 1618166
>
> URL: http://svn.apache.org/r1618166
> Log:
> Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56848
> Improve handling of <code>accept-language</code> headers.
>
> Added:
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/AcceptLanguage.java  
>  (with props)
>     
> tomcat/trunk/test/org/apache/tomcat/util/http/parser/TestAcceptLanguage.java  
>  (with props)
> Modified:
>     tomcat/trunk/java/org/apache/catalina/connector/Request.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/Authorization.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/HttpParser.java
>     tomcat/trunk/java/org/apache/tomcat/util/http/parser/MediaType.java
>     tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java
>     tomcat/trunk/test/org/apache/catalina/connector/TesterRequest.java
>     tomcat/trunk/webapps/docs/changelog.xml
>
> Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java
> URL: 
> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1618166&r1=1618165&r2=1618166&view=diff
> ==============================================================================
> --- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
> +++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Fri Aug 15 
> 12:47:56 2014
> @@ -21,6 +21,7 @@ import java.io.BufferedReader;
>  import java.io.File;
>  import java.io.IOException;
>  import java.io.InputStream;
> +import java.io.StringReader;
>  import java.io.UnsupportedEncodingException;
>  import java.lang.reflect.InvocationTargetException;
>  import java.nio.charset.Charset;
> @@ -76,7 +77,6 @@ import org.apache.catalina.core.Applicat
>  import org.apache.catalina.core.AsyncContextImpl;
>  import org.apache.catalina.mapper.MappingData;
>  import org.apache.catalina.util.ParameterMap;
> -import org.apache.catalina.util.StringParser;
>  import org.apache.coyote.ActionCode;
>  import org.apache.juli.logging.Log;
>  import org.apache.juli.logging.LogFactory;
> @@ -95,6 +95,7 @@ import org.apache.tomcat.util.http.fileu
>  import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
>  import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
>  import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
> +import org.apache.tomcat.util.http.parser.AcceptLanguage;
>  import org.apache.tomcat.util.res.StringManager;
>  import org.ietf.jgss.GSSCredential;
>  import org.ietf.jgss.GSSException;
> @@ -367,12 +368,6 @@ public class Request
>
>
>      /**
> -     * The string parser we will use for parsing request lines.
> -     */
> -    private final StringParser parser = new StringParser();

As a result, the o.a.c.util.StringParser class is no longer used anywhere.

> -
> -
> -    /**
>       * Local port
>       */
>      protected int localPort = -1;
> @@ -3114,99 +3109,24 @@ public class Request
>       */
>      protected void parseLocalesHeader(String value, TreeMap<Double, 
> ArrayList<Locale>> locales) {
>
> -        // Preprocess the value to remove all whitespace
> -        int white = value.indexOf(' ');
> -        if (white < 0) {
> -            white = value.indexOf('\t');
> -        }
> -        if (white >= 0) {
> -            StringBuilder sb = new StringBuilder();
> -            int len = value.length();
> -            for (int i = 0; i < len; i++) {
> -                char ch = value.charAt(i);
> -                if ((ch != ' ') && (ch != '\t')) {
> -                    sb.append(ch);
> -                }
> -            }
> -            parser.setString(sb.toString());
> -        } else {
> -            parser.setString(value);
> +        List<AcceptLanguage> acceptLanguages;
> +        try {
> +            acceptLanguages = AcceptLanguage.parse(new StringReader(value));
> +        } catch (IOException e) {
> +            // Mal-formed headers are ignore. Do the same in the unlikely 
> event
> +            // of an IOException.
> +            return;
>          }
>
> -        // Process each comma-delimited language specification
> -        int length = parser.getLength();
> -        while (true) {
> -
> -            // Extract the next comma-delimited entry
> -            int start = parser.getIndex();
> -            if (start >= length) {
> -                break;
> -            }
> -            int end = parser.findChar(',');
> -            String entry = parser.extract(start, end).trim();
> -            parser.advance();   // For the following entry
> -
> -            // Extract the quality factor for this entry
> -            double quality = 1.0;
> -            int semi = entry.indexOf(";q=");
> -            if (semi >= 0) {
> -                try {
> -                    String strQuality = entry.substring(semi + 3);
> -                    if (strQuality.length() <= 5) {
> -                        quality = Double.parseDouble(strQuality);
> -                    } else {
> -                        quality = 0.0;
> -                    }
> -                } catch (NumberFormatException e) {
> -                    quality = 0.0;
> -                }
> -                entry = entry.substring(0, semi);
> -            }
> -
> -            // Skip entries we are not going to keep track of
> -            if (quality < 0.00005)
> -             {
> -                continue;       // Zero (or effectively zero) quality factors
> -            }
> -            if ("*".equals(entry))
> -             {
> -                continue;       // FIXME - "*" entries are not handled
> -            }
> -
> -            // Extract the language and country for this entry
> -            String language = null;
> -            String country = null;
> -            String variant = null;
> -            int dash = entry.indexOf('-');
> -            if (dash < 0) {
> -                language = entry;
> -                country = "";
> -                variant = "";
> -            } else {
> -                language = entry.substring(0, dash);
> -                country = entry.substring(dash + 1);
> -                int vDash = country.indexOf('-');
> -                if (vDash > 0) {
> -                    String cTemp = country.substring(0, vDash);
> -                    variant = country.substring(vDash + 1);
> -                    country = cTemp;
> -                } else {
> -                    variant = "";
> -                }
> -            }
> -            if (!isAlpha(language) || !isAlpha(country) || 
> !isAlpha(variant)) {
> -                continue;
> -            }
> -
> +        for (AcceptLanguage acceptLanguage : acceptLanguages) {
>              // Add a new Locale to the list of Locales for this quality level
> -            Locale locale = new Locale(language, country, variant);
> -            Double key = new Double(-quality);  // Reverse the order
> +            Double key = new Double(-acceptLanguage.getQuality());  // 
> Reverse the order
>              ArrayList<Locale> values = locales.get(key);
>              if (values == null) {
>                  values = new ArrayList<>();
>                  locales.put(key, values);
>              }
> -            values.add(locale);
> +            values.add(acceptLanguage.getLocale());
>          }
>      }
>
>
> Added: 
> tomcat/trunk/java/org/apache/tomcat/util/http/parser/AcceptLanguage.java
> URL: 
> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/parser/AcceptLanguage.java?rev=1618166&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/tomcat/util/http/parser/AcceptLanguage.java 
> (added)
> +++ tomcat/trunk/java/org/apache/tomcat/util/http/parser/AcceptLanguage.java 
> Fri Aug 15 12:47:56 2014
> @@ -0,0 +1,76 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one or more
> + *  contributor license agreements.  See the NOTICE file distributed with
> + *  this work for additional information regarding copyright ownership.
> + *  The ASF licenses this file to You under the Apache License, Version 2.0
> + *  (the "License"); you may not use this file except in compliance with
> + *  the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + */
> +package org.apache.tomcat.util.http.parser;
> +
> +import java.io.IOException;
> +import java.io.StringReader;
> +import java.util.ArrayList;
> +import java.util.List;
> +import java.util.Locale;
> +
> +public class AcceptLanguage {
> +
> +    private final Locale locale;
> +    private final double quality;
> +
> +    protected AcceptLanguage(Locale locale, double quality) {
> +        this.locale = locale;
> +        this.quality = quality;
> +    }
> +
> +    public Locale getLocale() {
> +        return locale;
> +    }
> +
> +    public double getQuality() {
> +        return quality;
> +    }
> +
> +
> +    public static List<AcceptLanguage> parse(StringReader input) throws 
> IOException {
> +
> +        List<AcceptLanguage> result = new ArrayList<>();
> +
> +        do {
> +            // Token is broader than what is permitted in a language tag
> +            // (alphanumeric + '-') but any invalid values that slip through
> +            // will be caught later
> +            String languageTag = HttpParser.readToken(input);
> +            if (languageTag == null) {
> +                // Invalid tag, skip to the next one
> +                HttpParser.skipUntil(input, 0, ',');
> +                continue;
> +            }
> +
> +            if (languageTag.length() == 0) {
> +                // No more data to read
> +                break;
> +            }
> +
> +            // See if a quality has been provided
> +            double quality = 1;
> +            HttpParser.SkipResult lookForSemiColon = 
> HttpParser.skipConstant(input, ";");
> +            if (lookForSemiColon == HttpParser.SkipResult.FOUND) {
> +                quality = HttpParser.readWeight(input, ',');
> +            }
> +

If readWeight() above returns 0 (invalid weight value detected),  it
would better to just skip the next line that creates an AcceptLanguage
object.

> +            result.add(new 
> AcceptLanguage(Locale.forLanguageTag(languageTag), quality));
> +        } while (true);
> +
> +        return result;
> +    }
> +}
>

(...)

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

Reply via email to