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; }
static int cydir_mail_get_stream(struct mail *_mail, struct message_size *hdr_size, struct message_size *body_size, struct istream **stream_r) { struct index_mail *mail = (struct index_mail *)_mail; const char *path; int fd; if (mail->data.stream == NULL) { mail->mail.stats_open_lookup_count++; path = cydir_mail_get_path(_mail); fd = open(path, O_RDONLY); if (fd == -1) { if (errno == ENOENT) mail_set_expunged(_mail); else { mail_storage_set_critical(_mail->box->storage, "open(%s) failed: %m", path); } return -1; } mail->data.stream = i_stream_create_fd(fd, 0, TRUE); i_stream_set_name(mail->data.stream, path); index_mail_set_read_buffer_size(_mail, mail->data.stream); if (mail->mail.v.istream_opened != NULL) { if (mail->mail.v.istream_opened(_mail, stream_r) < 0) return -1; } } return index_mail_init_stream(mail, hdr_size, body_size, stream_r); }
static int zlib_mailbox_open_input(struct mailbox *box) { const struct compression_handler *handler; struct istream *input; struct stat st; int fd; handler = compression_lookup_handler_from_ext(box->name); if (handler == NULL || handler->create_istream == NULL) return 0; if (mail_storage_is_mailbox_file(box->storage)) { /* looks like a compressed single file mailbox. we should be able to handle this. */ const char *box_path = mailbox_get_path(box); fd = open(box_path, O_RDONLY); if (fd == -1) { /* let the standard handler figure out what to do with the failure */ return 0; } if (fstat(fd, &st) == 0 && S_ISDIR(st.st_mode)) { i_close_fd(&fd); return 0; } input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); i_stream_set_name(input, box_path); box->input = handler->create_istream(input, TRUE); i_stream_unref(&input); box->flags |= MAILBOX_FLAG_READONLY; } return 0; }
static void connection_init_streams(struct connection *conn) { const struct connection_settings *set = &conn->list->set; i_assert(conn->io == NULL); i_assert(conn->input == NULL); i_assert(conn->output == NULL); i_assert(conn->to == NULL); conn->version_received = set->major_version == 0; if (set->input_max_size != 0) { conn->input = i_stream_create_fd(conn->fd_in, set->input_max_size, FALSE); i_stream_set_name(conn->input, conn->name); } if (set->output_max_size != 0) { conn->output = o_stream_create_fd(conn->fd_out, set->output_max_size, FALSE); o_stream_set_no_error_handling(conn->output, TRUE); o_stream_set_name(conn->output, conn->name); } conn->io = io_add(conn->fd_in, IO_READ, *conn->list->v.input, conn); if (set->input_idle_timeout_secs != 0) { conn->to = timeout_add(set->input_idle_timeout_secs*1000, connection_idle_timeout, conn); } if (set->major_version != 0 && !set->dont_send_version) { o_stream_nsend_str(conn->output, t_strdup_printf( "VERSION\t%s\t%u\t%u\n", set->service_name_out, set->major_version, set->minor_version)); } }
struct istream *tee_i_stream_create_child(struct tee_istream *tee) { struct tee_child_istream *tstream; struct istream *ret, *input = tee->input; tstream = i_new(struct tee_child_istream, 1); tstream->tee = tee; tstream->istream.max_buffer_size = input->real_stream->max_buffer_size; tstream->istream.iostream.close = i_stream_tee_close; tstream->istream.iostream.destroy = i_stream_tee_destroy; tstream->istream.iostream.set_max_buffer_size = i_stream_tee_set_max_buffer_size; tstream->istream.read = i_stream_tee_read; tstream->istream.stat = i_stream_tee_stat; tstream->istream.sync = i_stream_tee_sync; tstream->next = tee->children; tee->children = tstream; ret = i_stream_create(&tstream->istream, input, i_stream_get_fd(input)); i_stream_set_name(&tstream->istream.istream, i_stream_get_name(input)); /* we keep the reference in tee stream, no need for extra references */ i_stream_unref(&input); return ret; }
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; }
void connection_init_from_streams(struct connection_list *list, struct connection *conn, const char *name, struct istream *input, struct ostream *output) { i_assert(name != NULL); conn->list = list; conn->name = i_strdup(name); conn->fd_in = i_stream_get_fd(input); conn->fd_out = o_stream_get_fd(output); i_assert(conn->fd_in >= 0); i_assert(conn->fd_out >= 0); i_assert(conn->io == NULL); i_assert(conn->input == NULL); i_assert(conn->output == NULL); i_assert(conn->to == NULL); conn->input = input; i_stream_ref(conn->input); i_stream_set_name(conn->input, conn->name); conn->output = output; o_stream_ref(conn->output); o_stream_set_no_error_handling(conn->output, TRUE); o_stream_set_name(conn->output, conn->name); conn->io = io_add_istream(conn->input, *list->v.input, conn); DLLIST_PREPEND(&list->connections, conn); list->connections_count++; if (list->v.client_connected != NULL) list->v.client_connected(conn, TRUE); }
struct istream *i_stream_create_file(const char *path, size_t max_buffer_size) { struct istream *input; input = i_stream_create_file_common(-1, path, max_buffer_size, TRUE); i_stream_set_name(input, path); return input; }
static int copy_to_temp_file(struct seekable_istream *sstream) { struct istream_private *stream = &sstream->istream; const char *path; const unsigned char *buffer; size_t size; int fd; fd = sstream->fd_callback(&path, sstream->context); if (fd == -1) return -1; /* copy our currently read buffer to it */ i_assert(stream->pos <= sstream->buffer_peak); if (write_full(fd, stream->buffer, sstream->buffer_peak) < 0) { if (!ENOSPACE(errno)) i_error("istream-seekable: write_full(%s) failed: %m", path); i_close_fd(&fd); return -1; } sstream->temp_path = i_strdup(path); sstream->write_peak = sstream->buffer_peak; sstream->fd = fd; sstream->fd_input = i_stream_create_fd_autoclose(&fd, I_MAX(stream->pos, sstream->istream.max_buffer_size)); i_stream_set_name(sstream->fd_input, t_strdup_printf( "(seekable temp-istream for: %s)", i_stream_get_name(&stream->istream))); /* read back the data we just had in our buffer */ for (;;) { buffer = i_stream_get_data(sstream->fd_input, &size); if (size >= stream->pos) break; ssize_t ret; if ((ret = i_stream_read_memarea(sstream->fd_input)) <= 0) { i_assert(ret != 0); i_assert(ret != -2); i_error("istream-seekable: Couldn't read back " "in-memory input %s: %s", i_stream_get_name(&stream->istream), i_stream_get_error(sstream->fd_input)); i_stream_destroy(&sstream->fd_input); i_close_fd(&sstream->fd); return -1; } } /* Set the max buffer size only after we've already read everything into memory. For example with istream-data it's possible that more data exists in buffer than max_buffer_size. */ i_stream_set_max_buffer_size(sstream->fd_input, sstream->istream.max_buffer_size); stream->buffer = buffer; i_stream_free_buffer(&sstream->istream); return 0; }
static int cmd_setmetadata_entry(struct imap_setmetadata_context *ctx, const char *entry_name, const struct imap_arg *entry_value) { struct istream *inputs[2]; struct mail_attribute_value value; string_t *path; int ret; switch (entry_value->type) { case IMAP_ARG_NIL: case IMAP_ARG_ATOM: case IMAP_ARG_STRING: /* we have the value already */ if (ctx->failed) return 1; memset(&value, 0, sizeof(value)); value.value = imap_arg_as_nstring(entry_value); ret = imap_metadata_set(ctx->trans, entry_name, &value); if (ret < 0) { /* delay reporting the failure so we'll finish reading the command input */ ctx->storage_failure = TRUE; ctx->failed = TRUE; } return 1; case IMAP_ARG_LITERAL_SIZE: o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6); o_stream_nflush(ctx->cmd->client->output); o_stream_uncork(ctx->cmd->client->output); o_stream_cork(ctx->cmd->client->output); /* fall through */ case IMAP_ARG_LITERAL_SIZE_NONSYNC: i_free(ctx->entry_name); ctx->entry_name = i_strdup(entry_name); ctx->entry_value_len = imap_arg_as_literal_size(entry_value); inputs[0] = i_stream_create_limit(ctx->cmd->client->input, ctx->entry_value_len); inputs[1] = NULL; path = t_str_new(128); mail_user_set_get_temp_prefix(path, ctx->cmd->client->user->set); ctx->input = i_stream_create_seekable_path(inputs, METADATA_MAX_INMEM_SIZE, str_c(path)); i_stream_set_name(ctx->input, i_stream_get_name(inputs[0])); i_stream_unref(&inputs[0]); return cmd_setmetadata_entry_read_stream(ctx); case IMAP_ARG_LITERAL: case IMAP_ARG_LIST: case IMAP_ARG_EOL: break; } i_unreached(); }
struct istream *i_stream_create_file(const char *path, size_t max_buffer_size) { struct file_istream *fstream; struct istream *input; fstream = i_new(struct file_istream, 1); input = i_stream_create_file_common(fstream, -1, path, max_buffer_size, TRUE); i_stream_set_name(input, path); return input; }
static int pop3c_mail_get_stream(struct mail *_mail, bool get_body, struct message_size *hdr_size, struct message_size *body_size, struct istream **stream_r) { struct index_mail *mail = (struct index_mail *)_mail; struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box; enum pop3c_capability capa; const char *name, *cmd, *error; struct istream *input; if (get_body && mail->data.stream != NULL) { name = i_stream_get_name(mail->data.stream); if (strncmp(name, "RETR", 4) == 0) { /* we've fetched the body */ } else if (strncmp(name, "TOP", 3) == 0) { /* we've fetched the header, but we need the body now too */ index_mail_close_streams(mail); } else { i_panic("Unexpected POP3 stream name: %s", name); } } if (mail->data.stream == NULL) { capa = pop3c_client_get_capabilities(mbox->client); if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) { cmd = t_strdup_printf("RETR %u\r\n", _mail->seq); get_body = TRUE; } else { cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq); } if (pop3c_client_cmd_stream(mbox->client, cmd, &input, &error) < 0) { mail_storage_set_error(mbox->box.storage, !pop3c_client_is_connected(mbox->client) ? MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error); return -1; } mail->data.stream = input; if (mail->mail.v.istream_opened != NULL) { if (mail->mail.v.istream_opened(_mail, &mail->data.stream) < 0) { index_mail_close_streams(mail); return -1; } } i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r')); if (get_body) pop3c_mail_cache_size(mail); } return index_mail_init_stream(mail, hdr_size, body_size, stream_r); }
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; }
struct istream *i_stream_create_error(int stream_errno) { struct istream_private *stream; stream = i_new(struct istream_private, 1); stream->istream.closed = TRUE; stream->istream.readable_fd = FALSE; stream->istream.blocking = TRUE; stream->istream.seekable = TRUE; stream->istream.eof = TRUE; stream->istream.stream_errno = stream_errno; i_stream_create(stream, NULL, -1); i_stream_set_name(&stream->istream, "(error)"); return &stream->istream; }
static int copy_to_temp_file(struct seekable_istream *sstream) { struct istream_private *stream = &sstream->istream; const char *path; const unsigned char *buffer; size_t size; int fd; fd = sstream->fd_callback(&path, sstream->context); if (fd == -1) return -1; /* copy our currently read buffer to it */ if (write_full(fd, sstream->membuf->data, sstream->membuf->used) < 0) { if (!ENOSPACE(errno)) i_error("istream-seekable: write_full(%s) failed: %m", path); i_close_fd(&fd); return -1; } sstream->temp_path = i_strdup(path); sstream->write_peak = sstream->membuf->used; sstream->fd = fd; sstream->fd_input = i_stream_create_fd_autoclose(&fd, sstream->istream.max_buffer_size); i_stream_set_name(sstream->fd_input, t_strdup_printf( "(seekable temp-istream for: %s)", i_stream_get_name(&stream->istream))); /* read back the data we just had in our buffer */ i_stream_seek(sstream->fd_input, stream->istream.v_offset); for (;;) { buffer = i_stream_get_data(sstream->fd_input, &size); if (size >= stream->pos) break; if (i_stream_read(sstream->fd_input) <= 0) { i_error("istream-seekable: Couldn't read back " "in-memory input %s", i_stream_get_name(&stream->istream)); i_stream_destroy(&sstream->fd_input); return -1; } } stream->buffer = buffer; stream->pos = size; buffer_free(&sstream->membuf); return 0; }
static struct istream * i_stream_create_file_common(int fd, const char *path, size_t max_buffer_size, bool autoclose_fd) { struct file_istream *fstream; struct istream *input; struct stat st; bool is_file; fstream = i_new(struct file_istream, 1); fstream->autoclose_fd = autoclose_fd; fstream->istream.iostream.close = i_stream_file_close; fstream->istream.max_buffer_size = max_buffer_size; fstream->istream.read = i_stream_file_read; fstream->istream.seek = i_stream_file_seek; fstream->istream.sync = i_stream_file_sync; fstream->istream.stat = i_stream_file_stat; /* if it's a file, set the flags properly */ if (fd == -1) is_file = TRUE; else if (fstat(fd, &st) < 0) is_file = FALSE; else if (S_ISREG(st.st_mode)) is_file = TRUE; else if (!S_ISDIR(st.st_mode)) is_file = FALSE; else { /* we're trying to open a directory. we're not designed for it. */ io_stream_set_error(&fstream->istream.iostream, "%s is a directory, can't read it as file", path != NULL ? path : t_strdup_printf("<fd %d>", fd)); fstream->istream.istream.stream_errno = EISDIR; is_file = FALSE; } if (is_file) { fstream->file = TRUE; fstream->istream.istream.blocking = TRUE; fstream->istream.istream.seekable = TRUE; } fstream->istream.istream.readable_fd = TRUE; input = i_stream_create(&fstream->istream, NULL, fd); i_stream_set_name(input, is_file ? "(file)" : "(fd)"); return input; }
static struct istream * maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail, bool *deleted_r) { struct istream *input; const char *path; struct maildir_open_context ctx; *deleted_r = FALSE; ctx.fd = -1; ctx.path = NULL; mail->transaction->stats.open_lookup_count++; if (!mail->saving) { if (maildir_file_do(mbox, mail->uid, do_open, &ctx) < 0) return NULL; } else { path = maildir_save_file_get_path(mail->transaction, mail->seq); if (do_open(mbox, path, &ctx) <= 0) return NULL; } if (ctx.fd == -1) { *deleted_r = TRUE; return NULL; } input = i_stream_create_fd_autoclose(&ctx.fd, 0); if (input->stream_errno == EISDIR) { i_stream_destroy(&input); if (maildir_lose_unexpected_dir(&mbox->storage->storage, ctx.path) >= 0) *deleted_r = TRUE; } else { i_stream_set_name(input, ctx.path); index_mail_set_read_buffer_size(mail, input); } i_free(ctx.path); return input; }
struct client_connection * client_connection_create(int fd, int listen_fd, bool ssl) { struct client_connection *conn; const char *ip; pool_t pool; pool = pool_alloconly_create("doveadm client", 1024*16); conn = p_new(pool, struct client_connection, 1); conn->pool = pool; conn->fd = fd; conn->io = io_add(fd, IO_READ, client_connection_input, conn); conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); o_stream_set_no_error_handling(conn->output, TRUE); (void)net_getsockname(fd, &conn->local_ip, &conn->local_port); (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port); i_stream_set_name(conn->input, net_ip2addr(&conn->remote_ip)); o_stream_set_name(conn->output, net_ip2addr(&conn->remote_ip)); ip = net_ip2addr(&conn->remote_ip); if (ip[0] != '\0') i_set_failure_prefix("doveadm(%s): ", ip); if (client_connection_read_settings(conn) < 0) { client_connection_destroy(&conn); return NULL; } if (ssl) { if (client_connection_init_ssl(conn) < 0) { client_connection_destroy(&conn); return NULL; } } client_connection_send_auth_handshake(conn, listen_fd); return conn; }
static void cmd_dump_dbox(int argc ATTR_UNUSED, char *argv[]) { struct istream *input; int fd; unsigned int hdr_size; bool ret; fd = open(argv[1], O_RDONLY); if (fd < 0) i_fatal("open(%s) failed: %m", argv[1]); input = i_stream_create_fd_autoclose(&fd, (size_t)-1); i_stream_set_name(input, argv[1]); hdr_size = dump_file_hdr(input); do { printf("\n"); T_BEGIN { ret = dump_msg(input, hdr_size); } T_END; } while (ret); i_stream_destroy(&input); }
static int cydir_mail_get_stream(struct mail *_mail, bool get_body ATTR_UNUSED, struct message_size *hdr_size, struct message_size *body_size, struct istream **stream_r) { struct index_mail *mail = (struct index_mail *)_mail; struct istream *input; const char *path; int fd; if (mail->data.stream == NULL) { _mail->transaction->stats.open_lookup_count++; path = cydir_mail_get_path(_mail); fd = open(path, O_RDONLY); if (fd == -1) { if (errno == ENOENT) mail_set_expunged(_mail); else { mail_storage_set_critical(_mail->box->storage, "open(%s) failed: %m", path); } return -1; } input = i_stream_create_fd(fd, 0, TRUE); i_stream_set_name(input, path); index_mail_set_read_buffer_size(_mail, input); if (mail->mail.v.istream_opened != NULL) { if (mail->mail.v.istream_opened(_mail, &input) < 0) { i_stream_unref(&input); return -1; } } mail->data.stream = input; } return index_mail_init_stream(mail, hdr_size, body_size, stream_r); }
struct istream * i_stream_create_fs_file(struct fs_file **file, size_t max_buffer_size) { struct fs_file_istream *fstream; struct istream *input; fstream = i_new(struct fs_file_istream, 1); fstream->file = *file; fstream->istream.iostream.close = i_stream_fs_file_close; fstream->istream.max_buffer_size = max_buffer_size; fstream->istream.read = i_stream_fs_file_read; fstream->istream.stream_size_passthrough = TRUE; fstream->istream.istream.blocking = ((*file)->flags & FS_OPEN_FLAG_ASYNC) == 0; fstream->istream.istream.seekable = ((*file)->flags & FS_OPEN_FLAG_SEEKABLE) != 0; input = i_stream_create(&fstream->istream, NULL, -1); i_stream_set_name(input, fs_file_path(*file)); *file = NULL; return input; }
int server_connection_create(struct doveadm_server *server, struct server_connection **conn_r) { #define DOVEADM_SERVER_HANDSHAKE "VERSION\tdoveadm-server\t1\t0\n" struct server_connection *conn; pool_t pool; pool = pool_alloconly_create("doveadm server connection", 1024*16); conn = p_new(pool, struct server_connection, 1); conn->pool = pool; conn->server = server; conn->fd = doveadm_connect_with_default_port(server->name, doveadm_settings->doveadm_port); net_set_nonblock(conn->fd, TRUE); conn->io = io_add(conn->fd, IO_READ, server_connection_input, conn); conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE); conn->output = o_stream_create_fd(conn->fd, (size_t)-1); o_stream_set_flush_callback(conn->output, server_connection_output, conn); i_stream_set_name(conn->input, server->name); o_stream_set_name(conn->output, server->name); array_append(&conn->server->connections, &conn, 1); if (server_connection_read_settings(conn) < 0 || server_connection_init_ssl(conn) < 0) { server_connection_destroy(&conn); return -1; } o_stream_set_no_error_handling(conn->output, TRUE); conn->state = SERVER_REPLY_STATE_DONE; o_stream_nsend_str(conn->output, DOVEADM_SERVER_HANDSHAKE); *conn_r = conn; return 0; }
static int openssl_iostream_create(struct ssl_iostream_context *ctx, const char *source, const struct ssl_iostream_settings *set, struct istream **input, struct ostream **output, struct ssl_iostream **iostream_r) { struct ssl_iostream *ssl_io; SSL *ssl; BIO *bio_int, *bio_ext; int ret; ssl = SSL_new(ctx->ssl_ctx); if (ssl == NULL) { i_error("SSL_new() failed: %s", openssl_iostream_error()); return -1; } /* BIO pairs use default buffer sizes (17 kB in OpenSSL 0.9.8e). Each of the BIOs have one "write buffer". BIO_write() copies data to them, while BIO_read() reads from the other BIO's write buffer into the given buffer. The bio_int is used by OpenSSL and bio_ext is used by this library. */ if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) { i_error("BIO_new_bio_pair() failed: %s", openssl_iostream_error()); SSL_free(ssl); return -1; } ssl_io = i_new(struct ssl_iostream, 1); ssl_io->refcount = 1; ssl_io->ctx = ctx; ssl_io->ssl = ssl; ssl_io->bio_ext = bio_ext; ssl_io->plain_input = *input; ssl_io->plain_output = *output; ssl_io->source = i_strdup(source); /* bio_int will be freed by SSL_free() */ SSL_set_bio(ssl_io->ssl, bio_int, bio_int); SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io); T_BEGIN { ret = openssl_iostream_set(ssl_io, set); } T_END; if (ret < 0) { openssl_iostream_free(ssl_io); return -1; } o_stream_uncork(ssl_io->plain_output); *input = openssl_i_stream_create_ssl(ssl_io); *output = openssl_o_stream_create_ssl(ssl_io); i_stream_set_name(*input, t_strconcat("SSL ", i_stream_get_name(ssl_io->plain_input), NULL)); o_stream_set_name(*output, t_strconcat("SSL ", o_stream_get_name(ssl_io->plain_output), NULL)); if (ssl_io->plain_output->real_stream->error_handling_disabled) o_stream_set_no_error_handling(*output, TRUE); ssl_io->ssl_output = *output; *iostream_r = ssl_io; return 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; }
struct client *client_create(int fd_in, int fd_out, const char *session_id, struct mail_user *user, struct mail_storage_service_user *service_user, const struct imap_settings *set) { const struct mail_storage_settings *mail_set; struct client *client; const char *ident; pool_t pool; bool explicit_capability = FALSE; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); net_set_nonblock(fd_out, TRUE); pool = pool_alloconly_create("imap client", 2048); client = p_new(pool, struct client, 1); client->pool = pool; client->v = imap_client_vfuncs; client->set = set; client->service_user = service_user; client->session_id = p_strdup(pool, session_id); client->fd_in = fd_in; client->fd_out = fd_out; client->input = i_stream_create_fd(fd_in, set->imap_max_line_length, FALSE); client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE); o_stream_set_no_error_handling(client->output, TRUE); i_stream_set_name(client->input, "<imap client>"); o_stream_set_name(client->output, "<imap client>"); o_stream_set_flush_callback(client->output, client_output, client); p_array_init(&client->module_contexts, client->pool, 5); client->io = io_add_istream(client->input, client_input, client); client->last_input = ioloop_time; client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, client_idle_timeout, client); client->command_pool = pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2); client->user = user; client->notify_count_changes = TRUE; client->notify_flag_changes = TRUE; mail_namespaces_set_storage_callbacks(user->namespaces, &mail_storage_callbacks, client); client->capability_string = str_new(client->pool, sizeof(CAPABILITY_STRING)+64); if (*set->imap_capability == '\0') str_append(client->capability_string, CAPABILITY_STRING); else if (*set->imap_capability != '+') { explicit_capability = TRUE; str_append(client->capability_string, set->imap_capability); } else { str_append(client->capability_string, CAPABILITY_STRING); str_append_c(client->capability_string, ' '); str_append(client->capability_string, set->imap_capability + 1); } if (user->fuzzy_search && !explicit_capability) { /* Enable FUZZY capability only when it actually has a chance of working */ str_append(client->capability_string, " SEARCH=FUZZY"); } mail_set = mail_user_set_get_storage_set(user); if (mail_set->mailbox_list_index && !explicit_capability) { /* NOTIFY is enabled only when mailbox list indexes are enabled, although even that doesn't necessarily guarantee it always */ str_append(client->capability_string, " NOTIFY"); } if (*set->imap_urlauth_host != '\0' && *mail_set->mail_attribute_dict != '\0') { /* Enable URLAUTH capability only when dict is configured correctly */ client_init_urlauth(client); if (!explicit_capability) str_append(client->capability_string, " URLAUTH URLAUTH=BINARY"); } if (set->imap_metadata && *mail_set->mail_attribute_dict != '\0') { client->imap_metadata_enabled = TRUE; if (!explicit_capability) str_append(client->capability_string, " METADATA"); } if (!explicit_capability && user_has_special_use_mailboxes(user)) { /* Advertise SPECIAL-USE only if there are actually some SPECIAL-USE flags in mailbox configuration. */ str_append(client->capability_string, " SPECIAL-USE"); } ident = mail_user_get_anvil_userip_ident(client->user); if (ident != NULL) { master_service_anvil_send(master_service, t_strconcat( "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL)); client->anvil_sent = TRUE; } imap_client_count++; DLLIST_PREPEND(&imap_clients, client); if (hook_client_created != NULL) hook_client_created(&client); imap_refresh_proctitle(); return client; }
static int cmd_filter_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { const struct sieve_extension *this_ext = renv->oprtn->ext; unsigned int is_test = 0; struct sieve_stringlist *args_list = NULL; enum sieve_error error = SIEVE_ERROR_NONE; string_t *pname = NULL; const char *program_name = NULL; const char *const *args = NULL; struct istream *newmsg = NULL; struct sieve_extprogram *sprog; 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 */ if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, NULL) != 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, "filter 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, "filter", program_name, args, &error); if ( sprog != NULL ) { 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, "filter action: failed to read input message"); } sieve_extprogram_set_output_seekable(sprog); ret = sieve_extprogram_run(sprog); } else { ret = -1; } if ( ret > 0 ) newmsg = sieve_extprogram_get_output_seekable(sprog); if ( sprog != NULL ) sieve_extprogram_destroy(&sprog); if ( ret > 0 && newmsg != NULL ) { sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "executed program successfully"); i_stream_set_name(newmsg, t_strdup_printf("filter %s output", program_name)); newmsg->blocking = TRUE; if ( (ret=sieve_message_substitute(renv->msgctx, newmsg)) >= 0 ) { sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "changed message"); } else { sieve_runtime_critical(renv, NULL, "filter action", "filter action: failed to substitute message"); } i_stream_unref(&newmsg); } else if ( ret < 0 ) { if ( error == SIEVE_ERROR_NOT_FOUND ) { sieve_runtime_error(renv, NULL, "filter action: program `%s' not found", str_sanitize(program_name, 80)); } else { sieve_extprogram_exec_error(renv->ehandler, sieve_runtime_get_full_command_location(renv), "filter action: failed to execute to program `%s'", str_sanitize(program_name, 80)); } } else { sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action: program indicated false result"); } if ( is_test > 0 ) { sieve_interpreter_set_test_result(renv->interp, ( ret > 0 )); return SIEVE_EXEC_OK; } return ( ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE ); }