[Dovecot] Problem with the command hooks api

Tony dove-tony at yttrium.plus.com
Sun Feb 24 19:29:26 EET 2013


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 {



More information about the dovecot mailing list