summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2016-08-02 11:58:50 +0200
committerKarel Zak2016-08-02 12:05:05 +0200
commit1ca2661bb8c4021aac2130536d846d6276448f53 (patch)
tree0021e9af03b0afe7ecb21af72d6895403b5cd0e0
parentagetty: call uname() only when necessary (diff)
downloadkernel-qcow2-util-linux-1ca2661bb8c4021aac2130536d846d6276448f53.tar.gz
kernel-qcow2-util-linux-1ca2661bb8c4021aac2130536d846d6276448f53.tar.xz
kernel-qcow2-util-linux-1ca2661bb8c4021aac2130536d846d6276448f53.zip
libsmartcols: Corrected JSON escaping
Based on patch set https://github.com/karelzak/util-linux/pull/331 from Fordi. Addresses: https://github.com/karelzak/util-linux/issues/330 Co-Author: Bryan Elliott <fordiman@gmail.com> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--include/carefulputc.h80
-rw-r--r--libsmartcols/src/table_print.c4
2 files changed, 82 insertions, 2 deletions
diff --git a/include/carefulputc.h b/include/carefulputc.h
index 681e66660..688435ed5 100644
--- a/include/carefulputc.h
+++ b/include/carefulputc.h
@@ -26,6 +26,82 @@ static inline int fputc_careful(int c, FILE *fp, const char fail)
return (ret < 0) ? EOF : 0;
}
+/*
+ * Requirements enumerated via testing (V8, Firefox, IE11):
+ *
+ * var charsToEscape = [];
+ * for (var i = 0; i < 65535; i += 1) {
+ * try {
+ * JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
+ * } catch (e) {
+ * charsToEscape.push(i);
+ * }
+ * }
+ */
+static inline void fputs_quoted_case_json(const char *data, FILE *out, int dir)
+{
+ const char *p;
+
+ fputc('"', out);
+ for (p = data; p && *p; p++) {
+
+ const unsigned char c = (unsigned char) *p;
+
+ /* From http://www.json.org
+ *
+ * The double-quote and backslashes would break out a string or
+ * init an escape sequence if not escaped.
+ *
+ * Note that single-quotes and forward slashes, while they're
+ * in the JSON spec, don't break double-quoted strings.
+ */
+ if (c == '"' || c == '\\') {
+ fputc('\\', out);
+ fputc(c, out);
+ continue;
+ }
+
+ /* All non-control characters OK; do the case swap as required. */
+ if (c >= 0x20) {
+ fputc(dir == 1 ? toupper(c) :
+ dir == -1 ? tolower(c) : *p, out);
+ continue;
+ }
+
+ /* In addition, all chars under ' ' break Node's/V8/Chrome's, and
+ * Firefox's JSON.parse function
+ */
+ switch (c) {
+ /* Handle short-hand cases to reduce output size. C
+ * has most of the same stuff here, so if there's an
+ * "Escape for C" function somewhere in the STL, we
+ * should probably be using it.
+ */
+ case '\b':
+ fputs("\\b", out);
+ break;
+ case '\t':
+ fputs("\\t", out);
+ break;
+ case '\n':
+ fputs("\\n", out);
+ break;
+ case '\f':
+ fputs("\\f", out);
+ break;
+ case '\r':
+ fputs("\\r", out);
+ break;
+ default:
+ /* Other assorted control characters */
+ fprintf(out, "\\u00%02x", c);
+ break;
+ }
+ }
+ fputc('"', out);
+}
+
+
static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
{
const char *p;
@@ -52,6 +128,10 @@ static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
#define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1)
#define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1)
+#define fputs_quoted_json(_d, _o) fputs_quoted_case_json(_d, _o, 0)
+#define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1)
+#define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1)
+
static inline void fputs_nonblank(const char *data, FILE *out)
{
const char *p;
diff --git a/libsmartcols/src/table_print.c b/libsmartcols/src/table_print.c
index d2f13f831..4b250eb0f 100644
--- a/libsmartcols/src/table_print.c
+++ b/libsmartcols/src/table_print.c
@@ -421,12 +421,12 @@ static int print_data(struct libscols_table *tb,
return 0;
case SCOLS_FMT_JSON:
- fputs_quoted_lower(scols_cell_get_data(&cl->header), tb->out);
+ fputs_quoted_json_lower(scols_cell_get_data(&cl->header), tb->out);
fputs(": ", tb->out);
if (!data || !*data)
fputs("null", tb->out);
else
- fputs_quoted(data, tb->out);
+ fputs_quoted_json(data, tb->out);
if (!is_last_column(cl))
fputs(", ", tb->out);
return 0;