1
0
mirror of https://github.com/moparisthebest/davmail synced 2025-01-08 04:08:12 -05:00

Refactor StringUtil and encode ~ in urlcompname

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@2050 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2012-10-11 17:08:48 +00:00
parent 1165665d01
commit 0cf9f1ce80
2 changed files with 117 additions and 169 deletions

View File

@ -24,7 +24,9 @@ import org.apache.commons.codec.binary.Hex;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -128,79 +130,112 @@ public final class StringUtil {
} }
} }
static class PatternMap {
protected String match;
protected String value;
protected Pattern pattern;
protected PatternMap(String match, String value) {
this.match = match;
this.value = value;
pattern = Pattern.compile(match);
}
protected PatternMap(String match, String escapedMatch, String value) {
this.match = match;
this.value = value;
pattern = Pattern.compile(escapedMatch);
}
protected PatternMap(String match, Pattern pattern, String value) {
this.match = match;
this.value = value;
this.pattern = pattern;
}
protected String replaceAll(String string) {
if (string != null && string.indexOf(match) >= 0) {
return pattern.matcher(string).replaceAll(value);
} else {
return string;
}
}
}
private static final Pattern AMP_PATTERN = Pattern.compile("&"); private static final Pattern AMP_PATTERN = Pattern.compile("&");
private static final Pattern LT_PATTERN = Pattern.compile("<"); private static final Pattern PLUS_PATTERN = Pattern.compile("\\+");
private static final Pattern GT_PATTERN = Pattern.compile(">");
private static final Pattern PERCENT_PATTERN = Pattern.compile("%");
private static final Pattern HASH_PATTERN = Pattern.compile("#");
private static final Pattern STAR_PATTERN = Pattern.compile("\\*");
private static final Pattern QUOTE_PATTERN = Pattern.compile("\""); private static final Pattern QUOTE_PATTERN = Pattern.compile("\"");
private static final Pattern CR_PATTERN = Pattern.compile("\r"); private static final Pattern CR_PATTERN = Pattern.compile("\r");
private static final Pattern LF_PATTERN = Pattern.compile("\n"); private static final Pattern LF_PATTERN = Pattern.compile("\n");
private static final Pattern URLENCODED_F8FF_PATTERN = Pattern.compile(String.valueOf((char) 0xF8FF)); private static final List<PatternMap> URLENCODED_PATTERNS = new ArrayList<PatternMap>();
private static final Pattern URLENCODED_AMP_PATTERN = Pattern.compile("%26"); static {
private static final Pattern URLENCODED_PLUS_PATTERN = Pattern.compile("%2B"); URLENCODED_PATTERNS.add(new PatternMap(String.valueOf((char) 0xF8FF), "_xF8FF_"));
private static final Pattern URLENCODED_COLON_PATTERN = Pattern.compile("%3A"); URLENCODED_PATTERNS.add(new PatternMap("%26", "&"));
private static final Pattern URLENCODED_SEMICOLON_PATTERN = Pattern.compile("%3B"); URLENCODED_PATTERNS.add(new PatternMap("%2B", "+"));
private static final Pattern URLENCODED_LT_PATTERN = Pattern.compile("%3C"); URLENCODED_PATTERNS.add(new PatternMap("%3A", ":"));
private static final Pattern URLENCODED_GT_PATTERN = Pattern.compile("%3E"); URLENCODED_PATTERNS.add(new PatternMap("%3B", ";"));
private static final Pattern URLENCODED_QUOTE_PATTERN = Pattern.compile("%22"); URLENCODED_PATTERNS.add(new PatternMap("%3C", "<"));
private static final Pattern URLENCODED_X0D0A_PATTERN = Pattern.compile("\n"); URLENCODED_PATTERNS.add(new PatternMap("%3E", ">"));
private static final Pattern URLENCODED_PERCENT_PATTERN = Pattern.compile("%25"); URLENCODED_PATTERNS.add(new PatternMap("%22", "\""));
private static final Pattern URLENCODED_HASH_PATTERN = Pattern.compile("%23"); URLENCODED_PATTERNS.add(new PatternMap("%23", "#"));
private static final Pattern URLENCODED_STAR_PATTERN = Pattern.compile("%2A"); URLENCODED_PATTERNS.add(new PatternMap("%2A", "*"));
private static final Pattern URLENCODED_PIPE_PATTERN = Pattern.compile("%7C"); URLENCODED_PATTERNS.add(new PatternMap("%7C", "|"));
private static final Pattern URLENCODED_QUESTION_PATTERN = Pattern.compile("%3F"); URLENCODED_PATTERNS.add(new PatternMap("%3F", "?"));
URLENCODED_PATTERNS.add(new PatternMap("%7E", "~"));
private static final Pattern ENCODED_AMP_PATTERN = Pattern.compile("&amp;"); // CRLF is replaced with LF in response
private static final Pattern ENCODED_LT_PATTERN = Pattern.compile("&lt;"); URLENCODED_PATTERNS.add(new PatternMap("\n", "_x000D__x000A_"));
private static final Pattern ENCODED_GT_PATTERN = Pattern.compile("&gt;");
private static final Pattern F8FF_PATTERN = Pattern.compile("_xF8FF_"); // last replace %
private static final Pattern X0D0A_PATTERN = Pattern.compile("_x000D__x000A_"); URLENCODED_PATTERNS.add(new PatternMap("%25", "%"));
}
private static final List<PatternMap> URLENCODE_PATTERNS = new ArrayList<PatternMap>();
static {
// first replace %
URLENCODE_PATTERNS.add(new PatternMap("%", "%25"));
URLENCODE_PATTERNS.add(new PatternMap("_xF8FF_", String.valueOf((char) 0xF8FF)));
URLENCODE_PATTERNS.add(new PatternMap("&", AMP_PATTERN, "%26"));
URLENCODE_PATTERNS.add(new PatternMap("+", PLUS_PATTERN, "%2B"));
URLENCODE_PATTERNS.add(new PatternMap(":", "%3A"));
URLENCODE_PATTERNS.add(new PatternMap(";", "%3B"));
URLENCODE_PATTERNS.add(new PatternMap("<", "%3C"));
URLENCODE_PATTERNS.add(new PatternMap(">", "%3E"));
URLENCODE_PATTERNS.add(new PatternMap("\"", "%22"));
URLENCODE_PATTERNS.add(new PatternMap("#", "%23"));
URLENCODE_PATTERNS.add(new PatternMap("~", "%7E"));
URLENCODE_PATTERNS.add(new PatternMap("*", "\\*", "%2A"));
URLENCODE_PATTERNS.add(new PatternMap("|", "\\|", "%7C"));
URLENCODE_PATTERNS.add(new PatternMap("?", "\\?", "%3F"));
URLENCODE_PATTERNS.add(new PatternMap("_x000D__x000A_", "\r\n"));
}
private static final List<PatternMap> XML_DECODE_PATTERNS = new ArrayList<PatternMap>();
static {
XML_DECODE_PATTERNS.add(new PatternMap("&amp;", "&"));
XML_DECODE_PATTERNS.add(new PatternMap("&lt;", "<"));
XML_DECODE_PATTERNS.add(new PatternMap("&gt;", ">"));
}
private static final List<PatternMap> XML_ENCODE_PATTERNS = new ArrayList<PatternMap>();
static {
XML_ENCODE_PATTERNS.add(new PatternMap("&", AMP_PATTERN, "&amp;"));
XML_ENCODE_PATTERNS.add(new PatternMap("<", "&lt;"));
XML_ENCODE_PATTERNS.add(new PatternMap(">", "&gt;"));
}
private static final Pattern PLUS_PATTERN = Pattern.compile("\\+");
private static final Pattern COLON_PATTERN = Pattern.compile(":");
private static final Pattern SEMICOLON_PATTERN = Pattern.compile(";");
private static final Pattern SLASH_PATTERN = Pattern.compile("/"); private static final Pattern SLASH_PATTERN = Pattern.compile("/");
private static final Pattern UNDERSCORE_PATTERN = Pattern.compile("_"); private static final Pattern UNDERSCORE_PATTERN = Pattern.compile("_");
private static final Pattern DASH_PATTERN = Pattern.compile("-"); private static final Pattern DASH_PATTERN = Pattern.compile("-");
private static final Pattern PIPE_PATTERN = Pattern.compile("\\|");
private static final Pattern QUESTION_PATTERN = Pattern.compile("\\?");
// WebDav search parameter encode // WebDav search parameter encode
private static final Pattern APOS_PATTERN = Pattern.compile("'"); private static final Pattern APOS_PATTERN = Pattern.compile("'");
/**
* Encode & to %26 for urlcompname.
*
* @param name decoded name
* @return name encoded name
*/
public static String urlEncodeAmpersand(String name) {
String result = name;
if (name.indexOf('&') >= 0) {
result = AMP_PATTERN.matcher(result).replaceAll("%26");
}
return result;
}
/**
* Decode %26 to & for urlcompname.
*
* @param name decoded name
* @return name encoded name
*/
public static String urlDecodeAmpersand(String name) {
String result = name;
if (name != null && name.indexOf("%26") >= 0) {
result = URLENCODED_AMP_PATTERN.matcher(result).replaceAll("&");
}
return result;
}
/** /**
* Xml encode content. * Xml encode content.
* *
@ -209,15 +244,9 @@ public final class StringUtil {
*/ */
public static String xmlEncode(String name) { public static String xmlEncode(String name) {
String result = name; String result = name;
if (name != null) { if (result != null) {
if (name.indexOf('&') >= 0) { for (PatternMap patternMap : XML_ENCODE_PATTERNS) {
result = AMP_PATTERN.matcher(result).replaceAll("&amp;"); result = patternMap.replaceAll(result);
}
if (name.indexOf('<') >= 0) {
result = LT_PATTERN.matcher(result).replaceAll("&lt;");
}
if (name.indexOf('>') >= 0) {
result = GT_PATTERN.matcher(result).replaceAll("&gt;");
} }
} }
return result; return result;
@ -253,14 +282,10 @@ public final class StringUtil {
*/ */
public static String xmlDecode(String name) { public static String xmlDecode(String name) {
String result = name; String result = name;
if (name.indexOf("&amp;") >= 0) { if (result != null) {
result = ENCODED_AMP_PATTERN.matcher(result).replaceAll("&"); for (PatternMap patternMap : XML_DECODE_PATTERNS) {
result = patternMap.replaceAll(result);
} }
if (name.indexOf("&lt;") >= 0) {
result = ENCODED_LT_PATTERN.matcher(result).replaceAll("<");
}
if (name.indexOf("&gt;") >= 0) {
result = ENCODED_GT_PATTERN.matcher(result).replaceAll(">");
} }
return result; return result;
} }
@ -302,47 +327,10 @@ public final class StringUtil {
*/ */
public static String encodeUrlcompname(String value) { public static String encodeUrlcompname(String value) {
String result = value; String result = value;
if (result.indexOf('%') >= 0) { if (result != null) {
result = PERCENT_PATTERN.matcher(result).replaceAll("%25"); for (PatternMap patternMap : URLENCODE_PATTERNS) {
result = patternMap.replaceAll(result);
} }
if (result.indexOf("_xF8FF_") >= 0) {
result = F8FF_PATTERN.matcher(result).replaceAll(String.valueOf((char) 0xF8FF));
}
if (result.indexOf('&') >= 0) {
result = AMP_PATTERN.matcher(result).replaceAll("%26");
}
if (result.indexOf('+') >= 0) {
result = PLUS_PATTERN.matcher(result).replaceAll("%2B");
}
if (result.indexOf(':') >= 0) {
result = COLON_PATTERN.matcher(result).replaceAll("%3A");
}
if (result.indexOf(';') >= 0) {
result = SEMICOLON_PATTERN.matcher(result).replaceAll("%3B");
}
if (result.indexOf('<') >= 0) {
result = LT_PATTERN.matcher(result).replaceAll("%3C");
}
if (result.indexOf('>') >= 0) {
result = GT_PATTERN.matcher(result).replaceAll("%3E");
}
if (result.indexOf('"') >= 0) {
result = QUOTE_PATTERN.matcher(result).replaceAll("%22");
}
if (result.indexOf('#') >= 0) {
result = HASH_PATTERN.matcher(result).replaceAll("%23");
}
if (result.indexOf('*') >= 0) {
result = STAR_PATTERN.matcher(result).replaceAll("%2A");
}
if (result.indexOf("_x000D__x000A_") >= 0) {
result = X0D0A_PATTERN.matcher(result).replaceAll("\r\n");
}
if (result.indexOf('|') >= 0) {
result = PIPE_PATTERN.matcher(result).replaceAll("%7C");
}
if (result.indexOf('?') >= 0) {
result = QUESTION_PATTERN.matcher(result).replaceAll("%3F");
} }
return result; return result;
} }
@ -356,49 +344,8 @@ public final class StringUtil {
public static String decodeUrlcompname(String urlcompname) { public static String decodeUrlcompname(String urlcompname) {
String result = urlcompname; String result = urlcompname;
if (result != null) { if (result != null) {
if (result.indexOf((char) 0xF8FF) >= 0) { for (PatternMap patternMap : URLENCODED_PATTERNS) {
result = URLENCODED_F8FF_PATTERN.matcher(result).replaceAll("_xF8FF_"); result = patternMap.replaceAll(result);
}
if (result.indexOf("%26") >= 0) {
result = URLENCODED_AMP_PATTERN.matcher(result).replaceAll("&");
}
if (result.indexOf("%2B") >= 0) {
result = URLENCODED_PLUS_PATTERN.matcher(result).replaceAll("+");
}
if (result.indexOf("%3A") >= 0) {
result = URLENCODED_COLON_PATTERN.matcher(result).replaceAll(":");
}
if (result.indexOf("%3B") >= 0) {
result = URLENCODED_SEMICOLON_PATTERN.matcher(result).replaceAll(";");
}
if (result.indexOf("%3C") >= 0) {
result = URLENCODED_LT_PATTERN.matcher(result).replaceAll("<");
}
if (result.indexOf("%3E") >= 0) {
result = URLENCODED_GT_PATTERN.matcher(result).replaceAll(">");
}
if (result.indexOf("%22") >= 0) {
result = URLENCODED_QUOTE_PATTERN.matcher(result).replaceAll("\"");
}
// CRLF is replaced with LF in response
if (result.indexOf('\n') >= 0) {
result = URLENCODED_X0D0A_PATTERN.matcher(result).replaceAll("_x000D__x000A_");
}
if (result.indexOf("%23") >= 0) {
result = URLENCODED_HASH_PATTERN.matcher(result).replaceAll("#");
}
if (result.indexOf("%2A") >= 0) {
result = URLENCODED_STAR_PATTERN.matcher(result).replaceAll("*");
}
if (result.indexOf("%7C") >= 0) {
result = URLENCODED_PIPE_PATTERN.matcher(result).replaceAll("|");
}
if (result.indexOf("%3F") >= 0) {
result = URLENCODED_QUESTION_PATTERN.matcher(result).replaceAll("?");
}
// last replace %
if (result.indexOf("%25") >= 0) {
result = URLENCODED_PERCENT_PATTERN.matcher(result).replaceAll("%");
} }
} }
return result; return result;

View File

@ -60,22 +60,17 @@ public class StringUtilTest extends TestCase {
assertEquals("&lt;test&gt;", StringUtil.xmlEncode("<test>")); assertEquals("&lt;test&gt;", StringUtil.xmlEncode("<test>"));
} }
public void testUrlEncodeAmpersand() {
assertEquals("%26", StringUtil.urlEncodeAmpersand("&"));
assertEquals("&", StringUtil.urlDecodeAmpersand("%26"));
}
public void testPerf() { public void testPerf() {
String value = "dqsdqs+dsqds+dsqdqs"; String value = "dqsdqs+dsqds+dsqdqs";
for (int j = 0; j < 5; j++) { for (int j = 0; j < 5; j++) {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) { for (int i = 0; i < 1000000; i++) {
//String result = StringUtil.encodePlusSign(value); //String result = StringUtil.encodePlusSign(value);
//String result = StringUtil.replaceAll(value, '+', "%2B"); //String result = value.replaceAll("\\+", "%2B");
/*int length = value.length(); int length = value.length();
StringBuilder buffer = new StringBuilder(length); StringBuilder buffer = new StringBuilder(length);
int startIndex = 0; /*int startIndex = 0;
int endIndex = value.indexOf('+'); int endIndex = value.indexOf('+');
while (endIndex >= 0) { while (endIndex >= 0) {
buffer.append(value.substring(startIndex, endIndex)); buffer.append(value.substring(startIndex, endIndex));
@ -83,8 +78,8 @@ public class StringUtilTest extends TestCase {
startIndex = endIndex + 1; startIndex = endIndex + 1;
endIndex = value.indexOf('+', startIndex); endIndex = value.indexOf('+', startIndex);
} }
buffer.append(value.substring(startIndex)); */ buffer.append(value.substring(startIndex));*/
/*
for (int k = 0; k < length; k++) { for (int k = 0; k < length; k++) {
char c = value.charAt(k); char c = value.charAt(k);
if (c == '+') { if (c == '+') {
@ -92,7 +87,7 @@ public class StringUtilTest extends TestCase {
} else { } else {
buffer.append(c); buffer.append(c);
} }
}*/ }
//String result = buffer.toString(); //String result = buffer.toString();
//String result = value.replaceAll("\\+", "%2B"); //String result = value.replaceAll("\\+", "%2B");
} }
@ -119,4 +114,10 @@ public class StringUtilTest extends TestCase {
assertEquals("test %3F", StringUtil.encodeUrlcompname("test ?")); assertEquals("test %3F", StringUtil.encodeUrlcompname("test ?"));
assertEquals("test ?", StringUtil.decodeUrlcompname("test %3F")); assertEquals("test ?", StringUtil.decodeUrlcompname("test %3F"));
} }
public void testEncodeUrlCompname() {
assertEquals("test %7E", StringUtil.encodeUrlcompname("test ~"));
assertEquals("test ~", StringUtil.decodeUrlcompname("test %7E"));
}
} }