diff --git a/org.springframework.core/src/main/java/org/springframework/util/StringUtils.java b/org.springframework.core/src/main/java/org/springframework/util/StringUtils.java index e86ab49793..3e1960870f 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/StringUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/util/StringUtils.java @@ -665,16 +665,11 @@ public abstract class StringUtils { * @return a corresponding Locale instance */ public static Locale parseLocaleString(String localeString) { - for (int i = 0; i < localeString.length(); i++) { - char ch = localeString.charAt(i); - if (ch != '_' && ch != ' ' && !Character.isLetterOrDigit(ch)) { - throw new IllegalArgumentException( - "Locale value \"" + localeString + "\" contains invalid characters"); - } - } String[] parts = tokenizeToStringArray(localeString, "_ ", false, false); String language = (parts.length > 0 ? parts[0] : ""); String country = (parts.length > 1 ? parts[1] : ""); + validateLocalePart(language); + validateLocalePart(country); String variant = ""; if (parts.length >= 2) { // There is definitely a variant, and it is everything after the country @@ -689,6 +684,16 @@ public abstract class StringUtils { return (language.length() > 0 ? new Locale(language, country, variant) : null); } + private static void validateLocalePart(String localePart) { + for (int i = 0; i < localePart.length(); i++) { + char ch = localePart.charAt(i); + if (ch != '_' && ch != ' ' && !Character.isLetterOrDigit(ch)) { + throw new IllegalArgumentException( + "Locale part \"" + localePart + "\" contains invalid characters"); + } + } + } + /** * Determine the RFC 3066 compliant language tag, * as used for the HTTP "Accept-Language" header. diff --git a/org.springframework.core/src/test/java/org/springframework/util/StringUtilsTests.java b/org.springframework.core/src/test/java/org/springframework/util/StringUtilsTests.java index 320b7363c6..65cf242724 100644 --- a/org.springframework.core/src/test/java/org/springframework/util/StringUtilsTests.java +++ b/org.springframework.core/src/test/java/org/springframework/util/StringUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -268,21 +268,26 @@ public class StringUtilsTests extends TestCase { assertEquals(null, StringUtils.getFilenameExtension("")); assertEquals(null, StringUtils.getFilenameExtension("myfile")); assertEquals(null, StringUtils.getFilenameExtension("myPath/myfile")); + assertEquals(null, StringUtils.getFilenameExtension("/home/user/.m2/settings/myfile")); assertEquals("", StringUtils.getFilenameExtension("myfile.")); assertEquals("", StringUtils.getFilenameExtension("myPath/myfile.")); assertEquals("txt", StringUtils.getFilenameExtension("myfile.txt")); assertEquals("txt", StringUtils.getFilenameExtension("mypath/myfile.txt")); + assertEquals("txt", StringUtils.getFilenameExtension("/home/user/.m2/settings/myfile.txt")); } public void testStripFilenameExtension() { assertEquals(null, StringUtils.stripFilenameExtension(null)); assertEquals("", StringUtils.stripFilenameExtension("")); assertEquals("myfile", StringUtils.stripFilenameExtension("myfile")); - assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile")); assertEquals("myfile", StringUtils.stripFilenameExtension("myfile.")); - assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile.")); assertEquals("myfile", StringUtils.stripFilenameExtension("myfile.txt")); + assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile")); + assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile.")); assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile.txt")); + assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile")); + assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile.")); + assertEquals("/home/user/.m2/settings/myfile", StringUtils.stripFilenameExtension("/home/user/.m2/settings/myfile.txt")); } public void testCleanPath() { @@ -561,6 +566,16 @@ public class StringUtilsTests extends TestCase { assertNull("When given an empty Locale string, must return null.", locale); } + /** + * See SPR-8637. + */ + public void testParseLocaleWithMultiSpecialCharactersInVariant() throws Exception { + final String variant = "proper-northern"; + final String localeString = "en_GB_" + variant; + Locale locale = StringUtils.parseLocaleString(localeString); + assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant()); + } + /** * See SPR-3671. */ @@ -611,4 +626,17 @@ public class StringUtilsTests extends TestCase { assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant()); } + /** + * See SPR-7779. + */ + public void testParseLocaleWithInvalidCharacters() { + try { + StringUtils.parseLocaleString("%0D%0AContent-length:30%0D%0A%0D%0A%3Cscript%3Ealert%28123%29%3C/script%3E"); + fail("Should have thrown IllegalArgumentException"); + } + catch (IllegalArgumentException ex) { + // expected + } + } + }