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