I have been trying to use the command hook api in an experimental plugin I
have written. The hook is registered using the command_hook_register function,
and for most commands my hook functions get called once as expected.
But when the client uses one of the "UID" commands (e.g. "UID
FETCH" ) the
hook functions are executed twice.
I am using dovecot version 2.1.12.
Am I correct in thinking this is a bug?
If I am wrong and this is the intended behaviour, how should I detect whether
the hook function call is the first or second for a client's command (in
particular for the 'post command' hook)?
Assuming it is a bug, I modified the code in the command_exec function to stop
the second hook call, a patch for this is below. This appears to apply to
later dovecot releases as well. I am happy for this code to be included in
future releases of dovecot.
Thanks,
Tony.
diff -ur -x .deps -x Makefile dovecot-2.1.12-orig/src/imap/imap-commands.c
dovecot-2.1.12-mod/src/imap/imap-commands.c
--- dovecot-2.1.12-orig/src/imap/imap-commands.c 2012-03-22
12:59:17.000000000 +0000
+++ dovecot-2.1.12-mod/src/imap/imap-commands.c 2013-02-20 17:15:50.000000000
+0000
@@ -38,7 +38,7 @@
{ "FETCH", cmd_fetch,
COMMAND_FLAG_USES_SEQS },
{ "SEARCH", cmd_search,
COMMAND_FLAG_USES_SEQS },
{ "STORE", cmd_store,
COMMAND_FLAG_USES_SEQS },
- { "UID", cmd_uid, 0 },
+ { "UID", cmd_uid,
COMMAND_FLAG_HOOKS_DELAY },
{ "UID COPY", cmd_copy,
COMMAND_FLAG_BREAKS_SEQS },
{ "UID FETCH", cmd_fetch,
COMMAND_FLAG_BREAKS_SEQS },
{ "UID SEARCH", cmd_search,
COMMAND_FLAG_BREAKS_SEQS },
@@ -142,12 +142,20 @@
{
const struct command_hook *hook;
bool ret;
+ bool exec_hooks = FALSE;
- array_foreach(&command_hooks, hook)
- hook->pre(cmd);
+ if ( !(cmd->cmd_flags & COMMAND_FLAG_HOOKS_DELAY)) {
+ exec_hooks = TRUE;
+ array_foreach(&command_hooks, hook)
+ hook->pre(cmd);
+ }
ret = cmd->func(cmd);
- array_foreach(&command_hooks, hook)
- hook->post(cmd);
+
+ if (exec_hooks != FALSE)
+ {
+ array_foreach(&command_hooks, hook)
+ hook->post(cmd);
+ }
return ret;
}
diff -ur -x .deps -x Makefile dovecot-2.1.12-orig/src/imap/imap-commands.h
dovecot-2.1.12-mod/src/imap/imap-commands.h
--- dovecot-2.1.12-orig/src/imap/imap-commands.h 2011-12-13
11:35:28.000000000 +0000
+++ dovecot-2.1.12-mod/src/imap/imap-commands.h 2013-02-20 17:15:44.000000000
+0000
@@ -30,7 +30,9 @@
Dovecot internally returns it for all kinds of commands,
but unfortunately RFC 5530 specifies it only for "delete
something"
operations. */
- COMMAND_FLAG_USE_NONEXISTENT = 0x10
+ COMMAND_FLAG_USE_NONEXISTENT = 0x10,
+ /* Set when need to delay command hook function calls due to recursive
command_exec() */
+ COMMAND_FLAG_HOOKS_DELAY = 0x20
};
struct command {