static int fetch_binary_size(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { string_t *str; uoff_t size; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_size(mail, body->msgpart, &size) < 0) { if (mailbox_get_last_mail_error(mail->box) != MAIL_ERROR_INVALIDDATA) return -1; /* tried to do BINARY.SIZE fetch for a MIME part with broken content */ size = 0; } str = t_str_new(128); if (ctx->state.cur_first) ctx->state.cur_first = FALSE; else str_append_c(str, ' '); str_printfa(str, "%s %"PRIuUOFF_T, get_body_name(body), size); if (o_stream_send(ctx->client->output, str_data(str), str_len(str)) < 0) return -1; return 1; }
void http_client_request_remove_header(struct http_client_request *req, const char *key) { const unsigned char *data, *p; size_t size, line_len, line_start_pos; unsigned int key_len = strlen(key); i_assert(req->state == HTTP_REQUEST_STATE_NEW || /* allow calling for retries */ req->state == HTTP_REQUEST_STATE_GOT_RESPONSE || req->state == HTTP_REQUEST_STATE_ABORTED); data = str_data(req->headers); size = str_len(req->headers); while ((p = memchr(data, '\n', size)) != NULL) { line_len = (p+1) - data; if (size > key_len && i_memcasecmp(data, key, key_len) == 0 && data[key_len] == ':' && data[key_len+1] == ' ') { /* key was found from header, replace its value */ line_start_pos = str_len(req->headers) - size; str_delete(req->headers, line_start_pos, line_len); break; } size -= line_len; data += line_len; } }
static int fetch_body_msgpart(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { struct imap_msgpart_open_result result; string_t *str; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_open(mail, body->msgpart, &result) < 0) return -1; i_assert(result.input->v_offset == 0); ctx->state.cur_input = result.input; ctx->state.cur_size = result.size; ctx->state.cur_size_field = result.size_field; ctx->state.cur_human_name = get_body_human_name(ctx->ctx_pool, body); fetch_state_update_stats(ctx, body->msgpart); str = get_prefix(&ctx->state, body, ctx->state.cur_size, result.binary_decoded_input_has_nuls); o_stream_nsend(ctx->client->output, str_data(str), str_len(str)); ctx->state.cont_handler = fetch_stream_continue; return ctx->state.cont_handler(ctx); }
static int fetch_data(struct imap_fetch_context *ctx, const struct imap_fetch_body_data *body, const struct message_size *size) { string_t *str; ctx->cur_name = p_strconcat(ctx->cmd->pool, "[", body->section, "]", NULL); ctx->cur_size = get_send_size(body, size->virtual_size); str = get_prefix(ctx, body, ctx->cur_size); if (o_stream_send(ctx->client->output, str_data(str), str_len(str)) < 0) return -1; if (!ctx->update_partial) { if (message_skip_virtual(ctx->cur_input, body->skip, NULL, FALSE, &ctx->skip_cr) < 0) { fetch_read_error(ctx); return -1; } } else { if (seek_partial(ctx->select_counter, ctx->cur_mail->uid, &last_partial, ctx->cur_input, body->skip, &ctx->skip_cr) < 0) { fetch_read_error(ctx); return -1; } } return fetch_stream(ctx, size); }
static bool cmd_getquotaroot(struct client_command_context *cmd) { struct client *client = cmd->client; struct quota_user *quser = QUOTA_USER_CONTEXT(client->user); struct mail_namespace *ns; struct mailbox *box; struct quota_root_iter *iter; struct quota_root *root; const char *mailbox, *storage_name, *name; string_t *quotaroot_reply, *quota_reply; /* <mailbox> */ if (!client_read_string_args(cmd, 1, &mailbox)) return FALSE; ns = client_find_namespace(cmd, mailbox, &storage_name, NULL); if (ns == NULL) return TRUE; if (quser == NULL) { client_send_tagline(cmd, "OK No quota."); return TRUE; } if (ns->owner != NULL && ns->owner != client->user && !client->user->admin) { client_send_tagline(cmd, "NO Not showing other users' quota."); return TRUE; } box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT); /* build QUOTAROOT reply and QUOTA reply for all quota roots */ quotaroot_reply = t_str_new(128); quota_reply = t_str_new(256); str_append(quotaroot_reply, "* QUOTAROOT "); imap_quote_append_string(quotaroot_reply, mailbox, FALSE); iter = quota_root_iter_init(box); while ((root = quota_root_iter_next(iter)) != NULL) { str_append_c(quotaroot_reply, ' '); name = imap_quota_root_get_name(client->user, ns->owner, root); imap_quote_append_string(quotaroot_reply, name, FALSE); quota_reply_write(quota_reply, client->user, ns->owner, root); } quota_root_iter_deinit(&iter); mailbox_free(&box); /* send replies */ if (str_len(quota_reply) == 0) client_send_tagline(cmd, "OK No quota."); else { client_send_line(client, str_c(quotaroot_reply)); o_stream_send(client->output, str_data(quota_reply), str_len(quota_reply)); client_send_tagline(cmd, "OK Getquotaroot completed."); } return TRUE; }
static int fetch_binary_size(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { string_t *str; uoff_t size; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_size(mail, body->msgpart, &size) < 0) return -1; str = t_str_new(128); if (ctx->state.cur_first) ctx->state.cur_first = FALSE; else str_append_c(str, ' '); str_printfa(str, "%s %"PRIuUOFF_T, get_body_name(body), size); if (o_stream_send(ctx->client->output, str_data(str), str_len(str)) < 0) return -1; return 1; }
static void auth_worker_send_reply(struct auth_worker_client *client, string_t *str) { if (shutdown_request) o_stream_send_str(client->output, "SHUTDOWN\n"); o_stream_send(client->output, str_data(str), str_len(str)); }
static void list_iter_callback(const char *user, void *context) { struct auth_worker_list_context *ctx = context; string_t *str; if (user == NULL) { if (ctx->sending) ctx->done = TRUE; else list_iter_deinit(ctx); return; } T_BEGIN { str = t_str_new(128); str_printfa(str, "%u\t*\t%s\n", ctx->id, user); o_stream_send(ctx->client->output, str_data(str), str_len(str)); } T_END; if (ctx->sending) { /* avoid recursively looping to this same function */ ctx->sent = TRUE; return; } do { ctx->sending = TRUE; ctx->sent = FALSE; ctx->userdb->iface->iterate_next(ctx->iter); } while (ctx->sent && o_stream_get_buffer_used_size(ctx->client->output) == 0); ctx->sending = FALSE; if (ctx->done) list_iter_deinit(ctx); }
static void script_execute_finish(void) { const char *keys_str, *username, *const *keys, *value; string_t *reply = t_str_new(512); ssize_t ret; keys_str = getenv(ENV_USERDB_KEYS); if (keys_str == NULL) i_fatal(ENV_USERDB_KEYS" environment missing"); username = getenv("USER"); if (username == NULL) i_fatal("USER environment missing"); str_append(reply, username); for (keys = t_strsplit_spaces(keys_str, " "); *keys != NULL; keys++) { value = getenv(t_str_ucase(*keys)); if (value != NULL) { str_append_c(reply, '\t'); str_tabescape_write(reply, t_strconcat(t_str_lcase(*keys), "=", value, NULL)); } } str_append_c(reply, '\n'); ret = fd_send(SCRIPT_COMM_FD, STDOUT_FILENO, str_data(reply), str_len(reply)); if (ret < 0) i_fatal("fd_send() failed: %m"); else if (ret != (ssize_t)str_len(reply)) i_fatal("fd_send() sent partial output"); }
void worker_connection_request(struct worker_connection *conn, const struct indexer_request *request, void *context) { i_assert(worker_connection_is_connected(conn)); i_assert(context != NULL); i_assert(request->index || request->optimize); if (conn->request_username == NULL) conn->request_username = i_strdup(request->username); else { i_assert(strcmp(conn->request_username, request->username) == 0); } aqueue_append(conn->request_queue, &context); T_BEGIN { string_t *str = t_str_new(128); str_append_tabescaped(str, request->username); str_append_c(str, '\t'); str_append_tabescaped(str, request->mailbox); str_append_c(str, '\t'); if (request->session_id != NULL) str_append_tabescaped(str, request->session_id); str_printfa(str, "\t%u\t", request->max_recent_msgs); if (request->index) str_append_c(str, 'i'); if (request->optimize) str_append_c(str, 'o'); str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); } T_END; }
static void test_str_insert(void) { string_t *str = t_str_new(32); test_begin("str_insert()"); str_insert(str, 0, "foo"); str_insert(str, 3, ">"); str_insert(str, 3, "bar"); str_insert(str, 0, "<"); test_assert(str->used == 8 && memcmp(str_data(str), "<foobar>", 8) == 0); str_insert(str, 10, "!"); test_assert(str->used == 11 && memcmp(str_data(str), "<foobar>\0\0!", 11) == 0); test_end(); }
static bool lmtp_client_send_xclient(struct lmtp_client *client) { string_t *str; unsigned int empty_len; if (client->xclient_args == NULL) { /* not supported */ return FALSE; } if (client->xclient_sent) return FALSE; str = t_str_new(64); str_append(str, "XCLIENT"); empty_len = str_len(str); if (client->set.source_ip.family != 0 && str_array_icase_find(client->xclient_args, "ADDR")) str_printfa(str, " ADDR=%s", net_ip2addr(&client->set.source_ip)); if (client->set.source_port != 0 && str_array_icase_find(client->xclient_args, "PORT")) str_printfa(str, " PORT=%u", client->set.source_port); if (client->set.proxy_ttl != 0 && str_array_icase_find(client->xclient_args, "TTL")) str_printfa(str, " TTL=%u", client->set.proxy_ttl); if (client->set.proxy_timeout_secs != 0 && str_array_icase_find(client->xclient_args, "TIMEOUT")) str_printfa(str, " TIMEOUT=%u", client->set.proxy_timeout_secs); if (str_len(str) == empty_len) return FALSE; str_append(str, "\r\n"); o_stream_nsend(client->output, str_data(str), str_len(str)); return TRUE; }
static void test_rfc822_parse_comment_nuls(void) { const unsigned char input[] = "(\000a\000\000b\\\000c(\000d)\000)"; const char output[] = "!a!!b\\!c(!d)!"; struct rfc822_parser_context parser; string_t *str = t_str_new(64); test_begin("rfc822 parse comment with NULs"); rfc822_parser_init(&parser, input, sizeof(input)-1, str); test_assert(rfc822_skip_comment(&parser) == 0); /* should be same as input, except the outer () removed */ test_assert(str_len(str) == sizeof(input)-1-2 && memcmp(input+1, str_data(str), str_len(str)) == 0); rfc822_parser_deinit(&parser); str_truncate(str, 0); rfc822_parser_init(&parser, input, sizeof(input)-1, str); parser.nul_replacement_str = "!"; test_assert(rfc822_skip_comment(&parser) == 0); test_assert(strcmp(str_c(str), output) == 0); rfc822_parser_deinit(&parser); test_end(); }
static int client_input_status(struct doveadm_connection *client, const char *const *args) { struct replicator_queue *queue = replicator_brain_get_queue(client->brain); struct replicator_queue_iter *iter; struct replicator_user *user; const char *mask = args[0]; string_t *str = t_str_new(128); if (mask == NULL) return client_input_status_overview(client); iter = replicator_queue_iter_init(queue); while ((user = replicator_queue_iter_next(iter)) != NULL) { if (!wildcard_match(user->username, mask)) continue; str_truncate(str, 0); str_append_tabescaped(str, user->username); str_append_c(str, '\t'); str_append(str, replicator_priority_to_str(user->priority)); str_printfa(str, "\t%lld\t%lld\t%d\t%lld\n", (long long)user->last_fast_sync, (long long)user->last_full_sync, user->last_sync_failed ? 1 : 0, (long long)user->last_successful_sync); o_stream_send(client->conn.output, str_data(str), str_len(str)); } replicator_queue_iter_deinit(&iter); o_stream_send(client->conn.output, "\n", 1); return 0; }
bool mod_length_modify(string_t *in, string_t **result) { *result = t_str_new(64); str_printfa(*result, "%llu", (unsigned long long) uni_utf8_strlen_n(str_data(in), str_len(in))); return TRUE; }
static int proxy_input_banner(struct imap_client *client, struct ostream *output, const char *line) { const char *const *capabilities = NULL; string_t *str; int ret; if (!str_begins(line, "* OK ")) { client_log_err(&client->common, t_strdup_printf( "proxy: Remote returned invalid banner: %s", str_sanitize(line, 160))); return -1; } str = t_str_new(128); if (str_begins(line + 5, "[CAPABILITY ")) { capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " "); if (str_array_icase_find(capabilities, "SASL-IR")) client->proxy_sasl_ir = TRUE; if (str_array_icase_find(capabilities, "LOGINDISABLED")) client->proxy_logindisabled = TRUE; i_free(client->proxy_backend_capability); client->proxy_backend_capability = i_strdup(t_strcut(line + 5 + 12, ']')); if (str_array_icase_find(capabilities, "ID") && !client->common.proxy_not_trusted) { client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID; proxy_write_id(client, str); if (client->common.proxy_nopipelining) { /* write login or starttls after I OK */ o_stream_nsend(output, str_data(str), str_len(str)); return 0; } } } if ((ret = proxy_write_starttls(client, str)) < 0) { return -1; } else if (ret == 0) { if (proxy_write_login(client, str) < 0) return -1; } o_stream_nsend(output, str_data(str), str_len(str)); return 0; }
static int replication_notify_sync(struct mail_user *user) { struct replication_user *ruser = REPLICATION_USER_CONTEXT(user); string_t *str; char buf[1024]; int fd; ssize_t ret; fd = net_connect_unix(ruser->socket_path); if (fd == -1) { i_error("net_connect_unix(%s) failed: %m", ruser->socket_path); return -1; } net_set_nonblock(fd, FALSE); /* <username> \t "sync" */ str = t_str_new(256); str_append_tabescaped(str, user->username); str_append(str, "\tsync\n"); alarm(ruser->sync_secs); if (write_full(fd, str_data(str), str_len(str)) < 0) { i_error("write(%s) failed: %m", ruser->socket_path); ret = -1; } else { /* + | - */ ret = read(fd, buf, sizeof(buf)); if (ret < 0) { if (errno != EINTR) { i_error("read(%s) failed: %m", ruser->socket_path); } else { i_warning("replication(%s): Sync failure: " "Timeout in %u secs", user->username, ruser->sync_secs); } } else if (ret == 0) { i_error("read(%s) failed: EOF", ruser->socket_path); ret = -1; } else if (buf[0] == '+') { /* success */ ret = 0; } else if (buf[0] == '-') { /* failure */ if (buf[ret-1] == '\n') ret--; i_warning("replication(%s): Sync failure: %s", user->username, t_strndup(buf+1, ret-1)); ret = -1; } else { i_warning("replication(%s): " "Remote sent invalid input: %s", user->username, t_strndup(buf, ret)); } } alarm(0); if (close(fd) < 0) i_error("close(%s) failed: %m", ruser->socket_path); return ret; }
void error_env_not_defined(char *var) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "environment variable '%s' not defined", var ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void info_total_errors(void) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "%d errors occurred during assembly", get_num_errors() ); do_error( ErrInfo, str_data(msg) ); STR_DELETE(msg); }
void error_int_range(long value) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "integer '%ld' out of range", value ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void error_not_lib_file(char *filename) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "file '%s' not a library file", filename ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void warn_option_deprecated(char *option) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "option '%s' is deprecated", option ); do_error( ErrWarn, str_data(msg) ); STR_DELETE(msg); }
void error_include_recursion(char *filename) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "cannot include file '%s' recursively", filename ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void error_illegal_option(char *option) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "illegal option '%s'", option ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void error_no_src_file(void) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "source filename missing" ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void error_illegal_src_filename(char *filename) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "illegal source filename '%s'", filename ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
static void mbox_sync_header_remove_space(struct mbox_sync_mail_context *ctx, size_t start_pos, size_t *size) { const unsigned char *data; size_t data_size, pos, last_line_pos; /* find the end of the LWSP */ data = str_data(ctx->header); data_size = str_len(ctx->header); for (pos = last_line_pos = start_pos; pos < data_size; pos++) { if (data[pos] == '\n') { /* possibly continues in next line */ if (pos+1 == data_size || !IS_LWSP(data[pos+1])) { data_size = pos; break; } last_line_pos = pos+1; } else if (!IS_LWSP(data[pos]) && data[pos] != '\r') { start_pos = last_line_pos = pos+1; } } if (start_pos == data_size) return; /* and remove what we can */ if (ctx->header_first_change > start_pos) ctx->header_first_change = start_pos; ctx->header_last_change = (size_t)-1; if (data_size - start_pos <= *size) { /* remove it all */ mbox_sync_move_buffer(ctx, start_pos, 0, data_size - start_pos); *size -= data_size - start_pos; return; } /* we have more space than needed. since we're removing from the beginning of header instead of end, we don't have to worry about multiline-headers. */ mbox_sync_move_buffer(ctx, start_pos, 0, *size); if (last_line_pos <= start_pos + *size) last_line_pos = start_pos; else last_line_pos -= *size; data_size -= *size; *size = 0; if (ctx->mail.space < (off_t)(data_size - last_line_pos)) { ctx->mail.space = data_size - last_line_pos; ctx->mail.offset = ctx->hdr_offset; if (ctx->mail.space > 0) ctx->mail.offset += last_line_pos; } }
void warn_symbol_different(char *name, char *used) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "symbol '%s' used as '%s'", name, used ); do_error( ErrWarn, str_data(msg) ); STR_DELETE(msg); }
void error_syntax(void) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "syntax error" ); do_error( ErrError, str_data(msg) ); STR_DELETE(msg); }
void warn_deprecated(char *old_stmt, char *new_stmt) { STR_DEFINE(msg, STR_SIZE); str_append_sprintf( msg, "'%s' is deprecated, use '%s' instead", old_stmt, new_stmt ); do_error( ErrWarn, str_data(msg) ); STR_DELETE(msg); }