HDFS-7309. XMLUtils.mangleXmlString doesn't seem to handle less than sign. (Colin Patrick McCabe via raviprak)
(cherry picked from commit c7f81dad30
)
This commit is contained in:
parent
9b879d713a
commit
fe8cf32493
|
@ -446,6 +446,9 @@ Release 2.6.0 - UNRELEASED
|
|||
|
||||
BUG FIXES
|
||||
|
||||
HDFS-7309. XMLUtils.mangleXmlString doesn't seem to handle less than sign
|
||||
(Colin Patrick McCabe via raviprak)
|
||||
|
||||
HDFS-6823. dfs.web.authentication.kerberos.principal shows up in logs for
|
||||
insecure HDFS (Allen Wittenauer via raviprak)
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ class OfflineEditsXmlLoader
|
|||
|
||||
@Override
|
||||
public void endElement (String uri, String name, String qName) {
|
||||
String str = XMLUtils.unmangleXmlString(cbuf.toString()).trim();
|
||||
String str = XMLUtils.unmangleXmlString(cbuf.toString(), false).trim();
|
||||
cbuf = new StringBuffer();
|
||||
switch (state) {
|
||||
case EXPECT_EDITS_TAG:
|
||||
|
|
|
@ -411,7 +411,8 @@ public final class PBImageXmlWriter {
|
|||
}
|
||||
|
||||
private PBImageXmlWriter o(final String e, final Object v) {
|
||||
out.print("<" + e + ">" + XMLUtils.mangleXmlString(v.toString()) + "</" + e + ">");
|
||||
out.print("<" + e + ">" +
|
||||
XMLUtils.mangleXmlString(v.toString(), true) + "</" + e + ">");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ public class XmlImageVisitor extends TextWriterImageVisitor {
|
|||
}
|
||||
|
||||
private void writeTag(String tag, String value) throws IOException {
|
||||
write("<" + tag + ">" + XMLUtils.mangleXmlString(value) + "</" + tag + ">\n");
|
||||
write("<" + tag + ">" +
|
||||
XMLUtils.mangleXmlString(value, true) + "</" + tag + ">\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,23 @@ public class XMLUtils {
|
|||
return String.format("\\%0" + NUM_SLASH_POSITIONS + "x;", cp);
|
||||
}
|
||||
|
||||
private static String codePointToEntityRef(int cp) {
|
||||
switch (cp) {
|
||||
case '&':
|
||||
return "&";
|
||||
case '\"':
|
||||
return """;
|
||||
case '\'':
|
||||
return "'";
|
||||
case '<':
|
||||
return "<";
|
||||
case '>':
|
||||
return ">";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mangle a string so that it can be represented in an XML document.
|
||||
*
|
||||
|
@ -117,7 +134,7 @@ public class XMLUtils {
|
|||
*
|
||||
* @return The mangled string.
|
||||
*/
|
||||
public static String mangleXmlString(String str) {
|
||||
public static String mangleXmlString(String str, boolean createEntityRefs) {
|
||||
final StringBuilder bld = new StringBuilder();
|
||||
final int length = str.length();
|
||||
for (int offset = 0; offset < length; ) {
|
||||
|
@ -125,11 +142,19 @@ public class XMLUtils {
|
|||
final int len = Character.charCount(cp);
|
||||
if (codePointMustBeMangled(cp)) {
|
||||
bld.append(mangleCodePoint(cp));
|
||||
} else {
|
||||
String entityRef = null;
|
||||
if (createEntityRefs) {
|
||||
entityRef = codePointToEntityRef(cp);
|
||||
}
|
||||
if (entityRef != null) {
|
||||
bld.append(entityRef);
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
bld.append(str.charAt(offset + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
return bld.toString();
|
||||
|
@ -137,22 +162,42 @@ public class XMLUtils {
|
|||
|
||||
/**
|
||||
* Demangle a string from an XML document.
|
||||
* See {@link #mangleXmlString(String)} for a description of the mangling
|
||||
* format.
|
||||
* See {@link #mangleXmlString(String, boolean)} for a description of the
|
||||
* mangling format.
|
||||
*
|
||||
* @param str The string to be demangled.
|
||||
*
|
||||
* @return The unmangled string
|
||||
* @throws UnmanglingError if the input is malformed.
|
||||
*/
|
||||
public static String unmangleXmlString(String str)
|
||||
public static String unmangleXmlString(String str, boolean decodeEntityRefs)
|
||||
throws UnmanglingError {
|
||||
int slashPosition = -1;
|
||||
String escapedCp = "";
|
||||
StringBuilder bld = new StringBuilder();
|
||||
StringBuilder entityRef = null;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char ch = str.charAt(i);
|
||||
if ((slashPosition >= 0) && (slashPosition < NUM_SLASH_POSITIONS)) {
|
||||
if (entityRef != null) {
|
||||
entityRef.append(ch);
|
||||
if (ch == ';') {
|
||||
String e = entityRef.toString();
|
||||
if (e.equals(""")) {
|
||||
bld.append("\"");
|
||||
} else if (e.equals("'")) {
|
||||
bld.append("\'");
|
||||
} else if (e.equals("&")) {
|
||||
bld.append("&");
|
||||
} else if (e.equals("<")) {
|
||||
bld.append("<");
|
||||
} else if (e.equals(">")) {
|
||||
bld.append(">");
|
||||
} else {
|
||||
throw new UnmanglingError("Unknown entity ref " + e);
|
||||
}
|
||||
entityRef = null;
|
||||
}
|
||||
} else if ((slashPosition >= 0) && (slashPosition < NUM_SLASH_POSITIONS)) {
|
||||
escapedCp += ch;
|
||||
++slashPosition;
|
||||
} else if (slashPosition == NUM_SLASH_POSITIONS) {
|
||||
|
@ -169,11 +214,23 @@ public class XMLUtils {
|
|||
slashPosition = -1;
|
||||
} else if (ch == '\\') {
|
||||
slashPosition = 0;
|
||||
} else {
|
||||
boolean startingEntityRef = false;
|
||||
if (decodeEntityRefs) {
|
||||
startingEntityRef = (ch == '&');
|
||||
}
|
||||
if (startingEntityRef) {
|
||||
entityRef = new StringBuilder();
|
||||
entityRef.append("&");
|
||||
} else {
|
||||
bld.append(ch);
|
||||
}
|
||||
}
|
||||
if (slashPosition != -1) {
|
||||
}
|
||||
if (entityRef != null) {
|
||||
throw new UnmanglingError("unterminated entity ref starting with " +
|
||||
entityRef.toString());
|
||||
} else if (slashPosition != -1) {
|
||||
throw new UnmanglingError("unterminated code point escape: string " +
|
||||
"broke off in the middle");
|
||||
}
|
||||
|
@ -185,12 +242,12 @@ public class XMLUtils {
|
|||
*
|
||||
* @param contentHandler the SAX content handler
|
||||
* @param tag the element tag to use
|
||||
* @param value the string to put inside the tag
|
||||
* @param val the string to put inside the tag
|
||||
*/
|
||||
public static void addSaxString(ContentHandler contentHandler,
|
||||
String tag, String val) throws SAXException {
|
||||
contentHandler.startElement("", "", tag, new AttributesImpl());
|
||||
char c[] = mangleXmlString(val).toCharArray();
|
||||
char c[] = mangleXmlString(val, false).toCharArray();
|
||||
contentHandler.characters(c, 0, c.length);
|
||||
contentHandler.endElement("", "", tag);
|
||||
}
|
||||
|
|
|
@ -22,11 +22,21 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
|
||||
public class TestXMLUtils {
|
||||
private static void testRoundTripImpl(String str, String expectedMangled,
|
||||
boolean encodeEntityRefs) {
|
||||
String mangled = XMLUtils.mangleXmlString(str, encodeEntityRefs);
|
||||
Assert.assertEquals(expectedMangled, mangled);
|
||||
String unmangled = XMLUtils.unmangleXmlString(mangled, encodeEntityRefs);
|
||||
Assert.assertEquals(str, unmangled);
|
||||
}
|
||||
|
||||
private static void testRoundTrip(String str, String expectedMangled) {
|
||||
String mangled = XMLUtils.mangleXmlString(str);
|
||||
Assert.assertEquals(mangled, expectedMangled);
|
||||
String unmangled = XMLUtils.unmangleXmlString(mangled);
|
||||
Assert.assertEquals(unmangled, str);
|
||||
testRoundTripImpl(str, expectedMangled, false);
|
||||
}
|
||||
|
||||
private static void testRoundTripWithEntityRefs(String str,
|
||||
String expectedMangled) {
|
||||
testRoundTripImpl(str, expectedMangled, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -54,16 +64,25 @@ public class TestXMLUtils {
|
|||
@Test
|
||||
public void testInvalidSequence() throws Exception {
|
||||
try {
|
||||
XMLUtils.unmangleXmlString("\\000g;foo");
|
||||
XMLUtils.unmangleXmlString("\\000g;foo", false);
|
||||
Assert.fail("expected an unmangling error");
|
||||
} catch (UnmanglingError e) {
|
||||
// pass through
|
||||
}
|
||||
try {
|
||||
XMLUtils.unmangleXmlString("\\0");
|
||||
XMLUtils.unmangleXmlString("\\0", false);
|
||||
Assert.fail("expected an unmangling error");
|
||||
} catch (UnmanglingError e) {
|
||||
// pass through
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddEntityRefs() throws Exception {
|
||||
testRoundTripWithEntityRefs("The Itchy & Scratchy Show",
|
||||
"The Itchy & Scratchy Show");
|
||||
testRoundTripWithEntityRefs("\"He said '1 < 2, but 2 > 1'\"",
|
||||
""He said '1 < 2, but 2 > 1'"");
|
||||
testRoundTripWithEntityRefs("\u0001 < \u0002", "\\0001; < \\0002;");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue