You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2021/06/23 11:32:48 UTC

[cxf] 01/01: CXF-8555 - JsonMapObjectReaderWriter escapes now any back slash

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch CXF-8555
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 77bb7673e9b874234e82d8c6623953249df6f3a9
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Jun 23 12:32:12 2021 +0100

    CXF-8555 - JsonMapObjectReaderWriter escapes now any back slash
---
 .../json/basic/JsonMapObjectReaderWriter.java      | 59 +++++++++++++++++-----
 .../json/basic/JsonMapObjectReaderWriterTest.java  | 57 +++++++++++++++++++--
 2 files changed, 100 insertions(+), 16 deletions(-)

diff --git a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
index 9b2fee7..195b327 100644
--- a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
+++ b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
@@ -22,13 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UncheckedIOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.IOUtils;
@@ -36,6 +30,7 @@ import org.apache.cxf.helpers.IOUtils;
 
 
 public class JsonMapObjectReaderWriter {
+    private static final Set<Character> ESCAPED_CHARS;
     private static final char DQUOTE = '"';
     private static final char COMMA = ',';
     private static final char COLON = ':';
@@ -47,6 +42,19 @@ public class JsonMapObjectReaderWriter {
     private static final String NULL_VALUE = "null";
     private boolean format;
 
+    static {
+        Set<Character> chars = new HashSet<>();
+        chars.add('"');
+        chars.add('\\');
+        chars.add('/');
+        chars.add('b');
+        chars.add('f');
+        chars.add('h');
+        chars.add('r');
+        chars.add('t');
+        ESCAPED_CHARS = Collections.unmodifiableSet(chars);
+    }
+
     public JsonMapObjectReaderWriter() {
 
     }
@@ -254,9 +262,19 @@ public class JsonMapObjectReaderWriter {
             }
         }
 
-        if (value instanceof String && ((String)value).contains("\\/")) {
-            // Escape an encoded forward slash
-            value = ((String) value).replace("\\/", "/");
+        if (value instanceof String) {
+            if (((String) value).contains("\\/")) {
+                // Escape an encoded forward slash
+                value = ((String) value).replace("\\/", "/");
+            }
+            if (((String) value).contains("\\\"")) {
+                // Escape an encoded quotation mark
+                value = ((String) value).replace("\\\"", "\"");
+            }
+            if (((String) value).contains("\\\\")) {
+                // Escape an encoded backslash
+                value = ((String) value).replace("\\\\", "\\");
+            }
         }
         return value;
     }
@@ -367,8 +385,25 @@ public class JsonMapObjectReaderWriter {
     }
 
     private String escapeJson(String value) {
-        return value.replace("\"", "\\\"")
-                .replace("\\", "\\\\");
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            // If we have " and the previous char was not \ then escape it
+            if (c == '"' && (i == 0 || value.charAt(i - 1) != '\\')) {
+                sb.append('\\').append(c);
+            // If we have \ and the previous char was not \ and the next char is not an escaped char, then escape it
+            } else if (c == '\\' && (i == 0 || value.charAt(i - 1) != '\\')
+                    && (i == value.length() - 1 || !isEscapedChar(value.charAt(i + 1)))) {
+                sb.append('\\').append(c);
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    private boolean isEscapedChar(char c) {
+        return ESCAPED_CHARS.contains(Character.valueOf(c));
     }
 
 }
diff --git a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
index d08de1b..424eb72 100644
--- a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
+++ b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
@@ -32,6 +32,7 @@ import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 public class JsonMapObjectReaderWriterTest {
 
@@ -126,7 +127,7 @@ public class JsonMapObjectReaderWriterTest {
         assertEquals(1, map.size());
         Map<String, Object> xMap = CastUtils.cast((Map<?, ?>)map.get("x"));
         assertEquals(1, xMap.size());
-        assertEquals("{\\\"}", xMap.get("y"));
+        assertEquals("{\"}", xMap.get("y"));
     }
 
     @Test
@@ -153,12 +154,60 @@ public class JsonMapObjectReaderWriterTest {
     public void testEscapeDoubleQuotes() throws Exception {
         JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
         Map<String, Object> content = new HashMap<>();
-        content.put("userInput", "a\",\"exp\":9999999999,\"b\":\"x");
+        content.put("userInput", "a\"");
         String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\""));
 
         Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
         assertEquals(1, map.size());
-        assertEquals("userInput", map.keySet().iterator().next());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\"", entry.getValue());
     }
 
-}
\ No newline at end of file
+    @Test
+    public void testAlreadyEscapedDoubleQuotes() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\\"");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\""));
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\"", entry.getValue());
+    }
+
+    @Test
+    public void testEscapeBackslash() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\\"));
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\\", entry.getValue());
+    }
+
+    @Test
+    public void testAlreadyEscapedBackslash() throws Exception {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter();
+        Map<String, Object> content = new HashMap<>();
+        content.put("userInput", "a\\\\");
+        String json = jsonMapObjectReaderWriter.toJson(content);
+        assertTrue(json.contains("a\\\\"));
+
+        Map<String, Object> map = jsonMapObjectReaderWriter.fromJson(json);
+        assertEquals(1, map.size());
+        Map.Entry<String, Object> entry = map.entrySet().iterator().next();
+        assertEquals("userInput", entry.getKey());
+        assertEquals("a\\", entry.getValue());
+    }
+
+}