imap-client.c revision 1c02804cdc5f1ad830fec081100e951bc67204b4
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* If the last command took longer than this to run, log statistics on
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen where the time was spent. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#define IMAP_CLIENT_DISCONNECT_LOG_STATS_CMD_MIN_RUNNING_MSECS 1000
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenextern struct mail_storage_callbacks mail_storage_callbacks;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenextern struct imap_client_vfuncs imap_client_vfuncs;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct imap_module_register imap_module_register = { 0 };
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenunsigned int imap_client_count = 0;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenstatic const char *client_command_state_names[CLIENT_COMMAND_STATE_DONE+1] = {
c57776c06ec99ba9b0dafdbf9475ea72ea8ca134Timo Sirainen "wait-input",
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen "wait-output",
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen "wait-external",
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen "wait-unambiguity",
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainenstatic void client_idle_timeout(struct client *client)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen client_send_line(client, "* BYE Disconnected for inactivity.");
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen client_destroy(client, "Disconnected for inactivity");
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainenstatic void client_init_urlauth(struct client *client)
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen config.url_host = client->set->imap_urlauth_host;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen config.url_port = client->set->imap_urlauth_port;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen config.socket_path = t_strconcat(client->user->set->base_dir,
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen config.access_anonymous = client->user->anonymous;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen client->urlauth_ctx = imap_urlauth_init(client->user, &config);
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainenstatic bool user_has_special_use_mailboxes(struct mail_user *user)
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct client *client_create(int fd_in, int fd_out, const char *session_id,
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen struct mail_storage_service_user *service_user,
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen const char *ident;
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen /* always use nonblocking I/O */
e9e2d23e1ea5a149a7d8828d2a45b9f2313c3785Timo Sirainen pool = pool_alloconly_create("imap client", 2048);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen client->session_id = p_strdup(pool, session_id);
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen client->output = o_stream_create_fd(fd_out, (size_t)-1);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen o_stream_set_no_error_handling(client->output, TRUE);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_stream_set_name(client->input, "<imap client>");
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen o_stream_set_name(client->output, "<imap client>");
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen o_stream_set_flush_callback(client->output, client_output, client);
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen p_array_init(&client->module_contexts, client->pool, 5);
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen client->io = io_add_istream(client->input, client_input, client);
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
b7c2065b3f10f9ae27787a9db5aaefbfc70d4502Timo Sirainen pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2);
if (ident != NULL) {
return client;
bool cmd_ret;
i_unreached();
if (!cmd_ret) {
const char *error;
const char *wait_condition,
unsigned int msecs_in_ioloop;
if (buffered_size > 0)
const char *cond_str;
unsigned int msecs_since_cmd;
if (msecs_since_cmd > 0) {
T_BEGIN {
} T_END;
const char *msg)
switch (parse_error) {
case IMAP_PARSE_ERROR_NONE:
i_unreached();
int ret;
return TRUE;
return FALSE;
return FALSE;
unsigned int count, ...)
const char *str;
return FALSE;
for (i = 0; i < count; i++) {
return i == count;
static struct client_command_context *
return cmd;
return NULL;
return TRUE;
return TRUE;
return FALSE;
return TRUE;
return TRUE;
return FALSE;
if (broken_client) {
return TRUE;
return cmd;
static struct client_command_context *
return cmd;
unsigned int unfinished_count = 0;
i_unreached();
return TRUE;
return FALSE;
return FALSE;
return TRUE;
if (!ret)
const unsigned char *data;
for (i = 0; i < data_size; i++) {
return FALSE;
return TRUE;
return TRUE;
return TRUE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
T_BEGIN {
} T_END;
if (ret)
if (remove_io)
if (!handled_commands)
return FALSE;
return TRUE;
bool finished;
if (!finished)
int ret;
return ret;
return FALSE;
return TRUE;
int ret;
if (ret == 0) {
if (ret < 0) {
return ret;
struct imap_search_update *
unsigned int *idx_r)
unsigned int i, count;
return NULL;
for (i = 0; i < count; i++) {
*idx_r = i;
return &updates[i];
return NULL;
void clients_destroy_all(void)