18403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Copyright (c) 2011, Mike Samuel 28403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// All rights reserved. 38403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// 48403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistribution and use in source and binary forms, with or without 58403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// modification, are permitted provided that the following conditions 68403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// are met: 78403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// 88403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions of source code must retain the above copyright 98403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer. 108403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Redistributions in binary form must reproduce the above copyright 118403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// notice, this list of conditions and the following disclaimer in the 128403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// documentation and/or other materials provided with the distribution. 138403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// Neither the name of the OWASP nor the names of its contributors may 148403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// be used to endorse or promote products derived from this software 158403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// without specific prior written permission. 168403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 178403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 188403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 198403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 208403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 218403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 228403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 248403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 268403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 278403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel// POSSIBILITY OF SUCH DAMAGE. 288403881c365ab36b721ccc4500af1b3a5bd25870mikesamuel 295c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.compackage org.owasp.html; 305c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 315c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.comimport javax.annotation.Nullable; 325c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 335c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com/** 345c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * Locale independent versions of String case-insensitive operations. 355c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * <p> 365c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * The normal case insensitive operators {@link String#toLowerCase} 375c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * and {@link String#equalsIgnoreCase} depend upon the current locale. 385c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * They will fold the letters "i" and "I" differently if the locale is 395c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * Turkish than if it is English. 405c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * <p> 415c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * These operations ignore all case folding for non-Roman letters, and are 424e867904c8295537803c1c8a076e130df5674b58mikesamuel * independent of the current locale. 434e867904c8295537803c1c8a076e130df5674b58mikesamuel * Lower-casing is exactly equivalent to {@code tr/A-Z/a-z/}, upper-casing to 445c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * {@code tr/a-z/A-Z/}, and case insensitive comparison is equivalent to 454e867904c8295537803c1c8a076e130df5674b58mikesamuel * lower-casing both then comparing by code-unit. 465c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * <p> 475c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * Because of this simpler case folding, it is the case that for all Strings s 485c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * <code> 495c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * Strings.toUpperCase(s).equals(Strings.toUpperCase(Strings.toLowerCase(s))) 505c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * </code>. 515c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com * 524e867904c8295537803c1c8a076e130df5674b58mikesamuel * @author Mike Samuel <mikesamuel@gmail.com> 535c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com */ 544e867904c8295537803c1c8a076e130df5674b58mikesamuelfinal class Strings { 554e867904c8295537803c1c8a076e130df5674b58mikesamuel public static boolean equalsIgnoreCase( 564e867904c8295537803c1c8a076e130df5674b58mikesamuel @Nullable String a, @Nullable String b) { 575c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (a == null) { return b == null; } 585c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (b == null) { return false; } 595c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com int length = a.length(); 605c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (b.length() != length) { return false; } 618560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel for (int i = length; --i >= 0;) { 628560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel char c = a.charAt(i), d = b.charAt(i); 638560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (c != d) { 648560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (c <= 'z' && c >= 'A') { 658560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (c <= 'Z') { c |= 0x20; } 668560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (d <= 'Z' && d >= 'A') { d |= 0x20; } 678560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (c == d) { continue; } 688560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel } 698560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel return false; 708560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel } 718560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel } 728560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel return true; 735c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 745c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 755c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com public static boolean regionMatchesIgnoreCase( 768560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel CharSequence a, int aoffset, CharSequence b, int boffset, int n) { 778560af5e2982092cb27cce62aa9cfa5bb45ea387mikesamuel if (aoffset + n > a.length() || boffset + n > b.length()) { return false; } 785c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = n; --i >= 0;) { 795c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char c = a.charAt(aoffset + i), d = b.charAt(boffset + i); 805c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c != d) { 815c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'z' && c >= 'A') { 825c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'Z') { c |= 0x20; } 835c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (d <= 'Z' && d >= 'A') { d |= 0x20; } 845c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c == d) { continue; } 855c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 865c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return false; 875c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 885c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 895c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return true; 905c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 915c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 925c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com /** True iff {@code s.equals(String.toLowerCase(s))}. */ 935c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com public static boolean isLowerCase(CharSequence s) { 945c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = s.length(); --i >= 0;) { 955c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char c = s.charAt(i); 965c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'Z' && c >= 'A') { 975c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return false; 985c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 995c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1005c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return true; 1015c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1025c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 1035c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com private static final char[] LCASE_CHARS = new char['Z' + 1]; 1045c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com private static final char[] UCASE_CHARS = new char['z' + 1]; 1055c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com static { 1065c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = 0; i < 'A'; ++i) { LCASE_CHARS[i] = (char) i; } 1075c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = 'A'; i <= 'Z'; ++i) { LCASE_CHARS[i] = (char) (i | 0x20); } 1085c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = 0; i < 'a'; ++i) { UCASE_CHARS[i] = (char) i; } 1095c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = 'a'; i <= 'z'; ++i) { UCASE_CHARS[i] = (char) (i & ~0x20); } 1105c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1115c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com public static String toLowerCase(String s) { 1125c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = s.length(); --i >= 0;) { 1135c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char c = s.charAt(i); 1145c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'Z' && c >= 'A') { 1155c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char[] chars = s.toCharArray(); 1165c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com chars[i] = LCASE_CHARS[c]; 1175c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com while (--i >= 0) { 1185c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com c = chars[i]; 1195c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'Z') { 1205c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com chars[i] = LCASE_CHARS[c]; 1215c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1225c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1235c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return String.valueOf(chars); 1245c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1255c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1265c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return s; 1275c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1285c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 1295c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com public static String toUpperCase(String s) { 1305c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com for (int i = s.length(); --i >= 0;) { 1315c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char c = s.charAt(i); 1325c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'z' && c >= 'a') { 1335c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com char[] chars = s.toCharArray(); 1345c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com chars[i] = UCASE_CHARS[c]; 1355c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com while (--i >= 0) { 1365c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com c = chars[i]; 1375c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com if (c <= 'z') { 1385c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com chars[i] = UCASE_CHARS[c]; 1395c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1405c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1415c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return String.valueOf(chars); 1425c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1435c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1445c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com return s; 1455c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com } 1465c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com 1475c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com private Strings() { /* uninstantiable */ } 1485c702c12be71d8070da9287cc4a044617dd726a7manico.james@gmail.com} 149