Exemple #1
0
int json_parser_deinit(struct json_parser **_parser, const char **error_r)
{
	struct json_parser *parser = *_parser;

	*_parser = NULL;

	if (parser->error != NULL) {
		/* actual parser error */
		*error_r = parser->error;
	} else if (parser->input->stream_errno != 0) {
		*error_r = t_strdup_printf("read(%s) failed: %m",
					   i_stream_get_name(parser->input));
	} else if (parser->data == parser->end &&
		   !i_stream_have_bytes_left(parser->input) &&
		   parser->state != JSON_STATE_DONE) {
		*error_r = "Missing '}'";
	} else {
		*error_r = NULL;
	}
	
	i_stream_unref(&parser->input);
	array_free(&parser->nesting);
	str_free(&parser->value);
	i_free(parser);
	return *error_r != NULL ? -1 : 0;
}
static int server_connection_send_cmd_input_more(struct server_connection *conn)
{
    off_t ret;

    /* ostream-dot writes only up to max buffer size, so keep it non-zero */
    o_stream_set_max_buffer_size(conn->cmd_output, IO_BLOCK_SIZE);
    ret = o_stream_send_istream(conn->cmd_output, conn->cmd_input);
    o_stream_set_max_buffer_size(conn->cmd_output, (size_t)-1);

    if (ret >= 0 && i_stream_have_bytes_left(conn->cmd_input)) {
        o_stream_set_flush_pending(conn->cmd_output, TRUE);
        return 0;
    }
    if (conn->cmd_input->stream_errno != 0) {
        i_error("read(%s) failed: %s",
                i_stream_get_name(conn->cmd_input),
                i_stream_get_error(conn->cmd_input));
    } else if (conn->cmd_output->stream_errno != 0 ||
               o_stream_flush(conn->cmd_output) < 0) {
        i_error("write(%s) failed: %s",
                o_stream_get_name(conn->cmd_output),
                o_stream_get_error(conn->cmd_output));
    }

    i_stream_destroy(&conn->cmd_input);
    o_stream_destroy(&conn->cmd_output);
    return ret < 0 ? -1 : 1;
}
Exemple #3
0
static int program_client_program_output(struct program_client *pclient)
{
	struct istream *input = pclient->input;
	struct ostream *output = pclient->program_output;
	const unsigned char *data;
	size_t size;
	int ret = 0;

	if ((ret = o_stream_flush(output)) <= 0) {
		if (ret < 0)
			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
		return ret;
	}

	if ( input != NULL && output != NULL ) {
		do {
			while ( (data=i_stream_get_data(input, &size)) != NULL ) {
				ssize_t sent;
	
				if ( (sent=o_stream_send(output, data, size)) < 0 ) {
					program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
					return -1;
				}
	
				if ( sent == 0 )
					return 0;
				i_stream_skip(input, sent);
			}
		} while ( (ret=i_stream_read(input)) > 0 );

		if ( ret == 0 )
			return 1;

		if ( ret < 0 ) {
			if ( !input->eof ) {
				program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
				return -1;
			} else if ( !i_stream_have_bytes_left(input) ) {
				i_stream_unref(&pclient->input);
				input = NULL;

				if ( (ret = o_stream_flush(output)) <= 0 ) {
					if ( ret < 0 )
						program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
					return ret;
				}
			} 
		}
	}

	if ( input == NULL ) {
		if ( !program_client_input_pending(pclient) ) {
			program_client_disconnect(pclient, FALSE);
		} else if (program_client_close_output(pclient) < 0) {
			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
		}
	}
	return 1;
}
Exemple #4
0
bool i_stream_is_eof(struct istream *stream)
{
	const struct istream_private *_stream = stream->real_stream;

	if (_stream->skip == _stream->pos)
		(void)i_stream_read(stream);
	return !i_stream_have_bytes_left(stream);
}
Exemple #5
0
static int o_stream_mail_filter_flush(struct ostream_private *stream)
{
	struct mail_filter_ostream *mstream =
		(struct mail_filter_ostream *)stream;
	const unsigned char *data;
	size_t size;
	ssize_t ret;

	if (mstream->ext_out == NULL) {
		/* connect failed */
		return -1;
	}
	if (mstream->flushed)
		return 0;

	if (shutdown(mstream->fd, SHUT_WR) < 0)
		i_error("ext-filter: shutdown() failed: %m");

	while ((ret = i_stream_read_data(mstream->ext_in, &data, &size, 0)) > 0) {
		ret = o_stream_send(stream->parent, data, size);
		if (ret != (ssize_t)size) {
			i_assert(ret < 0);
			o_stream_copy_error_from_parent(stream);
			return -1;
		}
		i_stream_skip(mstream->ext_in, size);
	}
	i_assert(ret == -1);

	if (!i_stream_have_bytes_left(mstream->ext_in) &&
	    mstream->ext_in->v_offset == 0) {
		/* EOF without any input -> assume the script is repoting
		   failure. pretty ugly way, but currently there's no error
		   reporting channel. */
		stream->ostream.stream_errno = EIO;
		return -1;
	}
	if (mstream->ext_in->stream_errno != 0) {
		stream->ostream.stream_errno = mstream->ext_in->stream_errno;
		return -1;
	}

	ret = o_stream_flush(stream->parent);
	if (ret < 0)
		o_stream_copy_error_from_parent(stream);
	else
		mstream->flushed = TRUE;
	return ret;
}
Exemple #6
0
static int fetch_stream_continue(struct imap_fetch_context *ctx)
{
	struct imap_fetch_state *state = &ctx->state;
	const char *disconnect_reason;
	off_t ret;

	o_stream_set_max_buffer_size(ctx->client->output, 0);
	ret = o_stream_send_istream(ctx->client->output, state->cur_input);
	o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1);

	if (ret > 0) {
		state->cur_offset += ret;
		if (ctx->state.cur_stats_sizep != NULL)
			*ctx->state.cur_stats_sizep += ret;
	}

	if (state->cur_offset != state->cur_size) {
		/* unfinished */
		if (state->cur_input->stream_errno != 0) {
			fetch_read_error(ctx, &disconnect_reason);
			client_disconnect(ctx->client, disconnect_reason);
			return -1;
		}
		if (!i_stream_have_bytes_left(state->cur_input)) {
			/* Input stream gave less data than expected */
			i_error("read(%s): FETCH %s for mailbox %s UID %u "
				"got too little data: "
				"%"PRIuUOFF_T" vs %"PRIuUOFF_T,
				i_stream_get_name(state->cur_input),
				state->cur_human_name,
				mailbox_get_vname(state->cur_mail->box),
				state->cur_mail->uid,
				state->cur_offset, state->cur_size);
			mail_set_cache_corrupted(state->cur_mail,
						 state->cur_size_field);
			client_disconnect(ctx->client, "FETCH failed");
			return -1;
		}
		if (ret < 0) {
			/* client probably disconnected */
			return -1;
		}

		o_stream_set_flush_pending(ctx->client->output, TRUE);
		return 0;
	}
	return 1;
}
static int fetch_stream_send_direct(struct imap_fetch_context *ctx)
{
	off_t ret;

	o_stream_set_max_buffer_size(ctx->client->output, 0);
	ret = o_stream_send_istream(ctx->client->output, ctx->cur_input);
	o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1);

	if (ret < 0)
		return -1;

	ctx->cur_offset += ret;

	if (ctx->cur_append_eoh && ctx->cur_offset + 2 == ctx->cur_size) {
		/* Netscape missing EOH workaround. */
		if (o_stream_send(ctx->client->output, "\r\n", 2) < 0)
			return -1;
		ctx->cur_offset += 2;
		ctx->cur_append_eoh = FALSE;
	}

	if (ctx->cur_offset != ctx->cur_size) {
		/* unfinished */
		if (!i_stream_have_bytes_left(ctx->cur_input)) {
			/* Input stream gave less data than expected */
			i_error("FETCH %s for mailbox %s UID %u "
				"got too little data (copying): "
				"%"PRIuUOFF_T" vs %"PRIuUOFF_T,
				ctx->cur_name, mailbox_get_vname(ctx->mail->box),
				ctx->mail->uid, ctx->cur_offset, ctx->cur_size);
			mail_set_cache_corrupted(ctx->mail,
						 ctx->cur_size_field);
			client_disconnect(ctx->client, "FETCH failed");
			return -1;
		}

		o_stream_set_flush_pending(ctx->client->output, TRUE);
		return 0;
	}
	return 1;
}
Exemple #8
0
static bool cmd_getscript_continue(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_getscript_context *ctx = cmd->context;
	off_t ret;

	ret = o_stream_send_istream(client->output, ctx->script_stream);

	if ( ret < 0 ) {
		sieve_storage_set_critical(ctx->storage,
			"o_stream_send_istream(%s) failed: %m", 
			sieve_script_filename(ctx->script));
		ctx->failed = TRUE;
		return cmd_getscript_finish(ctx);
	}

	ctx->script_offset += ret;

	if ( ctx->script_offset != ctx->script_size && !ctx->failed ) {
		/* unfinished */
		if ( !i_stream_have_bytes_left(ctx->script_stream) ) {
			/* Input stream gave less data than expected */
			sieve_storage_set_critical(ctx->storage,
				"GETSCRIPT for SCRIPT %s got too little data: "
				"%"PRIuUOFF_T" vs %"PRIuUOFF_T, sieve_script_name(ctx->script),
				ctx->script_offset, ctx->script_size);

			client_disconnect(ctx->client, "GETSCRIPT failed");
			ctx->failed = TRUE;
			return cmd_getscript_finish(ctx);
		}

		return FALSE;
	}

	return cmd_getscript_finish(ctx);
}
static ssize_t i_stream_mail_filter_read(struct istream_private *stream)
{
	struct mail_filter_istream *mstream =
		(struct mail_filter_istream *)stream;
	ssize_t ret;

	if (mstream->ext_in == NULL) {
		stream->istream.stream_errno = EIO;
		return -1;
	}

	while ((ret = i_stream_mail_filter_read_once(mstream)) == 0) {
		if (!stream->istream.blocking)
			break;
	}
	if (ret == -1 && !i_stream_have_bytes_left(&stream->istream) &&
	    stream->istream.v_offset == 0) {
		/* EOF without any input -> assume the script is repoting
		   failure. pretty ugly way, but currently there's no error
		   reporting channel. */
		stream->istream.stream_errno = EIO;
	}
	return ret;
}
bool http_request_parser_pending_payload(struct http_request_parser *parser)
{
	if (parser->parser.payload == NULL)
		return FALSE;
	return i_stream_have_bytes_left(parser->parser.payload);
}
static int script_client_script_output(struct script_client *sclient)
{
	struct istream *input = sclient->input;
	struct ostream *output = sclient->script_output;
	const unsigned char *data;
	size_t size;
	int ret = 0;

	if ((ret = o_stream_flush(output)) <= 0) {
		if (ret < 0)
			script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO);
		return ret;
	}

	if ( input != NULL && output != NULL ) {
		do {
			while ( (data=i_stream_get_data(input, &size)) != NULL ) {
				ssize_t sent;
	
				if ( (sent=o_stream_send(output, data, size)) < 0 ) {
					script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO);
					return -1;
				}
	
				if ( sent == 0 )
					return 0;
				i_stream_skip(input, sent);
			}
		} while ( (ret=i_stream_read(input)) > 0 );

		if ( ret == 0 ) {
			// FIXME: not supposed to happen; returning 0 will poll the input stream
			return 0;
		}

		if ( ret < 0 ) {
			if ( !input->eof ) {
				script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO);
				return -1;
			} else if ( !i_stream_have_bytes_left(input) ) {
				i_stream_unref(&sclient->input);
				input = NULL;

				if ( (ret = o_stream_flush(output)) <= 0 ) {
					if ( ret < 0 )
						script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO);
					return ret;
				}
			} 
		}
	}

	if ( input == NULL ) {
		o_stream_unref(&sclient->script_output);

		if ( sclient->script_input == NULL ) {
			script_client_disconnect(sclient, FALSE);
		} else {
			sclient->close_output(sclient);
		}
		return 0;
	}

	return 1;
}
Exemple #12
0
static int
cmd_append_catenate_mpurl(struct client_command_context *cmd,
			  const char *caturl, struct imap_msgpart_url *mpurl)
{
	struct cmd_append_context *ctx = cmd->context;
	struct imap_msgpart_open_result mpresult;
	uoff_t newsize;
	const char *error;
	int ret;

	/* catenate URL */
	ret = imap_msgpart_url_read_part(mpurl, &mpresult, &error);
	if (ret < 0) {
		client_send_box_error(cmd, ctx->box);
		return -1;
	}
	if (ret == 0) {
		/* invalid url, abort */
		client_send_tagline(cmd,
			t_strdup_printf("NO [BADURL %s] %s.", caturl, error));
		return -1;
	}
	if (mpresult.size == 0) {
		/* empty input */
		return 0;
	}

	newsize = ctx->cat_msg_size + mpresult.size;
	if (newsize < ctx->cat_msg_size) {
		client_send_tagline(cmd,
			"NO [TOOBIG] Composed message grows too big.");
		return -1;
	}

	ctx->cat_msg_size = newsize;
	/* add this input stream to chain */
	i_stream_chain_append(ctx->catchain, mpresult.input);
	/* save by reading the chain stream */
	while (!i_stream_is_eof(mpresult.input)) {
		ret = i_stream_read(mpresult.input);
		i_assert(ret != 0); /* we can handle only blocking input here */
		if (mailbox_save_continue(ctx->save_ctx) < 0 || ret == -1)
			break;
	}

	if (mpresult.input->stream_errno != 0) {
		errno = mpresult.input->stream_errno;
		mail_storage_set_critical(ctx->box->storage,
			"read(%s) failed: %s (for CATENATE URL %s)",
			i_stream_get_name(mpresult.input),
			i_stream_get_error(mpresult.input), caturl);
		client_send_box_error(cmd, ctx->box);
		ret = -1;
	} else if (!mpresult.input->eof) {
		/* save failed */
		client_send_box_error(cmd, ctx->box);
		ret = -1;
	} else {
		/* all the input must be consumed, so istream-chain's read()
		   unreferences the stream and we can free its parent mail */
		i_assert(!i_stream_have_bytes_left(mpresult.input));
		ret = 0;
	}
	return ret;
}
Exemple #13
0
bool i_stream_is_eof(struct istream *stream)
{
	if (i_stream_get_data_size(stream) == 0)
		(void)i_stream_read(stream);
	return !i_stream_have_bytes_left(stream);
}