json.c: encode JSON strings the correct way (RFC 7159 section 7).
authorArt Cancro <ajc@citadel.org>
Fri, 3 Nov 2023 04:13:46 +0000 (19:13 -0900)
committerArt Cancro <ajc@citadel.org>
Fri, 3 Nov 2023 04:13:46 +0000 (19:13 -0900)
The previous code used the JavaScript encoder from the stringbuf library, which
is *not* the same encoding.  Now it doesn't make the browser's parser barf when
it encounters a control character.

libcitadel/lib/json.c

index d664700fa4850ef5d7e5426af9981fb7e5c0181d..277bfe0cb44b700ad0a8b34502f6c6d3a9757f39 100644 (file)
@@ -1,7 +1,7 @@
 //
 // JSON data type and serializer for Citadel
 //
-// Copyright (c) 1987-2018 by the citadel.org team
+// Copyright (c) 1987-2023 by the citadel.org team
 //
 // This program is open source software.  Use, duplication, or disclosure
 // is subject to the terms of the GNU General Public License, version 3.
@@ -197,7 +197,32 @@ void SerializeJson(StrBuf *Target, JsonValue *Val, int FreeVal) {
        switch (Val->Type) {
        case JSON_STRING:
                StrBufAppendBufPlain(Target, HKEY("\""), 0);
-               StrECMAEscAppend(Target, Val->Value, NULL);
+               int i;
+               char *plain = (char *)ChrPtr(Val->Value);
+               if (!IsEmptyStr(plain)) {
+                       int len = strlen(plain);
+                       for (i=0; i<len; ++i) {
+                               // JSON escaped strings as per RFC 7159 section 7
+                               if (plain[i] == '\r') {
+                                       StrBufAppendBufPlain(Target, HKEY("\\r"), 0);
+                               }
+                               else if (plain[i] == '\n') {
+                                       StrBufAppendBufPlain(Target, HKEY("\\n"), 0);
+                               }
+                               else if (plain[i] == '\"') {
+                                       StrBufAppendBufPlain(Target, HKEY("\\\""), 0);
+                               }
+                               else if (plain[i] == '\\') {
+                                       StrBufAppendBufPlain(Target, HKEY("\\\\"), 0);
+                               }
+                               else if (plain[i] < 32) {
+                                       StrBufAppendPrintf(Target, "\\u%04x", plain[i]);
+                               }
+                               else {
+                                       StrBufAppendBufPlain(Target, &plain[i], 1, 0);
+                               }
+                       }
+               }
                StrBufAppendBufPlain(Target, HKEY("\""), 0);
                break;
        case JSON_NUM: