Repository: commons-text Updated Branches: refs/heads/master 5cdb77906 -> 56eef1f88
TEXT-28: Add XSI escape/unescape support Project: http://git-wip-us.apache.org/repos/asf/commons-text/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-text/commit/6b0ff8df Tree: http://git-wip-us.apache.org/repos/asf/commons-text/tree/6b0ff8df Diff: http://git-wip-us.apache.org/repos/asf/commons-text/diff/6b0ff8df Branch: refs/heads/master Commit: 6b0ff8df40c1e65598ca43a62815c410095ecae1 Parents: 5cdb779 Author: Rob Tompkins <chtom...@gmail.com> Authored: Thu Dec 15 09:26:41 2016 -0500 Committer: Rob Tompkins <chtom...@gmail.com> Committed: Thu Dec 15 09:26:41 2016 -0500 ---------------------------------------------------------------------- .../apache/commons/text/StringEscapeUtils.java | 109 +++++++++++++++++++ .../commons/text/StringEscapeUtilsTest.java | 20 ++++ 2 files changed, 129 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-text/blob/6b0ff8df/src/main/java/org/apache/commons/text/StringEscapeUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java index 6b88275..7866566 100644 --- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java +++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java @@ -279,6 +279,39 @@ public class StringEscapeUtils { } } + /** + * Translator object for escaping Shell command language. + * + * @see <a href="http://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html">Shell Command Language</a> + */ + public static final CharSequenceTranslator ESCAPE_XSI = + new LookupTranslator( + new String[][] { + {"|", "\\|"}, + {"&", "\\&"}, + {";", "\\;"}, + {"<", "\\<"}, + {">", "\\>"}, + {"(", "\\("}, + {")", "\\)"}, + {"$", "\\$"}, + {"`", "\\`"}, + {"\\", "\\\\"}, + {"\"", "\\\""}, + {"'", "\\'"}, + {" ", "\\ "}, + {"\t", "\\\t"}, + {"\r\n", ""}, + {"\n", ""}, + {"*", "\\*"}, + {"?", "\\?"}, + {"[", "\\["}, + {"#", "\\#"}, + {"~", "\\~"}, + {"=", "\\="}, + {"%", "\\%"}, + }); + /* UNESCAPE TRANSLATORS */ /** @@ -420,6 +453,47 @@ public class StringEscapeUtils { } } + public static final CharSequenceTranslator UNESCAPE_XSI = new XsiUnescaper(); + + /** + * Translator object for unescaping backslash escaped entries. + * + * @since 3.6 + */ + static class XsiUnescaper extends CharSequenceTranslator { + + private static final char BACKSLASH = '\\'; + + @Override + public int translate(final CharSequence input, final int index, final Writer out) throws IOException { + + if(index != 0) { + throw new IllegalStateException("XsiUnescaper should never reach the [1] index"); + } + + String s = input.toString(); + + int segmentStart = 0; + int searchOffset = 0; + while (true) { + int pos = s.indexOf(BACKSLASH, searchOffset); + if (pos == -1) { + if (segmentStart < s.length()) { + out.write(s.substring(segmentStart)); + } + break; + } + if (pos > segmentStart) { + out.write(s.substring(segmentStart, pos)); + } + segmentStart = pos + 1; + searchOffset = pos + 2; + } + + return Character.codePointCount(input, 0, input.length()); + } + } + /* Helper functions */ /** @@ -808,4 +882,39 @@ public class StringEscapeUtils { return UNESCAPE_CSV.translate(input); } + // Shell + /** + * <p>Escapes the characters in a {@code String} using XSI rules.</p> + * + * <p><b>Beware!</b> In most cases you don't want to escape shell commands but use multi-argument + * methods provided by {@link java.lang.ProcessBuilder} or {@link java.lang.Runtime#exec(String[])} + * instead.</p> + * + * <p>Example:</p> + * <pre> + * input string: He didn't say, "Stop!" + * output string: He\ didn\'t\ say,\ \"Stop!\" + * </pre> + * + * @see <a href="http://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html">Shell Command Language</a> + * @param input String to escape values in, may be null + * @return String with escaped values, {@code null} if null string input + * @since 3.6 + */ + public static final String escapeXSI(final String input) { + return ESCAPE_XSI.translate(input); + } + + /** + * <p>Unescapes the characters in a {@code String} using XSI rules.</p> + * + * @see StringEscapeUtils#escapeXSI(String) + * @param input the {@code String} to unescape, may be null + * @return a new unescaped {@code String}, {@code null} if null string input + * @since 3.6 + */ + public static final String unescapeXSI(final String input) { + return UNESCAPE_XSI.translate(input); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/commons-text/blob/6b0ff8df/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java index 4700cde..e5fd3a0 100644 --- a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java +++ b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java @@ -16,9 +16,12 @@ */ package org.apache.commons.text; +import static org.apache.commons.text.StringEscapeUtils.escapeXSI; +import static org.apache.commons.text.StringEscapeUtils.unescapeXSI; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -618,4 +621,21 @@ public class StringEscapeUtilsTest { assertEquals(expected, StringEscapeUtils.escapeJson(input)); } + @Test + public void testEscapeXSI() { + assertNull(null, escapeXSI(null)); + assertEquals("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\"", escapeXSI("He didn't say, \"Stop!\"")); + assertEquals("\\\\", escapeXSI("\\")); + assertEquals("", escapeXSI("\n")); + } + + @Test + public void testUnscapeXSI() { + assertNull(null, unescapeXSI(null)); + assertEquals("\"", unescapeXSI("\\\"")); + assertEquals("He didn't say, \"Stop!\"", unescapeXSI("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\"")); + assertEquals("\\", unescapeXSI("\\\\")); + assertEquals("", unescapeXSI("\\")); + } + } \ No newline at end of file