istream-jsonstr.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* The end '"' was found */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Siraineni_stream_jsonstr_read_parent(struct jsonstr_istream *jstream,
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen struct istream_private *stream = &jstream->istream;
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen size = i_stream_get_data_size(stream->parent);
81a99eefdfda5781126617d47f8fd6da67bf5543Timo Sirainen /* tiny parent buffer size - shouldn't happen */
1547bafeb11368eb80168fe2899283e8bdcb8528Timo Sirainen if (ret == -1 && stream->istream.stream_errno == 0) {
1547bafeb11368eb80168fe2899283e8bdcb8528Timo Sirainen "EOF before trailing <\"> was seen");
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen size = i_stream_get_data_size(stream->parent);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen if (!i_stream_try_alloc(stream, size, &avail))
d9d28856f30b186378e687ab29fa4ba153441cd8Aki Tuomii_stream_json_unescape(const unsigned char *src, size_t len,
d9d28856f30b186378e687ab29fa4ba153441cd8Aki Tuomi unsigned char *dest,
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen unsigned int *src_size_r, unsigned int *dest_size_r)
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen buffer_create_from_data(&buf, dest, MAX_UTF8_LEN);
c3393007354b7ab607449fea0c3d7088193ab208Aki Tuomi /* if we encounter surrogate, we need another \\uxxxx */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainenstatic ssize_t i_stream_jsonstr_read(struct istream_private *stream)
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen struct jsonstr_istream *jstream = (struct jsonstr_istream *)stream;
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen const unsigned char *data;
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen ret = i_stream_jsonstr_read_parent(jstream, 1);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* @UNSAFE */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen data = i_stream_get_data(stream->parent, &size);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen for (i = 0; i < size && dest < stream->buffer_size; ) {
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* not enough input for \x */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen if (data[i+1] == 'u' && stream->buffer_size - dest < MAX_UTF8_LEN) {
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* UTF8 output is max. 6 chars */
d9d28856f30b186378e687ab29fa4ba153441cd8Aki Tuomi if ((ret2 = i_stream_json_unescape(data + i, size - i,
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* invalid string */
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "Invalid JSON string");
d9d28856f30b186378e687ab29fa4ba153441cd8Aki Tuomi } else if (ret2 > 0) {
c3393007354b7ab607449fea0c3d7088193ab208Aki Tuomi /* we need to get more bytes, do not consume
c3393007354b7ab607449fea0c3d7088193ab208Aki Tuomi escape slash */
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen /* not enough input */
076c46c6513161e2c7bbe53d421b0830e9975fb1Timo Sirainen ret = i_stream_jsonstr_read_parent(jstream, extra+1);
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainenstruct istream *i_stream_create_jsonstr(struct istream *input)
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen dstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen dstream->istream.read = i_stream_jsonstr_read;
7877db7b5daad125b6cb3e015574f33871c9a51bTimo Sirainen dstream->istream.istream.blocking = input->blocking;