Beispiel #1
0
static void
fts_tika_parser_response(const struct http_response *response,
			 struct tika_fts_parser *parser)
{
	i_assert(parser->payload == NULL);

	switch (response->status) {
	case 200:
		/* read response */
		if (response->payload == NULL)
			parser->payload = i_stream_create_from_data("", 0);
		else {
			i_stream_ref(response->payload);
			parser->payload = response->payload;
		}
		break;
	case 204: /* empty response */
	case 415: /* Unsupported Media Type */
	case 422: /* Unprocessable Entity */
		if (parser->user->mail_debug) {
			i_debug("fts_tika: PUT %s failed: %u %s",
				mail_user_plugin_getenv(parser->user, "fts_tika"),
				response->status, response->reason);
		}
		parser->payload = i_stream_create_from_data("", 0);
		break;
	case 500:
		/* Server Error - the problem could be anything (in Tika or
		   HTTP server or proxy) and might be retriable, but Tika has
		   trouble processing some documents and throws up this error
		   every time for those documents.

		   Unfortunately we can't easily re-send the request here,
		   because we would have to re-send the entire payload, which
		   isn't available anymore here. So we'd need to indicate
		   in fts_parser_deinit() that we want to retry.
		   FIXME: do this in v2.3. For now we'll just ignore it. */
		i_info("fts_tika: PUT %s failed: %u %s - ignoring",
		       mail_user_plugin_getenv(parser->user, "fts_tika"),
		       response->status, response->reason);
		parser->payload = i_stream_create_from_data("", 0);
		break;

	default:
		i_error("fts_tika: PUT %s failed: %u %s",
			mail_user_plugin_getenv(parser->user, "fts_tika"),
			response->status, response->reason);
		parser->failed = TRUE;
		break;
	}
	parser->http_req = NULL;
	io_loop_stop(current_ioloop);
}
Beispiel #2
0
static void
fts_tika_parser_response(const struct http_response *response,
                         struct tika_fts_parser *parser)
{
    i_assert(parser->payload == NULL);

    switch (response->status) {
    case 200:
        /* read response */
        if (response->payload == NULL)
            parser->payload = i_stream_create_from_data("", 0);
        else {
            i_stream_ref(response->payload);
            parser->payload = response->payload;
        }
        break;
    case 204: /* empty response */
    case 415: /* Unsupported Media Type */
    case 422: /* Unprocessable Entity */
        if (parser->user->mail_debug) {
            i_debug("fts_tika: PUT %s failed: %u %s",
                    mail_user_plugin_getenv(parser->user, "fts_tika"),
                    response->status, response->reason);
        }
        parser->payload = i_stream_create_from_data("", 0);
        break;
    case 500:
        /* Server Error - the problem could be anything (in Tika or
           HTTP server or proxy) and might be retriable, but Tika has
           trouble processing some documents and throws up this error
           every time for those documents. So we try retrying this a
           couple of times, but if that doesn't work we'll just ignore
           it. */
        if (http_client_request_try_retry(parser->http_req))
            return;
        i_info("fts_tika: PUT %s failed: %u %s - ignoring",
               mail_user_plugin_getenv(parser->user, "fts_tika"),
               response->status, response->reason);
        parser->payload = i_stream_create_from_data("", 0);
        break;

    default:
        i_error("fts_tika: PUT %s failed: %u %s",
                mail_user_plugin_getenv(parser->user, "fts_tika"),
                response->status, response->reason);
        parser->failed = TRUE;
        break;
    }
    parser->http_req = NULL;
    io_loop_stop(current_ioloop);
}
static int
sieve_attribute_set_active_script(struct mail_storage *storage,
			   struct sieve_storage *svstorage,
			   const struct mail_attribute_value *value)
{
	struct istream *input;

	if (value->value != NULL) {
		input = i_stream_create_from_data(value->value, strlen(value->value));
	} else if (value->value_stream != NULL) {
		input = value->value_stream;
		i_stream_ref(input);
	} else {
		return sieve_attribute_unset_active_script(storage, svstorage, value->last_change);
	}
	/* skip over the 'S' type */
	i_stream_skip(input, 1);

	if (sieve_storage_save_as_active
		(svstorage, input, value->last_change) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save active sieve script: %s",
			sieve_storage_get_last_error(svstorage, NULL));
		i_stream_unref(&input);
		return -1;
	}

	sieve_storage_set_modified(svstorage, value->last_change);
	i_stream_unref(&input);
	return 0;
}
int32_t elasticsearch_connection_post(struct elasticsearch_connection *conn,
                                      const char *url, const char *cmd)
{
    struct http_client_request *http_req = NULL;
    struct istream *post_payload = NULL;

    if (conn == NULL || url == NULL || cmd == NULL) {
        i_error("fts_elasticsearch: connection_post: critical error during POST");

        return -1;
    } else {
        /* safe to continue */
    }

    /* binds a callback object to elasticsearch_connection_http_response */
    http_req = elasticsearch_connection_http_request(conn, url);

    post_payload = i_stream_create_from_data(cmd, strlen(cmd));
    http_client_request_set_payload(http_req, post_payload, TRUE);
    i_stream_unref(&post_payload);
    http_client_request_submit(http_req);

    conn->request_status = 0;
    http_client_wait(elasticsearch_http_client);

    return conn->request_status;
}
Beispiel #5
0
int mbox_file_open_stream(struct mbox_mailbox *mbox)
{
	if (mbox->mbox_stream != NULL)
		return 0;

	if (mbox->mbox_file_stream != NULL) {
		/* read-only mbox stream */
		i_assert(mbox->mbox_fd == -1 && mbox_is_backend_readonly(mbox));
	} else {
		if (mbox->mbox_fd == -1) {
			if (mbox_file_open(mbox) < 0)
				return -1;
		}

		if (mbox->mbox_writeonly) {
			mbox->mbox_file_stream =
				i_stream_create_from_data("", 0);
		} else {
			mbox->mbox_file_stream =
				i_stream_create_fd(mbox->mbox_fd,
						   MBOX_READ_BLOCK_SIZE);
			i_stream_set_init_buffer_size(mbox->mbox_file_stream,
						      MBOX_READ_BLOCK_SIZE);
		}
		i_stream_set_name(mbox->mbox_file_stream,
				  mailbox_get_path(&mbox->box));
	}

	mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream);
	if (mbox->mbox_lock_type != F_UNLCK)
		istream_raw_mbox_set_locked(mbox->mbox_stream);
	return 0;
}
static void
test_istream_base64_encoder_seek(const char *textin, const char *textout)
{
	unsigned int offset, len = strlen(textout);
	struct istream *input, *input_data;
	const unsigned char *data;
	size_t size;
	ssize_t ret;

	input_data = i_stream_create_from_data(textin, strlen(textin));
	input = i_stream_create_base64_encoder(input_data, 4, TRUE);

	while (i_stream_read(input) > 0) ;
	i_stream_skip(input, i_stream_get_data_size(input));

	for (offset = 0; offset < len; offset++) {
		i_stream_seek(input, offset);
		while ((ret = i_stream_read(input)) > 0) ;
		test_assert(ret == -1);

		data = i_stream_get_data(input, &size);
		test_assert(size == len-offset);
		test_assert(memcmp(data, textout+offset, size) == 0);
		i_stream_skip(input, size);
	}

	i_stream_unref(&input);
	i_stream_unref(&input_data);
}
Beispiel #7
0
ARRAY_TYPE(imap_arg_list) *
test_parse_imap_args(pool_t pool, const char *line, unsigned int linelen,
		     const char **error_r)
{
	struct imap_parser *imap_parser;
	struct istream *input;
	const struct imap_arg *args;
	ARRAY_TYPE(imap_arg_list) *dup_args;
	enum imap_parser_error fatal;
	int ret;

	input = i_stream_create_from_data(line, linelen);
	imap_parser = imap_parser_create(input, NULL, (size_t)-1);
	ret = imap_parser_finish_line(imap_parser, 0,
				      IMAP_PARSE_FLAG_LITERAL8 |
				      IMAP_PARSE_FLAG_LITERAL_TYPE |
				      IMAP_PARSE_FLAG_ATOM_ALLCHARS |
				      IMAP_PARSE_FLAG_MULTILINE_STR, &args);
	if (ret < 0) {
		dup_args = NULL;
		if (ret == -2)
			*error_r = "Missing data";
		else {
			*error_r = t_strdup(imap_parser_get_error(imap_parser,
								  &fatal));
		}
	} else {
		dup_args = test_parse_imap_args_dup(pool, args);
	}
	imap_parser_unref(&imap_parser);
	i_stream_unref(&input);
	return dup_args;
}
Beispiel #8
0
static void cmd_append_catenate_text(struct client_command_context *cmd)
{
	struct cmd_append_context *ctx = cmd->context;

	if (ctx->literal_size > (uoff_t)-1 - ctx->cat_msg_size &&
	    !ctx->failed) {
		client_send_tagline(cmd,
			"NO [TOOBIG] Composed message grows too big.");
		ctx->failed = TRUE;
	}

	/* save the mail */
	ctx->cat_msg_size += ctx->literal_size;
	if (ctx->literal_size == 0) {
		/* zero length literal. RFC doesn't explicitly specify
		   what should be done with this, so we'll simply
		   handle it by skipping the empty text part. */
		ctx->litinput = i_stream_create_from_data("", 0);
		ctx->litinput->eof = TRUE;
	} else {
		ctx->litinput = i_stream_create_limit(cmd->client->input,
						      ctx->literal_size);
		i_stream_chain_append(ctx->catchain, ctx->litinput);
	}
}
static void test_dsync_proxy_msg_save(void)
{
	static const char *input = "..dotty\n..behavior\nfrom you\n.\nstop";
	struct test_dsync_msg_event event;
	const unsigned char *data;
	size_t size;

	test_begin("proxy server msg save");

	server->input = i_stream_create_from_data(input, strlen(input));

	test_assert(run_cmd("MSG-SAVE", "28492428", "pop3uidl",
			    "saveguid", "874", "33982482882924", "\\Flagged bar \\Answered",
			    "8294284", NULL) == 1);
	test_assert(test_dsync_worker_next_msg_event(test_worker, &event));
	test_assert(event.type == LAST_MSG_TYPE_SAVE);
	test_assert(event.save_data.received_date == 28492428);
	test_assert(strcmp(event.save_data.pop3_uidl, "pop3uidl") == 0);
	test_assert(strcmp(event.save_body, ".dotty\n.behavior\nfrom you") == 0);

	test_assert(strcmp(event.msg.guid, "saveguid") == 0);
	test_assert(event.msg.uid == 874);
	test_assert(event.msg.modseq == 33982482882924);
	test_assert(event.msg.flags == (MAIL_FLAGGED | MAIL_ANSWERED));
	test_assert(strcmp(event.msg.keywords[0], "bar") == 0);
	test_assert(event.msg.keywords[1] == NULL);
	test_assert(event.msg.save_date == 8294284);

	data = i_stream_get_data(server->input, &size);
	test_assert(size == 4 && memcmp(data, "stop", 4) == 0);
	i_stream_destroy(&server->input);

	test_end();
}
static struct message_part *msg_parse(pool_t pool, bool parse_bodystructure)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_block block;
	struct message_part *parts;
	int ret;

	input = i_stream_create_from_data(testmsg, sizeof(testmsg)-1);
	parser = message_parser_init(pool, input,
			MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
			MESSAGE_HEADER_PARSER_FLAG_DROP_CR,
			MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
		if (parse_bodystructure) {
			imap_bodystructure_parse_header(pool, block.part,
							block.hdr);
		}
	}
	test_assert(ret < 0);

	test_assert(message_parser_deinit(&parser, &parts) == 0);
	i_stream_unref(&input);
	return parts;
}
Beispiel #11
0
struct istream *iostream_temp_finish(struct ostream **output,
				     size_t max_buffer_size)
{
	struct temp_ostream *tstream =
		(struct temp_ostream *)(*output)->real_stream;
	struct istream *input, *input2;
	uoff_t abs_offset, size;
	const char *for_path;
	int fd;

	if (tstream->name[0] == '\0')
		for_path = "";
	else
		for_path = t_strdup_printf(" for %s", tstream->name);

	if (tstream->dupstream != NULL && !tstream->dupstream->closed) {
		abs_offset = i_stream_get_absolute_offset(tstream->dupstream) -
			tstream->dupstream->v_offset +
			tstream->dupstream_start_offset;
		size = tstream->dupstream_offset -
			tstream->dupstream_start_offset;
		fd = dup(i_stream_get_fd(tstream->dupstream));
		if (fd == -1)
			input = i_stream_create_error_str(errno, "dup() failed: %m");
		else {
			input2 = i_stream_create_fd_autoclose(&fd, max_buffer_size);
			i_stream_seek(input2, abs_offset);
			input = i_stream_create_limit(input2, size);
			i_stream_unref(&input2);
		}
		i_stream_set_name(input, t_strdup_printf(
			"(Temp file in %s%s, from %s)", tstream->temp_path_prefix,
			for_path, i_stream_get_name(tstream->dupstream)));
		i_stream_unref(&tstream->dupstream);
	} else if (tstream->dupstream != NULL) {
		/* return the original failed stream. */
		input = tstream->dupstream;
	} else if (tstream->fd != -1) {
		int fd = tstream->fd;
		input = i_stream_create_fd_autoclose(&tstream->fd, max_buffer_size);
		i_stream_set_name(input, t_strdup_printf(
			"(Temp file fd %d in %s%s, %"PRIuUOFF_T" bytes)",
			fd, tstream->temp_path_prefix, for_path, tstream->fd_size));
	} else {
		input = i_stream_create_from_data(tstream->buf->data,
						  tstream->buf->used);
		i_stream_set_name(input, t_strdup_printf(
			"(Temp buffer in %s%s, %"PRIuSIZE_T" bytes)",
			tstream->temp_path_prefix, for_path, tstream->buf->used));
		i_stream_add_destroy_callback(input, iostream_temp_buf_destroyed,
					      tstream->buf);
		tstream->buf = NULL;
	}
	o_stream_destroy(output);
	return input;
}
Beispiel #12
0
struct dsync_worker *dsync_worker_init_test(void)
{
	struct test_dsync_worker *worker;

	worker = i_new(struct test_dsync_worker, 1);
	worker->worker.v = test_dsync_worker;
	worker->tmp_pool = pool_alloconly_create("test worker", 256);
	i_array_init(&worker->box_events, 64);
	i_array_init(&worker->msg_events, 64);
	i_array_init(&worker->results, 64);
	worker->body_stream = i_stream_create_from_data("hdr\n\nbody", 9);
	return &worker->worker;
}
Beispiel #13
0
static struct istream *
mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input)
{
	struct istream *filter, *ret, *cache_input, *streams[3];

	/* filter out unwanted headers and keep track of headers' MD5 sum */
	filter = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
					       HEADER_FILTER_NO_CR |
					       HEADER_FILTER_ADD_MISSING_EOH |
					       HEADER_FILTER_END_BODY_WITH_LF,
					       mbox_save_drop_headers,
					       mbox_save_drop_headers_count,
					       save_header_callback, ctx);

	if ((ctx->mbox->storage->storage.flags &
	     MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0) {
		/* we're using MD5 sums to generate POP3 UIDLs.
		   clients don't like it much if there are duplicates,
		   so make sure that there can't be any by appending
		   our own X-Delivery-ID header. */
		const char *hdr;

		T_BEGIN {
			mbox_save_x_delivery_id(ctx);
		} T_END;
		hdr = ctx->x_delivery_id_header;

		streams[0] = i_stream_create_from_data(hdr, strlen(hdr));
		streams[1] = filter;
		streams[2] = NULL;
		ret = i_stream_create_concat(streams);
		i_stream_unref(&filter);
		filter = ret;
	}

	/* convert linefeeds to wanted format */
	ret = ctx->mbox->storage->storage.set->mail_save_crlf ?
		i_stream_create_crlf(filter) : i_stream_create_lf(filter);
	i_stream_unref(&filter);

	if (ctx->ctx.dest_mail != NULL) {
		/* caching creates a tee stream */
		cache_input =
			index_mail_cache_parse_init(ctx->ctx.dest_mail, ret);
		i_stream_unref(&ret);
		ret = cache_input;
	}
	return ret;
}
Beispiel #14
0
static void
fts_tika_parser_response(const struct http_response *response,
			 struct tika_fts_parser *parser)
{
	i_assert(parser->payload == NULL);

	switch (response->status) {
	case 200:
		/* read response */
		if (response->payload == NULL)
			parser->payload = i_stream_create_from_data("", 0);
		else {
			i_stream_ref(response->payload);
			parser->payload = response->payload;
		}
		break;
	case 204: /* empty response */
	case 415: /* Unsupported Media Type */
	case 422: /* Unprocessable Entity */
		if (parser->user->mail_debug) {
			i_debug("fts_tika: PUT %s failed: %u %s",
				mail_user_plugin_getenv(parser->user, "fts_tika"),
				response->status, response->reason);
		}
		parser->payload = i_stream_create_from_data("", 0);
		break;
	default:
		i_error("fts_tika: PUT %s failed: %u %s",
			mail_user_plugin_getenv(parser->user, "fts_tika"),
			response->status, response->reason);
		parser->failed = TRUE;
		break;
	}
	parser->http_req = NULL;
	io_loop_stop(current_ioloop);
}
Beispiel #15
0
struct mail_raw *mail_raw_open_data
(struct mail_user *ruser, string_t *mail_data)
{
	struct mail_raw *mailr;
	struct istream *input;

	input = i_stream_create_from_data(str_data(mail_data), str_len(mail_data));
	i_stream_set_name(input, "data");

	mailr = mail_raw_create(ruser, input, NULL, NULL, (time_t)-1);

	i_stream_unref(&input);

	return mailr;
}
Beispiel #16
0
void http_client_request_set_payload_data(struct http_client_request *req,
				     const unsigned char *data, size_t size)
{
	struct istream *input;
	unsigned char *payload_data;

	if (size == 0)
		return;

	payload_data = p_malloc(req->pool, size);
	memcpy(payload_data, data, size);
	input = i_stream_create_from_data(payload_data, size);

	http_client_request_set_payload(req, input, FALSE);
	i_stream_unref(&input);
}
static void test_message_snippet(void)
{
	string_t *str = t_str_new(128);
	struct istream *input;
	unsigned int i;

	test_begin("message snippet");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		str_truncate(str, 0);
		input = i_stream_create_from_data(tests[i].input, strlen(tests[i].input));
		test_assert_idx(message_snippet_generate(input, tests[i].max_snippet_chars, str) == 0, i);
		test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i);
		i_stream_destroy(&input);
	}
	test_end();
}
Beispiel #18
0
static int
imapc_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct imapc_mail *mail = (struct imapc_mail *)_mail;
	struct index_mail_data *data = &mail->imail.data;
	enum mail_fetch_field fetch_field;

	if (get_body && !mail->body_fetched &&
	    mail->imail.data.stream != NULL) {
		/* we've fetched the header, but we need the body now too */
		index_mail_close_streams(&mail->imail);
	}

	if (data->stream == NULL) {
		if (!data->initialized) {
			/* coming here from mail_set_seq() */
			mail_set_aborted(_mail);
			return -1;
		}
		fetch_field = get_body ||
			(data->access_part & READ_BODY) != 0 ?
			MAIL_FETCH_STREAM_BODY : MAIL_FETCH_STREAM_HEADER;
		if (imapc_mail_fetch(_mail, fetch_field) < 0)
			return -1;

		if (data->stream == NULL) {
			if (imapc_mail_failed(_mail, "BODY[]") < 0)
				return -1;
			i_assert(data->stream == NULL);

			/* this could be either a temporary server bug, or the
			   server may permanently just not return anything for
			   this mail. the latter happens at least with Exchange
			   when trying to fetch calendar "mails", so we'll just
			   return them as empty mails instead of disconnecting
			   the client. */
			mail->body_fetched = TRUE;
			data->stream = i_stream_create_from_data(&uchar_nul, 0);
			imapc_mail_init_stream(mail, TRUE);
		}
	}

	return index_mail_init_stream(&mail->imail, hdr_size, body_size,
				      stream_r);
}
static int
sieve_attribute_retrieve_script(struct mail_storage *storage,
			   struct sieve_storage *svstorage, struct sieve_script *script,
			   bool add_type_prefix,
			   struct mail_attribute_value *value_r, const char **errorstr_r)
{
	static char type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT;
	struct istream *input, *inputs[3];
	const struct stat *st;
	enum sieve_error error;

	if (script == NULL)
		*errorstr_r = sieve_storage_get_last_error(svstorage, &error);
	else if (sieve_script_get_stream(script, &input, &error) < 0)
		sieve_script_unref(&script);
	
	if (script == NULL) {
		if (error == SIEVE_ERROR_NOT_FOUND) {
			/* already deleted, but return the last_change */
			(void)sieve_storage_get_last_change(svstorage,
							    &value_r->last_change);
			return 0;
		}
		*errorstr_r = sieve_storage_get_last_error(svstorage, &error);
		return -1;
	}
	if (i_stream_stat(input, FALSE, &st) < 0) {
		mail_storage_set_critical(storage,
			"stat(%s) failed: %m", i_stream_get_name(input));
	} else {
		value_r->last_change = st->st_mtime;
	}
	if (!add_type_prefix) {
		i_stream_ref(input);
		value_r->value_stream = input;
	} else {
		inputs[0] = i_stream_create_from_data(&type, 1);
		inputs[1] = input;
		inputs[2] = NULL;
		value_r->value_stream = i_stream_create_concat(inputs);
		i_stream_unref(&inputs[0]);
	}
	sieve_script_unref(&script);
	return 1;
}
Beispiel #20
0
static int
imapc_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct imapc_mail *mail = (struct imapc_mail *)_mail;
	struct index_mail_data *data = &mail->imail.data;
	enum mail_fetch_field fetch_field;

	if (get_body && !mail->body_fetched &&
	    mail->imail.data.stream != NULL) {
		/* we've fetched the header, but we need the body now too */
		index_mail_close_streams(&mail->imail);
	}

	if (data->stream == NULL) {
		if (!data->initialized) {
			/* coming here from mail_set_seq() */
			mail_set_aborted(_mail);
			return -1;
		}
		fetch_field = get_body ||
			(data->access_part & READ_BODY) != 0 ?
			MAIL_FETCH_STREAM_BODY : MAIL_FETCH_STREAM_HEADER;
		if (imapc_mail_fetch(_mail, fetch_field, NULL) < 0)
			return -1;

		if (data->stream == NULL) {
			if (imapc_mail_failed(_mail, "BODY[]"))
				return -1;
			i_assert(data->stream == NULL);

			/* return the broken email as empty */
			mail->body_fetched = TRUE;
			data->stream = i_stream_create_from_data(NULL, 0);
			imapc_mail_init_stream(mail);
		}
	}

	return index_mail_init_stream(&mail->imail, hdr_size, body_size,
				      stream_r);
}
Beispiel #21
0
static void test_message_part_idx(void)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_part *parts, *part, *prev_part;
	struct message_block block;
	unsigned int i, prev_idx = 0, part_idx;
	pool_t pool;
	int ret;

	test_begin("message part indexes");
	pool = pool_alloconly_create("message parser", 10240);
	input = i_stream_create_from_data(test_msg, TEST_MSG_LEN);

	parser = message_parser_init(pool, input, 0, 0);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
		part_idx = message_part_to_idx(block.part);
		test_assert(part_idx >= prev_idx);
		prev_idx = part_idx;
	}
	test_assert(ret < 0);
	test_assert(message_parser_deinit(&parser, &parts) == 0);

	part = message_part_by_idx(parts, 0);
	test_assert(part == parts);
	test_assert(message_part_by_idx(parts, 1) == parts->children);

	for (i = 1; i < 11; i++) {
		prev_part = part;
		part = message_part_by_idx(parts, i);
		test_assert(part != NULL);
		test_assert(part != NULL && message_part_to_idx(part) == i);
		test_assert(part != NULL && prev_part != NULL &&
			    prev_part->physical_pos < part->physical_pos);
	}
	test_assert(message_part_by_idx(parts, i) == NULL);

	i_stream_unref(&input);
	pool_unref(&pool);
	test_end();
}
Beispiel #22
0
void test_istream_failure_at(void)
{
	struct istream *input, *data_input;
	unsigned char test_data[TEST_DATA_LENGTH];
	unsigned int i;
	ssize_t ret;

	test_begin("istream failure at");
	for (i = 0; i < sizeof(test_data); i++)
		test_data[i] = i;
	data_input = i_stream_create_from_data(test_data, sizeof(test_data));
	for (i = 0; i < TEST_DATA_LENGTH; i++) {
		i_stream_seek(data_input, 0);
		input = i_stream_create_failure_at(data_input, i, EIO, TEST_ERRMSG);
		while ((ret = i_stream_read(input)) > 0)
			i_stream_skip(input, ret);
		test_assert_idx(ret == -1 && input->v_offset == i &&
				input->stream_errno == EIO &&
				strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i);
		i_stream_destroy(&input);
	}
	/* shouldn't fail */
	i_stream_seek(data_input, 0);
	input = i_stream_create_failure_at(data_input, TEST_DATA_LENGTH, EIO, TEST_ERRMSG);
	while ((ret = i_stream_read(input)) > 0)
		i_stream_skip(input, ret);
	test_assert(ret == -1 && input->stream_errno == 0);
	i_stream_destroy(&input);
	/* fail at EOF */
	i_stream_seek(data_input, 0);
	input = i_stream_create_failure_at_eof(data_input, EIO, TEST_ERRMSG);
	while ((ret = i_stream_read(input)) > 0)
		i_stream_skip(input, ret);
	test_assert_idx(ret == -1 && input->v_offset == TEST_DATA_LENGTH &&
			input->stream_errno == EIO &&
			strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i);
	i_stream_destroy(&input);
	i_stream_destroy(&data_input);
	test_end();
}
static struct mail_search_args *
virtual_search_args_parse(const string_t *rule, const char **error_r)
{
	struct istream *input;
	struct imap_parser *imap_parser;
	const struct imap_arg *args;
	struct mail_search_parser *parser;
	struct mail_search_args *sargs;
	const char *charset = "UTF-8";
	bool fatal;
	int ret;

	if (str_len(rule) == 0) {
		sargs = mail_search_build_init();
		mail_search_build_add_all(sargs);
		return sargs;
	}

	input = i_stream_create_from_data(str_data(rule), str_len(rule));
	(void)i_stream_read(input);

	imap_parser = imap_parser_create(input, NULL, (size_t)-1);
	ret = imap_parser_finish_line(imap_parser, 0,  0, &args);
	if (ret < 0) {
		sargs = NULL;
		*error_r = t_strdup(imap_parser_get_error(imap_parser, &fatal));
	} else {
		parser = mail_search_parser_init_imap(args);
		if (mail_search_build(mail_search_register_get_imap(),
				      parser, &charset, &sargs, error_r) < 0)
			sargs = NULL;
		mail_search_parser_deinit(&parser);
	}

	imap_parser_unref(&imap_parser);
	i_stream_destroy(&input);
	return sargs;
}
Beispiel #24
0
const char *imap_id_reply_generate(const char *settings)
{
	struct istream *input;
	struct imap_parser *parser;
	const struct imap_arg *args;
	const char *ret;

	if (settings == NULL)
		return "NIL";

	input = i_stream_create_from_data(settings, strlen(settings));
	(void)i_stream_read(input);

	parser = imap_parser_create(input, NULL, (size_t)-1);
	if (imap_parser_finish_line(parser, 0, 0, &args) <= 0)
		ret = "NIL";
	else
		ret = imap_id_reply_generate_from_imap_args(args);

	imap_parser_unref(&parser);
	i_stream_destroy(&input);
	return ret;
}
static int
sieve_attribute_set_sieve(struct mail_storage *storage,
			  const char *key,
			  const struct mail_attribute_value *value)
{
	struct sieve_storage *svstorage;
	struct sieve_storage_save_context *save_ctx;
	struct istream *input;
	const char *scriptname;
	int ret;

	if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) {
		if (ret == 0) {
			mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
					       "Sieve not enabled for user");
		}
		return -1;
	}

	if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0)
		return sieve_attribute_set_default(storage, svstorage, value);
	if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
		    strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) != 0) {
		mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
				       "Nonexistent sieve attribute");
		return -1;
	}
	scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES);

	if (value->value != NULL) {
		input = i_stream_create_from_data(value->value,
						  strlen(value->value));
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
		i_stream_unref(&input);
	} else if (value->value_stream != NULL) {
		input = value->value_stream;
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
	} else {
		return sieve_attribute_unset_script(storage, svstorage, scriptname);
	}

	if (save_ctx == NULL) {
		/* save initialization failed */
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		return -1;
	}

	sieve_storage_save_set_mtime(save_ctx, value->last_change);

	ret = 0;
	while (i_stream_read(input) > 0) {
		if (sieve_storage_save_continue(save_ctx) < 0) {
			mail_storage_set_critical(storage,
				"Failed to save sieve script '%s': %s", scriptname,
				sieve_storage_get_last_error(svstorage, NULL));
			ret = -1;
			break;
		}
	}
	i_assert(input->eof || ret < 0);
	if (input->stream_errno != 0) {
		errno = input->stream_errno;
		mail_storage_set_critical(storage,
			"Saving sieve script: read(%s) failed: %m",
			i_stream_get_name(input));
		ret = -1;
	}
	if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	if (ret < 0)
		sieve_storage_save_cancel(&save_ctx);
	else if (sieve_storage_save_commit(&save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	return ret;
}
Beispiel #26
0
static int
http_client_request_continue_payload(struct http_client_request **_req,
	const unsigned char *data, size_t size)
{
	struct ioloop *prev_ioloop = current_ioloop;
	struct http_client_request *req = *_req;
	struct http_client_connection *conn = req->conn;
	struct http_client *client = req->client;
	int ret;

	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
		req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
	i_assert(req->payload_input == NULL);

	if (conn != NULL)
		http_client_connection_ref(conn);
	http_client_request_ref(req);
	req->payload_wait = TRUE;

	if (data == NULL) {
		req->payload_input = NULL;
		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
			http_client_request_finish_payload_out(req);
	} else { 
		req->payload_input = i_stream_create_from_data(data, size);
		i_stream_set_name(req->payload_input, "<HTTP request payload>");
	}
	req->payload_size = 0;
	req->payload_chunked = TRUE;

	if (req->state == HTTP_REQUEST_STATE_NEW)
		http_client_request_submit(req);

	/* Wait for payload data to be written */

	i_assert(client->ioloop == NULL);
	client->ioloop = io_loop_create();
	http_client_switch_ioloop(client);
	if (client->set.dns_client != NULL)
		dns_client_switch_ioloop(client->set.dns_client);

	while (req->state < HTTP_REQUEST_STATE_PAYLOAD_IN) {
		http_client_request_debug(req, "Waiting for request to finish");
		
		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
			o_stream_set_flush_pending(req->payload_output, TRUE);
		io_loop_run(client->ioloop);

		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT &&
			req->payload_input->eof) {
			i_stream_unref(&req->payload_input);
			req->payload_input = NULL;
			break;
		}
	}

	io_loop_set_current(prev_ioloop);
	http_client_switch_ioloop(client);
	if (client->set.dns_client != NULL)
		dns_client_switch_ioloop(client->set.dns_client);
	io_loop_set_current(client->ioloop);
	io_loop_destroy(&client->ioloop);

	switch (req->state) {
	case HTTP_REQUEST_STATE_PAYLOAD_IN:
	case HTTP_REQUEST_STATE_FINISHED:
		ret = 1;
		break;
	case HTTP_REQUEST_STATE_ABORTED:
		ret = -1;
		break;
	default:
		ret = 0;
		break;
	}

	req->payload_wait = FALSE;

	/* callback may have messed with our pointer,
	   so unref using local variable */	
	if (!http_client_request_unref(&req))
		*_req = NULL;

	if (conn != NULL)
		http_client_connection_unref(&conn);

	/* Return status */
	return ret;
}
Beispiel #27
0
static void test_istream_crlf_input(const char *input)
{
	string_t *output;
	const unsigned char *data;
	size_t size = 0;
	ssize_t ret1, ret2;
	unsigned int i, j, pos, input_len = strlen(input);
	struct istream *istream, *crlf_istream;

	output = t_str_new(256);

	for (j = 0; j < 4; j++) {
		istream = i_stream_create_from_data(input, input_len);
		str_truncate(output, 0);
		if (j%2 == 0) {
			/* drop CRs */
			crlf_istream = i_stream_create_lf(istream);
			for (i = 0; i < input_len; i++) {
				if (input[i] == '\r' &&
				    (i == input_len || input[i+1] == '\n'))
					;
				else
					str_append_c(output, input[i]);
			}
		} else {
			/* add missing CRs */
			crlf_istream = i_stream_create_crlf(istream);
			for (i = 0; i < input_len; i++) {
				if (input[i] == '\n' &&
				    (i == 0 || input[i-1] != '\r'))
					str_append_c(output, '\r');
				str_append_c(output, input[i]);
			}
		}

		pos = 0;
		for (i = 1; i <= input_len; i++) {
			if (j >= 2) {
				i_stream_unref(&istream);
				i_stream_unref(&crlf_istream);
				istream = i_stream_create_from_data(input,
								    input_len);
				crlf_istream = j%2 == 0 ?
					i_stream_create_lf(istream) :
					i_stream_create_crlf(istream);
				pos = 0;
			}
			istream->real_stream->pos = i;
			ret1 = i_stream_read(crlf_istream);
			if (crlf_istream->real_stream->buffer_size != 0) {
				/* this is pretty evil */
				crlf_istream->real_stream->buffer_size =
					I_MAX(crlf_istream->real_stream->pos, i);
			}
			ret2 = i_stream_read(crlf_istream);
			data = i_stream_get_data(crlf_istream, &size);
			if (ret1 > 0 || ret2 > 0) {
				ret1 = I_MAX(ret1, 0) + I_MAX(ret2, 0);
				test_assert(pos + (unsigned int)ret1 == size);
				pos += ret1;
			}
			test_assert(memcmp(data, str_data(output), size) == 0);
		}
		test_assert(size == str_len(output));
		i_stream_unref(&crlf_istream);
		i_stream_unref(&istream);
	}
}
Beispiel #28
0
static int cmd_execute_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{	
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	struct sieve_side_effects_list *slist = NULL;
	int opt_code = 0;
	unsigned int is_test = 0;
	struct sieve_stringlist *args_list = NULL;
	string_t *pname = NULL, *input = NULL;
	struct sieve_variable_storage *var_storage = NULL;
	unsigned int var_index;
	bool have_input = FALSE;
	const char *program_name = NULL;
	const char *const *args = NULL;
	enum sieve_error error = SIEVE_ERROR_NONE;
	buffer_t *outbuf = NULL;
	struct sieve_extprogram *sprog = NULL;
	int ret;

	/*
	 * Read operands
	 */

	/* The is_test flag */
	if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) {
		sieve_runtime_trace_error(renv, "invalid is_test flag");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	/* Optional operands */	

	for (;;) {
		int opt;

		if ( (opt=sieve_action_opr_optional_read
			(renv, address, &opt_code, &ret, &slist)) < 0 )
			return ret;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_INPUT:
			ret = sieve_opr_string_read_ex
				(renv, address, "input", TRUE, &input, NULL);
			have_input = TRUE;
			break;
		case OPT_OUTPUT:
			ret = sieve_variable_operand_read
				(renv, address, "output", &var_storage, &var_index);
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			return SIEVE_EXEC_BIN_CORRUPT;
		}

		if ( ret <= 0 ) return ret;
	}

	/* Fixed operands */

	if ( (ret=sieve_extprogram_command_read_operands
		(renv, address, &pname, &args_list)) <= 0 )
		return ret;

	program_name = str_c(pname);
	if ( args_list != NULL &&
		sieve_stringlist_read_all(args_list, pool_datastack_create(), &args) < 0 ) {
		sieve_runtime_trace_error(renv, "failed to read args operand");
		return args_list->exec_status;
	}

	/*
	 * Perform operation
	 */

	/* Trace */

	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "execute action");
	sieve_runtime_trace_descend(renv);
	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS,
		"execute program `%s'", str_sanitize(program_name, 128));

	sprog = sieve_extprogram_create
		(this_ext, renv->scriptenv, renv->msgdata, "execute", program_name, args,
			&error);
	if ( sprog != NULL ) {
		if ( var_storage != NULL ) {
			// FIXME: limit output size
			struct ostream *outdata;

			outbuf = buffer_create_dynamic(pool_datastack_create(), 1024);
			outdata = o_stream_create_buffer(outbuf);
			sieve_extprogram_set_output(sprog, outdata);
			o_stream_unref(&outdata);
		}

		if ( input == NULL && have_input ) {
			struct mail *mail = sieve_message_get_mail(renv->msgctx);

			if ( sieve_extprogram_set_input_mail(sprog, mail) < 0 ) {
				sieve_extprogram_destroy(&sprog);
				return sieve_runtime_mail_error(renv, mail,
					"execute action: failed to read input message");
			}
			ret = 1;
		} else if ( input != NULL ) {
			struct istream *indata =
				i_stream_create_from_data(str_data(input), str_len(input));
			sieve_extprogram_set_input(sprog, indata);
			i_stream_unref(&indata);
			ret = 1;
		}

		if ( ret >= 0 ) 
			ret = sieve_extprogram_run(sprog);
		sieve_extprogram_destroy(&sprog);
	} else {
		ret = -1;
	}

	if ( ret > 0 ) {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"executed program successfully");

		if ( var_storage != NULL ) {
			string_t *var;

			if ( sieve_variable_get_modifiable(var_storage, var_index, &var) ) {
				str_truncate(var, 0);
				str_append_str(var, outbuf); 

				sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
					"assigned output variable");
			} // FIXME: handle failure
		}

	} else if ( ret < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND ) {
			sieve_runtime_error(renv, NULL,
				"execute action: program `%s' not found",
				str_sanitize(program_name, 80));
		} else {
			sieve_extprogram_exec_error(renv->ehandler,
				sieve_runtime_get_full_command_location(renv),
				"execute action: failed to execute to program `%s'",
				str_sanitize(program_name, 80));
		}
	} else {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"execute action: program indicated false result");
	}

	if ( outbuf != NULL ) 
		buffer_free(&outbuf);

	if ( is_test )
		sieve_interpreter_set_test_result(renv->interp, ( ret > 0 ));

	return SIEVE_EXEC_OK;
}