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); } }
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; }
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; }