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