aboutsummaryrefslogtreecommitdiffstats
path: root/wsutil/json_dumper.c
diff options
context:
space:
mode:
authorDario Lombardo <lomato@gmail.com>2018-12-13 15:39:21 +0100
committerPeter Wu <peter@lekensteyn.nl>2018-12-23 21:10:47 +0000
commit71517540b7281d529ab24107ba4bb4723f916b32 (patch)
treee8bf2f052ba2bcb63b60aa7022139e755959c7ea /wsutil/json_dumper.c
parentc88bef54a9f417ca14e1743ddc138934a62ac82a (diff)
json_dumper: add base64 routines.
Change-Id: Iab9a201fe951e5557501f4e675ab74ecd9dbb930 Reviewed-on: https://code.wireshark.org/review/31034 Petri-Dish: Dario Lombardo <lomato@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'wsutil/json_dumper.c')
-rw-r--r--wsutil/json_dumper.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/wsutil/json_dumper.c b/wsutil/json_dumper.c
index 195049c99d..5162b6b8c9 100644
--- a/wsutil/json_dumper.c
+++ b/wsutil/json_dumper.c
@@ -23,9 +23,10 @@ enum json_dumper_element_type {
JSON_DUMPER_TYPE_VALUE = 1,
JSON_DUMPER_TYPE_OBJECT = 2,
JSON_DUMPER_TYPE_ARRAY = 3,
+ JSON_DUMPER_TYPE_BASE64 = 4,
};
-#define JSON_DUMPER_TYPE(state) ((enum json_dumper_element_type)((state) & 3))
-#define JSON_DUMPER_HAS_NAME (1 << 2)
+#define JSON_DUMPER_TYPE(state) ((enum json_dumper_element_type)((state) & 7))
+#define JSON_DUMPER_HAS_NAME (1 << 3)
#define JSON_DUMPER_FLAGS_ERROR (1 << 16) /* Output flag: an error occurred. */
#define JSON_DUMPER_FLAGS_NO_DEBUG (1 << 17) /* Input flag: disable debug prints (intended for speeding up fuzzing). */
@@ -35,6 +36,7 @@ enum json_dumper_change {
JSON_DUMPER_END,
JSON_DUMPER_SET_NAME,
JSON_DUMPER_SET_VALUE,
+ JSON_DUMPER_WRITE_BASE64,
JSON_DUMPER_FINISH,
};
@@ -137,10 +139,16 @@ json_dumper_check_state(json_dumper *dumper, enum json_dumper_change change, enu
ok = (prev_state & JSON_DUMPER_HAS_NAME);
} else if (prev_type == JSON_DUMPER_TYPE_ARRAY) {
ok = TRUE;
+ } else if (prev_type == JSON_DUMPER_TYPE_BASE64) {
+ ok = FALSE;
} else {
ok = JSON_DUMPER_TYPE(dumper->state[depth]) == JSON_DUMPER_TYPE_NONE;
}
break;
+ case JSON_DUMPER_WRITE_BASE64:
+ ok = (prev_type == JSON_DUMPER_TYPE_BASE64) &&
+ (type == JSON_DUMPER_TYPE_NONE || type == JSON_DUMPER_TYPE_BASE64);
+ break;
case JSON_DUMPER_FINISH:
ok = depth == 0;
break;
@@ -324,3 +332,61 @@ json_dumper_finish(json_dumper *dumper)
dumper->state[0] = 0;
return TRUE;
}
+
+void
+json_dumper_begin_base64(json_dumper *dumper)
+{
+ if (!json_dumper_check_state(dumper, JSON_DUMPER_BEGIN, JSON_DUMPER_TYPE_BASE64)) {
+ return;
+ }
+
+ dumper->base64_state = 0;
+ dumper->base64_save = 0;
+
+ prepare_token(dumper);
+
+ fputc('"', dumper->output_file);
+
+ dumper->state[dumper->current_depth] = JSON_DUMPER_TYPE_BASE64;
+ ++dumper->current_depth;
+ dumper->state[dumper->current_depth] = 0;
+}
+
+void
+json_dumper_write_base64(json_dumper* dumper, const guchar *data, size_t len)
+{
+ if (!json_dumper_check_state(dumper, JSON_DUMPER_WRITE_BASE64, JSON_DUMPER_TYPE_BASE64)) {
+ return;
+ }
+
+ #define CHUNK_SIZE 1024
+ gchar buf[(CHUNK_SIZE / 3 + 1) * 4 + 4];
+
+ while (len > 0) {
+ gsize chunk_size = len < CHUNK_SIZE ? len : CHUNK_SIZE;
+ gsize output_size = g_base64_encode_step(data, chunk_size, FALSE, buf, &dumper->base64_state, &dumper->base64_save);
+ fwrite(buf, 1, output_size, dumper->output_file);
+ data += chunk_size;
+ len -= chunk_size;
+ }
+
+ dumper->state[dumper->current_depth] = JSON_DUMPER_TYPE_BASE64;
+}
+
+void
+json_dumper_end_base64(json_dumper *dumper)
+{
+ if (!json_dumper_check_state(dumper, JSON_DUMPER_END, JSON_DUMPER_TYPE_BASE64)) {
+ return;
+ }
+
+ gchar buf[4];
+ gsize wrote;
+
+ wrote = g_base64_encode_close(FALSE, buf, &dumper->base64_state, &dumper->base64_save);
+ fwrite(buf, 1, wrote, dumper->output_file);
+
+ fputc('"', dumper->output_file);
+
+ --dumper->current_depth;
+}