cmd-select.c revision 115cf0320f679e4e63db25e7f44f47977b8338de
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "imap-common.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "seq-range-array.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "time-util.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "imap-commands.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-search-build.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "imap-search-args.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "imap-seqset.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "imap-fetch.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "imap-sync.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdlib.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenstruct imap_select_context {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct client_command_context *cmd;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct mail_namespace *ns;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct mailbox *box;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct timeval start_time;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct imap_fetch_context *fetch_ctx;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen uint32_t qresync_uid_validity;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen uint64_t qresync_modseq;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen ARRAY_TYPE(seq_range) qresync_known_uids;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen ARRAY_TYPE(uint32_t) qresync_sample_seqset;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen ARRAY_TYPE(uint32_t) qresync_sample_uidset;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen unsigned int condstore:1;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic int select_qresync_get_uids(struct imap_select_context *ctx,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const ARRAY_TYPE(seq_range) *seqset,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const ARRAY_TYPE(seq_range) *uidset)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct seq_range *uid_range;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct seq_range_iter seq_iter;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen unsigned int i, uid_count, diff, n = 0;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen uint32_t seq;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* change all n:m ranges to n,m and store the results */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen uid_range = array_get(uidset, &uid_count);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen seq_range_array_iter_init(&seq_iter, seqset);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_array_init(&ctx->qresync_sample_uidset, uid_count);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_array_init(&ctx->qresync_sample_seqset, uid_count);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen for (i = 0; i < uid_count; i++) {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (!seq_range_array_iter_nth(&seq_iter, n++, &seq))
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen return -1;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen array_append(&ctx->qresync_sample_uidset,
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen &uid_range[i].seq1, 1);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen array_append(&ctx->qresync_sample_seqset, &seq, 1);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen diff = uid_range[i].seq2 - uid_range[i].seq1;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (diff > 0) {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen n += diff - 1;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen if (!seq_range_array_iter_nth(&seq_iter, n++, &seq))
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen return -1;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen array_append(&ctx->qresync_sample_uidset,
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen &uid_range[i].seq2, 1);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen array_append(&ctx->qresync_sample_seqset, &seq, 1);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen }
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (seq_range_array_iter_nth(&seq_iter, n, &seq))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen return 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenselect_parse_qresync_known_set(struct imap_select_context *ctx,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const struct imap_arg *args)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ARRAY_TYPE(seq_range) seqset, uidset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *str;
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen t_array_init(&seqset, 32);
74066569545099304b20e790df7c261883d1746bTimo Sirainen if (!imap_arg_get_atom(args, &str) ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen imap_seq_set_nostar_parse(str, &seqset) < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_command_error(ctx->cmd,
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen "Invalid QRESYNC known-sequence-set");
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen return FALSE;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen }
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen args++;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen t_array_init(&uidset, 32);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!imap_arg_get_atom(args, &str) ||
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen imap_seq_set_nostar_parse(str, &uidset) < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_command_error(ctx->cmd,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Invalid QRESYNC known-uid-set");
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen return FALSE;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen }
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen args++;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen if (select_qresync_get_uids(ctx, &seqset, &uidset) < 0) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_send_command_error(ctx->cmd, "Invalid QRESYNC sets");
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return FALSE;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (!IMAP_ARG_IS_EOL(args)) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_send_command_error(ctx->cmd,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen "Too many parameters to QRESYNC known set");
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return FALSE;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return TRUE;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic bool
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenselect_parse_qresync(struct imap_select_context *ctx,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen const struct imap_arg *args)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen const struct imap_arg *list_args;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const char *str;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int count;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen if ((ctx->cmd->client->enabled_features &
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen MAILBOX_FEATURE_QRESYNC) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_command_error(ctx->cmd, "QRESYNC not enabled");
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen return FALSE;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!imap_arg_get_list_full(args, &args, &count)) {
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen client_send_command_error(ctx->cmd,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "QRESYNC parameters missing");
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen return FALSE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (!imap_arg_get_atom(&args[0], &str) ||
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen str_to_uint32(str, &ctx->qresync_uid_validity) < 0 ||
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen !imap_arg_get_atom(&args[1], &str) ||
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen str_to_uint64(str, &ctx->qresync_modseq) < 0) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client_send_command_error(ctx->cmd,
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen "Invalid QRESYNC parameters");
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen return FALSE;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen }
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen args += 2;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_array_init(&ctx->qresync_known_uids, 64);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (imap_arg_get_atom(args, &str)) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (imap_seq_set_nostar_parse(str, &ctx->qresync_known_uids) < 0) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client_send_command_error(ctx->cmd,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen "Invalid QRESYNC known-uids");
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return FALSE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen args++;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen } else {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen seq_range_array_add_range(&ctx->qresync_known_uids,
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen 1, (uint32_t)-1);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen }
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen if (imap_arg_get_list(args, &list_args)) {
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen if (!select_parse_qresync_known_set(ctx, list_args))
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen return FALSE;
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen args++;
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (!IMAP_ARG_IS_EOL(args)) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client_send_command_error(ctx->cmd,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen "Invalid QRESYNC parameters");
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic bool
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenselect_parse_options(struct imap_select_context *ctx,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const struct imap_arg *args)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *name;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen while (!IMAP_ARG_IS_EOL(args)) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (!imap_arg_get_atom(args, &name)) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen client_send_command_error(ctx->cmd,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "SELECT options contain non-atoms.");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return FALSE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen name = t_str_ucase(name);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen args++;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (strcmp(name, "CONDSTORE") == 0)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ctx->condstore = TRUE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen else if (strcmp(name, "QRESYNC") == 0) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (!select_parse_qresync(ctx, args))
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return FALSE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen args++;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen } else {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen client_send_command_error(ctx->cmd,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "Unknown FETCH modifier");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return FALSE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return TRUE;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void select_context_free(struct imap_select_context *ctx)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (array_is_created(&ctx->qresync_known_uids))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_free(&ctx->qresync_known_uids);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (array_is_created(&ctx->qresync_sample_seqset))
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen array_free(&ctx->qresync_sample_seqset);
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen if (array_is_created(&ctx->qresync_sample_uidset))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen array_free(&ctx->qresync_sample_uidset);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void cmd_select_finish(struct imap_select_context *ctx, int ret)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *resp_code;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret < 0) {
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen if (ctx->box != NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mailbox_free(&ctx->box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->cmd->client->mailbox = NULL;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen } else {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen resp_code = mailbox_is_readonly(ctx->box) ?
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen "READ-ONLY" : "READ-WRITE";
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client_send_tagline(ctx->cmd, t_strdup_printf(
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen "OK [%s] %s completed", resp_code,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->cmd->client->mailbox_examined ? "Examine" : "Select"));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen select_context_free(ctx);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenstatic bool cmd_select_continue(struct client_command_context *cmd)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct imap_select_context *ctx = cmd->context;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen int ret;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (imap_fetch_more(ctx->fetch_ctx, cmd) == 0) {
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* unfinished */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return FALSE;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen }
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen ret = imap_fetch_end(ctx->fetch_ctx);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret < 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client_send_box_error(ctx->cmd, ctx->box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen imap_fetch_free(&ctx->fetch_ctx);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen cmd_select_finish(ctx, ret);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return TRUE;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic int select_qresync(struct imap_select_context *ctx)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct imap_fetch_context *fetch_ctx;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct mail_search_args *search_args;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct imap_fetch_qresync_args qresync_args;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen search_args = mail_search_build_init();
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen search_args->args = p_new(search_args->pool, struct mail_search_arg, 1);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen search_args->args->type = SEARCH_UIDSET;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen search_args->args->value.seqset = ctx->qresync_known_uids;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen imap_search_add_changed_since(search_args, ctx->qresync_modseq);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen memset(&qresync_args, 0, sizeof(qresync_args));
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen qresync_args.qresync_sample_seqset = &ctx->qresync_sample_seqset;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen qresync_args.qresync_sample_uidset = &ctx->qresync_sample_uidset;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (imap_fetch_send_vanished(ctx->cmd->client, ctx->box,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen search_args, &qresync_args) < 0) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen mail_search_args_unref(&search_args);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fetch_ctx = imap_fetch_alloc(ctx->cmd->client, ctx->cmd->pool);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_uid_init);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_flags_init);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen imap_fetch_init_nofail_handler(fetch_ctx, imap_fetch_modseq_init);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen imap_fetch_begin(fetch_ctx, ctx->box, search_args);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen mail_search_args_unref(&search_args);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (imap_fetch_more(fetch_ctx, ctx->cmd) == 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* unfinished */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen ctx->fetch_ctx = fetch_ctx;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ctx->cmd->func = cmd_select_continue;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen ctx->cmd->context = ctx;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return 0;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen }
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen if (imap_fetch_end(fetch_ctx) < 0)
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen return -1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen imap_fetch_free(&fetch_ctx);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return 1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic int
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenselect_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct client *client = ctx->cmd->client;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct mailbox_status status;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen enum mailbox_flags flags = 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen int ret = 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen if (readonly)
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen flags |= MAILBOX_FLAG_READONLY;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen else
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen flags |= MAILBOX_FLAG_DROP_RECENT;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen ctx->box = mailbox_alloc(ctx->ns->list, mailbox, flags);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen if (mailbox_open(ctx->box) < 0) {
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen client_send_box_error(ctx->cmd, ctx->box);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen mailbox_free(&ctx->box);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen return -1;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen }
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (client->enabled_features != 0)
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen ret = mailbox_enable(ctx->box, client->enabled_features);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (ret < 0 ||
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen client_send_box_error(ctx->cmd, ctx->box);
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen return -1;
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen }
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen mailbox_get_open_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen STATUS_UIDNEXT | STATUS_KEYWORDS |
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen STATUS_HIGHESTMODSEQ, &status);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->mailbox = ctx->box;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->mailbox_examined = readonly;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->messages_count = status.messages;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->recent_count = status.recent;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->uidvalidity = status.uidvalidity;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client->notify_uidnext = status.uidnext;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_update_mailbox_flags(client, status.keywords);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_mailbox_flags(client, TRUE);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_line(client,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen t_strdup_printf("* %u EXISTS", status.messages));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_line(client,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen t_strdup_printf("* %u RECENT", status.recent));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (status.first_unseen_seq != 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_line(client,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen t_strdup_printf("* OK [UNSEEN %u] First unseen.",
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen status.first_unseen_seq));
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_line(client,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen t_strdup_printf("* OK [UIDVALIDITY %u] UIDs valid",
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen status.uidvalidity));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_send_line(client,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen t_strdup_printf("* OK [UIDNEXT %u] Predicted next UID",
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen status.uidnext));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client->nonpermanent_modseqs = status.nonpermanent_modseqs;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (status.nonpermanent_modseqs) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_send_line(client,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen "* OK [NOMODSEQ] No permanent modsequences");
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen } else if (!status.no_modseq_tracking) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_send_line(client,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen t_strdup_printf("* OK [HIGHESTMODSEQ %llu] Highest",
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen (unsigned long long)status.highest_modseq));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client->sync_last_full_modseq = status.highest_modseq;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ctx->qresync_uid_validity == status.uidvalidity &&
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen status.uidvalidity != 0 && !client->nonpermanent_modseqs) {
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen if ((ret = select_qresync(ctx)) < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_box_error(ctx->cmd, ctx->box);
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen return -1;
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen ret = 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen return ret;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen}
b7651d283ca261015ef3c445f1f27f340f0864e2Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainenstatic void close_selected_mailbox(struct client *client)
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen{
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen struct mailbox *box;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen if (client->mailbox == NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen client_search_updates_free(client);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen box = client->mailbox;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen client->mailbox = NULL;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen mailbox_free(&box);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen /* CLOSED response is required by QRESYNC */
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen client_send_line(client, "* OK [CLOSED] Previous mailbox closed.");
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen}
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainenbool cmd_select_full(struct client_command_context *cmd, bool readonly)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen struct client *client = cmd->client;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen struct imap_select_context *ctx;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen const struct imap_arg *args, *list_args;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen const char *mailbox, *error;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen int ret;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* <mailbox> [(optional parameters)] */
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen if (!client_read_args(cmd, 0, 0, &args))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (!imap_arg_get_astring(args, &mailbox)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen close_selected_mailbox(client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx = p_new(cmd->pool, struct imap_select_context, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->cmd = cmd;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen ctx->ns = client_find_namespace_full(cmd->client, &mailbox, &error);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (ctx->ns == NULL) {
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen close_selected_mailbox(client);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen client_send_tagline(cmd, error);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen return TRUE;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen }
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen (void)gettimeofday(&ctx->start_time, NULL);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (imap_arg_get_list(&args[1], &list_args)) {
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (!select_parse_options(ctx, list_args)) {
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen select_context_free(ctx);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen close_selected_mailbox(client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_assert(client->mailbox_change_lock == NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client->mailbox_change_lock = cmd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen close_selected_mailbox(client);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ctx->condstore) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* Enable while no mailbox is opened to avoid sending
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen HIGHESTMODSEQ for previously opened mailbox */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen (void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = select_open(ctx, mailbox, readonly);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen cmd_select_finish(ctx, ret);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return TRUE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen}
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainenbool cmd_select(struct client_command_context *cmd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen return cmd_select_full(cmd, FALSE);
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen}
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen