static void
imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url,
			 enum imap_urlauth_fetch_flags url_flags,
			 struct imap_url *imap_url)
{
	struct imap_urlauth_fetch_reply reply;
	struct imap_msgpart_open_result mpresult;
	const char *error, *errormsg = NULL, *bpstruct = NULL;
	bool debug = ufetch->uctx->user->mail_debug, success;
	enum mail_error error_code;
	struct imap_msgpart_url *mpurl = NULL;
	int ret;

	success = TRUE;

	if (debug)
		i_debug("Fetching local URLAUTH %s", url);

	if (url_flags == 0)
		url_flags = IMAP_URLAUTH_FETCH_FLAG_BODY;

	/* fetch URL */
	if (imap_url == NULL) {
		ret = imap_urlauth_fetch(ufetch->uctx, url,
					 &mpurl, &error_code, &error);
	} else {
		ret = imap_urlauth_fetch_parsed(ufetch->uctx, imap_url,
						&mpurl, &error_code, &error);
	}
	if (ret <= 0) {
		if (ret == 0) {
			errormsg = t_strdup_printf("Failed to fetch URLAUTH \"%s\": %s",
						   url, error);
			if (debug)
				i_debug("%s", errormsg);
		}
		success = FALSE;
	}

	/* fetch metadata */
	if (success && (url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
		imap_msgpart_url_set_decode_to_binary(mpurl);
	if (success &&
	    (url_flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0) {
		ret = imap_msgpart_url_get_bodypartstructure(mpurl, &bpstruct, &error);
		if (ret <= 0) {
			if (ret == 0) {
				errormsg = t_strdup_printf
					("Failed to read URLAUTH \"%s\": %s",	url, error);
				if (debug)
					i_debug("%s", errormsg);
			}
			success = FALSE;
		}
	}

	/* if requested, read the message part the URL points to */
	memset(&mpresult, 0, sizeof(mpresult));
	if (success && ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0 ||
			(url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)) {
		ret = imap_msgpart_url_read_part(mpurl, &mpresult, &error);
		if (ret <= 0) {
			if (ret == 0) {
				errormsg = t_strdup_printf
					("Failed to read URLAUTH \"%s\": %s",	url, error);
				if (debug)
					i_debug("%s", errormsg);
			}
			success = FALSE;
		}
	}

	if (debug && success) {
		if (bpstruct != NULL)
			i_debug("Fetched URLAUTH yielded BODYPARTSTRUCTURE (%s)", bpstruct);
		if (mpresult.size == 0 || mpresult.input == NULL)
			i_debug("Fetched URLAUTH yielded empty result");
		else {
			i_debug("Fetched URLAUTH yielded %"PRIuUOFF_T" bytes "
				"of %smessage data", mpresult.size,
				(mpresult.binary_decoded_input_has_nuls ? "binary " : ""));
		}
	}

	ufetch->pending_requests--;

	if (!success && ret < 0) {
		if (mpurl != NULL)
			imap_msgpart_url_free(&mpurl);
		(void)ufetch->callback(NULL, TRUE, ufetch->context);
		imap_urlauth_fetch_fail(ufetch);
		return;
	}

	memset(&reply, 0, sizeof(reply));
	reply.url = url;
	reply.flags = url_flags;
	reply.error = errormsg;
	reply.succeeded = success;

	reply.bodypartstruct = bpstruct;
	reply.binary_has_nuls = mpresult.binary_decoded_input_has_nuls;
	reply.size = mpresult.size;
	reply.input = mpresult.input;

	ret = ufetch->callback(&reply, ufetch->pending_requests == 0,
			       ufetch->context);
	if (ret == 0) {
		ufetch->local_url = mpurl;
		ufetch->waiting_local = TRUE;
		ufetch->pending_requests++;
	} else {

		if (mpurl != NULL)
			imap_msgpart_url_free(&mpurl);
		if (ret < 0)
			imap_urlauth_fetch_fail(ufetch);
	}
}
Beispiel #2
0
static int
client_fetch_urlpart(struct client *client, const char *url,
		     enum imap_urlauth_fetch_flags url_flags,
		     const char **bpstruct_r, bool *binary_with_nuls_r,
		     const char **errormsg_r)
{
	const char *error;
	struct imap_msgpart_open_result mpresult;
	enum mail_error error_code;
	int ret;

	*bpstruct_r = NULL;
	*errormsg_r = NULL;
	*binary_with_nuls_r = FALSE;

	ret = imap_urlauth_fetch(client->urlauth_ctx, url,
				 &client->url, &error_code, &error);
	if (ret <= 0) {
		if (ret < 0)
			return -1;
		error = t_strdup_printf("Failed to fetch URLAUTH \"%s\": %s",
					url, error);
		if (client->debug)
			i_debug("%s", error);
		/* don't leak info about existence/accessibility
		   of mailboxes */
		if (error_code == MAIL_ERROR_PARAMS)
			*errormsg_r = error;
		return 0;
	}

	if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
		imap_msgpart_url_set_decode_to_binary(client->url);
	if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0) {
		if (imap_msgpart_url_get_bodypartstructure(client->url,
							   bpstruct_r,
							   &error) <= 0) {
			if (ret < 0)
				return -1;
			*errormsg_r = t_strdup_printf(
				"Failed to read URLAUTH \"%s\": %s", url, error);
			if (client->debug)
				i_debug("%s", *errormsg_r);
			return 0;
		}
	}

	/* if requested, read the message part the URL points to */
	if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0 ||
	    (url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0) {
		if (imap_msgpart_url_read_part(client->url, &mpresult, &error) <= 0) {
			if (ret < 0)
				return -1;
			*errormsg_r = t_strdup_printf(
				"Failed to read URLAUTH \"%s\": %s", url, error);
			if (client->debug)
				i_debug("%s", *errormsg_r);
			return 0;
		}
		client->msg_part_size = mpresult.size;
		client->msg_part_input = mpresult.input;
		*binary_with_nuls_r = mpresult.binary_decoded_input_has_nuls;
	}
	return 1;
}
Beispiel #3
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;
}