mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-10 17:49:38 +02:00
Improve StringUtils.escapeForXml()
This commit is contained in:
parent
f2a748db9a
commit
e6a9027cc6
11 changed files with 169 additions and 43 deletions
|
@ -497,7 +497,7 @@ public class PacketParserUtils {
|
|||
CharSequence text = parser.getText();
|
||||
if (event == XmlPullParser.TEXT) {
|
||||
// TODO the toString() can be removed in Smack 4.2.
|
||||
text = StringUtils.escapeForXML(text.toString());
|
||||
text = StringUtils.escapeForXmlText(text.toString());
|
||||
}
|
||||
sb.append(text);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2007 Jive Software.
|
||||
* Copyright 2003-2007 Jive Software, 2016 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -41,6 +41,74 @@ public class StringUtils {
|
|||
|
||||
public static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
|
||||
|
||||
/**
|
||||
* Escape <code>input</code> for XML.
|
||||
*
|
||||
* @param input the input to escape.
|
||||
* @return the XML escaped variant of <code>input</code>.
|
||||
* @deprecated use {@link #escapeForXml(CharSequence)} instead.
|
||||
*/
|
||||
// Remove in 4.3.
|
||||
@Deprecated
|
||||
public static CharSequence escapeForXML(CharSequence input) {
|
||||
return escapeForXml(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape <code>input</code> for XML.
|
||||
*
|
||||
* @param input the input to escape.
|
||||
* @return the XML escaped variant of <code>input</code>.
|
||||
*/
|
||||
public static CharSequence escapeForXml(CharSequence input) {
|
||||
return escapeForXml(input, XmlEscapeMode.safe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape <code>input</code> for XML.
|
||||
*
|
||||
* @param input the input to escape.
|
||||
* @return the XML escaped variant of <code>input</code>.
|
||||
* @since 4.2
|
||||
*/
|
||||
public static CharSequence escapeForXmlAttribute(CharSequence input) {
|
||||
return escapeForXml(input, XmlEscapeMode.forAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape <code>input</code> for XML.
|
||||
* <p>
|
||||
* This is an optimized variant of {@link #escapeForXmlAttribute(CharSequence)} for XML where the
|
||||
* XML attribute is quoted using ''' (Apos).
|
||||
* </p>
|
||||
*
|
||||
* @param input the input to escape.
|
||||
* @return the XML escaped variant of <code>input</code>.
|
||||
* @since 4.2
|
||||
*/
|
||||
public static CharSequence escapeForXmlAttributeApos(CharSequence input) {
|
||||
return escapeForXml(input, XmlEscapeMode.forAttributeApos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape <code>input</code> for XML.
|
||||
*
|
||||
* @param input the input to escape.
|
||||
* @return the XML escaped variant of <code>input</code>.
|
||||
* @since 4.2
|
||||
*/
|
||||
public static CharSequence escapeForXmlText(CharSequence input) {
|
||||
return escapeForXml(input, XmlEscapeMode.forText);
|
||||
}
|
||||
|
||||
private enum XmlEscapeMode {
|
||||
safe,
|
||||
forAttribute,
|
||||
forAttributeApos,
|
||||
forText,
|
||||
;
|
||||
};
|
||||
|
||||
/**
|
||||
* Escapes all necessary characters in the CharSequence so that it can be used
|
||||
* in an XML doc.
|
||||
|
@ -48,7 +116,7 @@ public class StringUtils {
|
|||
* @param input the CharSequence to escape.
|
||||
* @return the string with appropriate characters escaped.
|
||||
*/
|
||||
public static CharSequence escapeForXML(final CharSequence input) {
|
||||
private static CharSequence escapeForXml(final CharSequence input, final XmlEscapeMode xmlEscapeMode) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -61,23 +129,75 @@ public class StringUtils {
|
|||
while (i < len) {
|
||||
toAppend = null;
|
||||
ch = input.charAt(i);
|
||||
switch(ch) {
|
||||
case '<':
|
||||
toAppend = LT_ENCODE;
|
||||
switch (xmlEscapeMode) {
|
||||
case safe:
|
||||
switch (ch) {
|
||||
case '<':
|
||||
toAppend = LT_ENCODE;
|
||||
break;
|
||||
case '>':
|
||||
toAppend = GT_ENCODE;
|
||||
break;
|
||||
case '&':
|
||||
toAppend = AMP_ENCODE;
|
||||
break;
|
||||
case '"':
|
||||
toAppend = QUOTE_ENCODE;
|
||||
break;
|
||||
case '\'':
|
||||
toAppend = APOS_ENCODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
toAppend = GT_ENCODE;
|
||||
case forAttribute:
|
||||
// No need to escape '>' for attributes.
|
||||
switch(ch) {
|
||||
case '<':
|
||||
toAppend = LT_ENCODE;
|
||||
break;
|
||||
case '&':
|
||||
toAppend = AMP_ENCODE;
|
||||
break;
|
||||
case '"':
|
||||
toAppend = QUOTE_ENCODE;
|
||||
break;
|
||||
case '\'':
|
||||
toAppend = APOS_ENCODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
toAppend = AMP_ENCODE;
|
||||
case forAttributeApos:
|
||||
// No need to escape '>' and '"' for attributes using '\'' as quote.
|
||||
switch(ch) {
|
||||
case '<':
|
||||
toAppend = LT_ENCODE;
|
||||
break;
|
||||
case '&':
|
||||
toAppend = AMP_ENCODE;
|
||||
break;
|
||||
case '\'':
|
||||
toAppend = APOS_ENCODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
toAppend = QUOTE_ENCODE;
|
||||
break;
|
||||
case '\'':
|
||||
toAppend = APOS_ENCODE;
|
||||
break;
|
||||
default:
|
||||
case forText:
|
||||
// No need to escape '"', '\'', and '>' for text.
|
||||
switch(ch) {
|
||||
case '<':
|
||||
toAppend = LT_ENCODE;
|
||||
break;
|
||||
case '&':
|
||||
toAppend = AMP_ENCODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (toAppend != null) {
|
||||
|
|
|
@ -233,7 +233,7 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
|||
public XmlStringBuilder attribute(String name, String value) {
|
||||
assert value != null;
|
||||
sb.append(' ').append(name).append("='");
|
||||
escape(value);
|
||||
escapeAttributeValue(value);
|
||||
sb.append('\'');
|
||||
return this;
|
||||
}
|
||||
|
@ -357,7 +357,13 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
|||
|
||||
public XmlStringBuilder escape(String text) {
|
||||
assert text != null;
|
||||
sb.append(StringUtils.escapeForXML(text));
|
||||
sb.append(StringUtils.escapeForXml(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder escapeAttributeValue(String value) {
|
||||
assert value != null;
|
||||
sb.append(StringUtils.escapeForXmlAttributeApos(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,43 +28,43 @@ import org.junit.Test;
|
|||
*/
|
||||
public class StringUtilsTest {
|
||||
@Test
|
||||
public void testEscapeForXML() {
|
||||
public void testEscapeForXml() {
|
||||
String input = null;
|
||||
|
||||
assertNull(StringUtils.escapeForXML(null));
|
||||
assertNull(StringUtils.escapeForXml(null));
|
||||
|
||||
input = "<b>";
|
||||
assertCharSequenceEquals("<b>", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("<b>", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "\"";
|
||||
assertCharSequenceEquals(""", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals(""", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "&";
|
||||
assertCharSequenceEquals("&", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("&", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "<b>\n\t\r</b>";
|
||||
assertCharSequenceEquals("<b>\n\t\r</b>", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("<b>\n\t\r</b>", StringUtils.escapeForXml(input));
|
||||
|
||||
input = " & ";
|
||||
assertCharSequenceEquals(" & ", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals(" & ", StringUtils.escapeForXml(input));
|
||||
|
||||
input = " \" ";
|
||||
assertCharSequenceEquals(" " ", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals(" " ", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "> of me <";
|
||||
assertCharSequenceEquals("> of me <", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("> of me <", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "> of me & you<";
|
||||
assertCharSequenceEquals("> of me & you<", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("> of me & you<", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "& <";
|
||||
assertCharSequenceEquals("& <", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("& <", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "&";
|
||||
assertCharSequenceEquals("&", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("&", StringUtils.escapeForXml(input));
|
||||
|
||||
input = "It's a good day today";
|
||||
assertCharSequenceEquals("It's a good day today", StringUtils.escapeForXML(input));
|
||||
assertCharSequenceEquals("It's a good day today", StringUtils.escapeForXml(input));
|
||||
}
|
||||
|
||||
public static void assertCharSequenceEquals(CharSequence expected, CharSequence actual) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue