imap-commands.c revision 567b56c2d6a1063cad997c956f3ed1d9d735f14e
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "imap-common.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "array.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "buffer.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "ioloop.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "istream.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "ostream.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "time-util.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#include "imap-commands.h"
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstruct command_hook {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_hook_callback_t *pre;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_hook_callback_t *post;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch};
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic const struct command imap4rev1_commands[] = {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "CAPABILITY", cmd_capability, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "LOGOUT", cmd_logout, COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "NOOP", cmd_noop, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "APPEND", cmd_append, COMMAND_FLAG_BREAKS_SEQS |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch /* finish syncing and sending
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch all tagged commands before
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch we wait for APPEND input */
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "EXAMINE", cmd_examine, COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "CREATE", cmd_create, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "DELETE", cmd_delete, COMMAND_FLAG_BREAKS_MAILBOX |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_USE_NONEXISTENT },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "RENAME", cmd_rename, COMMAND_FLAG_USE_NONEXISTENT },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "LIST", cmd_list, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "LSUB", cmd_lsub, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "SELECT", cmd_select, COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "STATUS", cmd_status, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "SUBSCRIBE", cmd_subscribe, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UNSUBSCRIBE", cmd_unsubscribe, COMMAND_FLAG_USE_NONEXISTENT },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "CHECK", cmd_check, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "CLOSE", cmd_close, COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "COPY", cmd_copy, COMMAND_FLAG_USES_SEQS |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "EXPUNGE", cmd_expunge, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "FETCH", cmd_fetch, COMMAND_FLAG_USES_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "SEARCH", cmd_search, COMMAND_FLAG_USES_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "STORE", cmd_store, COMMAND_FLAG_USES_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID COPY", cmd_copy, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID FETCH", cmd_fetch, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID SEARCH", cmd_search, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID STORE", cmd_store, COMMAND_FLAG_BREAKS_SEQS }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch};
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#define IMAP4REV1_COMMANDS_COUNT N_ELEMENTS(imap4rev1_commands)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic const struct command imap_ext_commands[] = {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch /* IMAP extensions: */
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "CANCELUPDATE", cmd_cancelupdate,0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "ENABLE", cmd_enable, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "ID", cmd_id, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "IDLE", cmd_idle, COMMAND_FLAG_BREAKS_SEQS |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_REQUIRES_SYNC |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch /* finish syncing and sending
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch all tagged commands before
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch IDLE is started */
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "GETMETADATA", cmd_getmetadata, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "SETMETADATA", cmd_setmetadata, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "NAMESPACE", cmd_namespace, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "NOTIFY", cmd_notify, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "SORT", cmd_sort, COMMAND_FLAG_USES_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "THREAD", cmd_thread, COMMAND_FLAG_USES_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID EXPUNGE", cmd_uid_expunge, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "MOVE", cmd_move, COMMAND_FLAG_USES_SEQS |
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID MOVE", cmd_move, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID SORT", cmd_sort, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UID THREAD", cmd_thread, COMMAND_FLAG_BREAKS_SEQS },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "UNSELECT", cmd_unselect, COMMAND_FLAG_BREAKS_MAILBOX },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "X-CANCEL", cmd_x_cancel, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "X-STATE", cmd_x_state, COMMAND_FLAG_REQUIRES_SYNC },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "XLIST", cmd_list, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch /* IMAP URLAUTH (RFC4467): */
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "GENURLAUTH", cmd_genurlauth, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "RESETKEY", cmd_resetkey, 0 },
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch { "URLFETCH", cmd_urlfetch, 0 }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch};
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch#define IMAP_EXT_COMMANDS_COUNT N_ELEMENTS(imap_ext_commands)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan BoschARRAY_TYPE(command) imap_commands;
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic bool commands_unsorted;
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic ARRAY(struct command_hook) command_hooks;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_register(const char *name, command_func_t *func,
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch enum command_flags flags)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch struct command cmd;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_zero(&cmd);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd.name = name;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd.func = func;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd.flags = flags;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_append(&imap_commands, &cmd, 1);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch commands_unsorted = TRUE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_unregister(const char *name)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch const struct command *cmd;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch unsigned int i, count;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd = array_get(&imap_commands, &count);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch for (i = 0; i < count; i++) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch if (strcasecmp(cmd[i].name, name) == 0) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_delete(&imap_commands, i, 1);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_error("Trying to unregister unknown command '%s'", name);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_register_array(const struct command *cmdarr, unsigned int count)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch commands_unsorted = TRUE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_append(&imap_commands, cmdarr, count);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_unregister_array(const struct command *cmdarr, unsigned int count)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch while (count > 0) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_unregister(cmdarr->name);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch count--; cmdarr++;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_hook_register(command_hook_callback_t *pre,
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_hook_callback_t *post)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch struct command_hook hook;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch hook.pre = pre;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch hook.post = post;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_append(&command_hooks, &hook, 1);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid command_hook_unregister(command_hook_callback_t *pre,
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_hook_callback_t *post)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch const struct command_hook *hooks;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch unsigned int i, count;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch hooks = array_get(&command_hooks, &count);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch for (i = 0; i < count; i++) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch if (hooks[i].pre == pre && hooks[i].post == post) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_delete(&command_hooks, i, 1);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_panic("command_hook_unregister(): hook not registered");
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschbool command_exec(struct client_command_context *cmd)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch const struct command_hook *hook;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch bool finished;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch struct timeval cmd_start_timeval;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch uint64_t cmd_start_bytes_in, cmd_start_bytes_out, cmd_start_lock_waits;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_assert(!cmd->executing);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch io_loop_time_refresh();
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd_start_lock_waits = file_lock_wait_get_total_usecs();
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd_start_timeval = ioloop_timeval;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd_start_bytes_in = i_stream_get_absolute_offset(cmd->client->input);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd_start_bytes_out = cmd->client->output->offset;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->executing = TRUE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_foreach(&command_hooks, hook)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch hook->pre(cmd);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch finished = cmd->func(cmd);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_foreach(&command_hooks, hook)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch hook->post(cmd);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->executing = FALSE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch if (cmd->state == CLIENT_COMMAND_STATE_DONE)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch finished = TRUE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch io_loop_time_refresh();
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->stats.running_usecs +=
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch timeval_diff_usecs(&ioloop_timeval, &cmd_start_timeval);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->stats.lock_wait_usecs +=
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch file_lock_wait_get_total_usecs() - cmd_start_lock_waits;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->stats.bytes_in += i_stream_get_absolute_offset(cmd->client->input) -
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd_start_bytes_in;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch cmd->stats.bytes_out += cmd->client->output->offset - cmd_start_bytes_out;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return finished;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic int command_cmp(const struct command *c1, const struct command *c2)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return strcasecmp(c1->name, c2->name);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstatic int command_bsearch(const char *name, const struct command *cmd)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return strcasecmp(name, cmd->name);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschstruct command *command_find(const char *name)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch if (commands_unsorted) {
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_sort(&imap_commands, command_cmp);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch commands_unsorted = FALSE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch }
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch return array_bsearch(&imap_commands, name, command_bsearch);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid commands_init(void)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_array_init(&imap_commands, 64);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch i_array_init(&command_hooks, 4);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch commands_unsorted = FALSE;
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_register_array(imap4rev1_commands, IMAP4REV1_COMMANDS_COUNT);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch command_register_array(imap_ext_commands, IMAP_EXT_COMMANDS_COUNT);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch
8620dc793885749c37000f11dd83b902b6844e20Stephan Boschvoid commands_deinit(void)
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch{
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_free(&imap_commands);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch array_free(&command_hooks);
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch}
8620dc793885749c37000f11dd83b902b6844e20Stephan Bosch