diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java
index 813abca62..401ea80c9 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java
@@ -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);
}
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java
index a0a70e19f..4398e836f 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java
@@ -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 input
for XML.
+ *
+ * @param input the input to escape.
+ * @return the XML escaped variant of input
.
+ * @deprecated use {@link #escapeForXml(CharSequence)} instead.
+ */
+ // Remove in 4.3.
+ @Deprecated
+ public static CharSequence escapeForXML(CharSequence input) {
+ return escapeForXml(input);
+ }
+
+ /**
+ * Escape input
for XML.
+ *
+ * @param input the input to escape.
+ * @return the XML escaped variant of input
.
+ */
+ public static CharSequence escapeForXml(CharSequence input) {
+ return escapeForXml(input, XmlEscapeMode.safe);
+ }
+
+ /**
+ * Escape input
for XML.
+ *
+ * @param input the input to escape.
+ * @return the XML escaped variant of input
.
+ * @since 4.2
+ */
+ public static CharSequence escapeForXmlAttribute(CharSequence input) {
+ return escapeForXml(input, XmlEscapeMode.forAttribute);
+ }
+
+ /**
+ * Escape input
for XML.
+ *
+ * This is an optimized variant of {@link #escapeForXmlAttribute(CharSequence)} for XML where the + * XML attribute is quoted using ''' (Apos). + *
+ * + * @param input the input to escape. + * @return the XML escaped variant ofinput
.
+ * @since 4.2
+ */
+ public static CharSequence escapeForXmlAttributeApos(CharSequence input) {
+ return escapeForXml(input, XmlEscapeMode.forAttributeApos);
+ }
+
+ /**
+ * Escape input
for XML.
+ *
+ * @param input the input to escape.
+ * @return the XML escaped variant of input
.
+ * @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) {
diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java
index 9dbec85b6..127382740 100644
--- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java
+++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java
@@ -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;
}
diff --git a/smack-core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java b/smack-core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java
index 86df0b2cb..bd0d5ad05 100644
--- a/smack-core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java
+++ b/smack-core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java
@@ -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 = "";
- 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 = "\n\t\r";
- 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) {
diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java
index 05bf8c813..b3cbccb6d 100644
--- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java
+++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java
@@ -186,7 +186,7 @@ public abstract class AbstractHttpOverXmppProvider