]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Merged changes from v2.1 tree.
authorTimo Sirainen <tss@iki.fi>
Wed, 26 Sep 2012 15:01:01 +0000 (18:01 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 26 Sep 2012 15:01:01 +0000 (18:01 +0300)
53 files changed:
1  2 
NEWS
configure.in
src/auth/auth-request.c
src/auth/auth-request.h
src/auth/db-ldap.c
src/auth/userdb-static.c
src/config/config-parser.c
src/director/director-connection.c
src/director/director.c
src/director/director.h
src/doveadm/Makefile.am
src/doveadm/doveadm-settings.c
src/doveadm/doveadm-settings.h
src/doveadm/doveadm.c
src/lib-imap-client/imapc-client.h
src/lib-imap-client/imapc-connection.c
src/lib-imap/imap-parser.c
src/lib-imap/imap-parser.h
src/lib-master/master-service-settings-cache.c
src/lib-settings/settings-parser.c
src/lib-storage/index/dbox-common/dbox-storage.c
src/lib-storage/index/dbox-multi/mdbox-file.c
src/lib-storage/index/dbox-multi/mdbox-map-private.h
src/lib-storage/index/dbox-multi/mdbox-map.c
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/index-status.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/pop3c/pop3c-mail.c
src/lib-storage/list/mailbox-list-fs-iter.c
src/lib-storage/list/mailbox-list-maildir-iter.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-storage.h
src/lib-storage/mailbox-guid-cache.c
src/lib-storage/mailbox-list-iter.h
src/lib-storage/mailbox-list-private.h
src/lib-storage/mailbox-list.c
src/lib-storage/mailbox-list.h
src/lib/hash.c
src/lmtp/client.c
src/lmtp/commands.c
src/lmtp/lmtp-settings.c
src/lmtp/lmtp-settings.h
src/plugins/acl/acl-lookup-dict.c
src/plugins/fts-lucene/lucene-wrapper.cc
src/plugins/fts-solr/fts-backend-solr.c
src/plugins/mailbox-alias/mailbox-alias-plugin.c
src/plugins/quota/quota-count.c
src/plugins/quota/quota-maildir.c
src/plugins/quota/quota-private.h
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c

diff --cc NEWS
index a94973ce7b337cf6f86b0a84c601a66e194f28d9,e4f06b1abea7595dca3496e2fcf78b6875332e70..f10b5ee3e36ac2d7607d41493f9a1f6ee7b5e995
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,24 -1,29 +1,50 @@@
 +v2.2.UNSTABLE 2012-xx-xx  Timo Sirainen <tss@iki.fi>
 +
 +      * "doveadm auth" command was renamed to "doveadm auth test"
 +
 +      + Implemented IMAP MOVE and BINARY extensions
 +      + Implemented IMAP CATENATE extension (by Stephan Bosch)
 +      + Implemented IMAP NOTIFY extension. Requires mailbox_list_index=yes
 +        to be enabled.
 +      + Improved mailbox list indexes. They should be usable now, although
 +        still disabled by default.
 +      + Redesigned and rewritten dsync. The new design makes the syncing
 +        faster, more reliable and more featureful. The new dsync protocol
 +        isn't backwards compatible with old dsync versions (but is designed
 +        to be forwards compatible with future versions).
 +      + All mailbox formats now support per-user message flags for shared
 +        mailboxes by using a private index. It can be enabled by adding
 +        :INDEXPVT=<path> to mail location. This should be used instead of
 +        :INDEX also for Maildir/mbox to improve performance.
 +      + LMTP proxy: Implemented XCLIENT extension for passing remote IP
 +        address through proxy.
 +
+ v2.1.10 2012-09-18  Timo Sirainen <tss@iki.fi>
+       + imap: Implemented THREAD=ORDEREDSUBJECT extension.
+       + Added "doveadm exec" command to easily execute commands from
+         libexec_dir, e.g. "doveadm exec imap -u user@domain"
+       + Added "doveadm copy" command.
+       + doveadm copy/move: Added optional user parameter to specify the
+         source username. This allows easily copying mails between different
+         users.
+       + Added namespace { disabled } setting to quickly enable/disable
+         namespaces. This is especially useful when its value is returned by
+         userdb.
+       + Added mailbox_alias plugin. It allows creating mailbox aliases using
+         symlinks.
+       + imapc storage: Added imapc_max_idle_time setting to force activity
+         on connection.
+       + fts-solr: Expunging multiple messages is now faster.
+       - director: In some conditions director may have disconnected from
+         another director (without logging about it), thinking it was sending
+         invalid data.
+       - imap: Various fixes to listing mailboxes.
+       - pop3-migration plugin: Avoid disconnection from POP3 server due
+         to idling.
+       - login processes crashed if there were a lot of local {} or remote {}
+         settings blocks.
  v2.1.9 2012-08-01  Timo Sirainen <tss@iki.fi>
  
        * mail-log plugin: Log mailbox names with UTF-8 everywhere 
diff --cc configure.in
Simple merge
Simple merge
index dd74b059e3ba145789af8db5e9d77fc3e4bd337e,0494a25c8c53c9880afb7ed2171f8f937964c5e5..59d6315e6deb224ed1ccb5231129a87643dd2e87
@@@ -210,8 -206,11 +210,12 @@@ int auth_request_password_verify(struc
  
  const struct var_expand_table *
  auth_request_get_var_expand_table(const struct auth_request *auth_request,
 -                                auth_request_escape_func_t *escape_func);
 +                                auth_request_escape_func_t *escape_func)
 +      ATTR_NULL(2);
+ struct var_expand_table *
+ auth_request_get_var_expand_table_full(const struct auth_request *auth_request,
+                                      auth_request_escape_func_t *escape_func,
 -                                     unsigned int *count);
++                                     unsigned int *count) ATTR_NULL(2);
  const char *auth_request_str_escape(const char *string,
                                    const struct auth_request *request);
  
index dd54d9bd5897528161df64b45ef308842152b35b,0c53c53f5453e31552003bb287aa6c1b1042dfa9..c520a1652a6d1c443a80ad2bc6a58803979e17a0
@@@ -61,9 -61,8 +61,8 @@@ struct db_ldap_result_iterate_context 
        const ARRAY_TYPE(ldap_field) *attr_map;
        unsigned int attr_idx;
  
 -      /* ldap_attr_name => struct db_ldap_value */
 -      struct hash_table *ldap_attrs;
 +      /* attribute name => value */
 +      HASH_TABLE(char *, struct db_ldap_value *) ldap_attrs;
-       struct var_expand_table *var_table;
  
        const char *val_1_arr[2];
        string_t *var, *debug;
Simple merge
Simple merge
index 5e9104b26640e884d6ab807db1ae6978eca9a432,a7b82069c48b9e756e75609aaab33419a855696c..e2b13e1977a75add0e41fbb123f8a4127e8499fa
@@@ -183,8 -191,15 +191,14 @@@ static void director_connection_send_co
        connect_str = t_strdup_printf("CONNECT\t%s\t%u\n",
                                      net_ip2addr(&host->ip), host->port);
        director_connection_send(conn, connect_str);
 -      (void)o_stream_flush(conn->output);
        o_stream_uncork(conn->output);
  
+       /* wait for a while for the remote to disconnect, so it will hopefully
+          see our CONNECT command. we'll also log the warning later to avoid
+          multiple log lines about it. */
+       conn->connect_request_to = host;
+       director_host_ref(conn->connect_request_to);
        conn->to_disconnect =
                timeout_add(DIRECTOR_WAIT_DISCONNECT_SECS*1000,
                            director_connection_wait_timeout, conn);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0aeee77421d1f1758b99de6fcaca67529bf23d62,6fa7c73430865a1516a8e1c69f0838e7d417f377..54bc3927a7a9b718223712d959ca75367380982f
@@@ -16,9 -16,9 +16,10 @@@ enum arg_parse_type 
        ARG_PARSE_ATOM,
        ARG_PARSE_STRING,
        ARG_PARSE_LITERAL,
 +      ARG_PARSE_LITERAL8,
        ARG_PARSE_LITERAL_DATA,
-       ARG_PARSE_LITERAL_DATA_FORCED
+       ARG_PARSE_LITERAL_DATA_FORCED,
+       ARG_PARSE_TEXT
  };
  
  struct imap_parser {
index 94937073809625498b8d4736f13a0b92a868167f,357a289ff00f5ddac7be2f69091dd8555905e460..623d3def8bf6e80d7a7fad8c7a6058a780dc7c35
@@@ -17,10 -17,10 +17,14 @@@ enum imap_parser_flags 
        IMAP_PARSE_FLAG_ATOM_ALLCHARS   = 0x08,
        /* Allow strings to contain CRLFs */
        IMAP_PARSE_FLAG_MULTILINE_STR   = 0x10,
-       IMAP_PARSE_FLAG_LITERAL8        = 0x40
 +      /* Parse in list context; ')' parses as EOL */
 +      IMAP_PARSE_FLAG_INSIDE_LIST     = 0x20,
 +      /* Parse literal8 and set it as flag to imap_arg. */
 -      IMAP_PARSE_FLAG_SERVER_TEXT     = 0x20
++      IMAP_PARSE_FLAG_LITERAL8        = 0x40,
+       /* We're parsing IMAP server replies. Parse the "text" after
+          OK/NO/BAD/BYE replies as a single atom. We assume that the initial
+          "*" or tag was already skipped over. */
++      IMAP_PARSE_FLAG_SERVER_TEXT     = 0x80
  };
  
  struct imap_parser;
Simple merge
index 998c60196db51e8754259c6678b17dff2007412e,8090a261e9dc5ed216b7771003b5c957acea142c..1348d0236ce2eee1be70b3dc5f735b3734de283e
@@@ -103,15 -104,11 +103,16 @@@ int dbox_storage_create(struct mail_sto
                dir = mail_user_home_expand(_storage->user,
                                            set->mail_attachment_dir);
                storage->attachment_dir = p_strdup(_storage->pool, dir);
 -              storage->attachment_fs = fs_init(name, args, &fs_set);
 -      } T_END;
 +              if (fs_init(name, args, &fs_set, &storage->attachment_fs,
 +                          &error) < 0) {
 +                      *error_r = t_strdup_printf("mail_attachment_fs: %s",
 +                                                 error);
 +                      return -1;
 +              }
 +      }
  
-       dbox_verify_alt_path(ns->list);
+       if (!ns->list->set.alt_dir_nocheck)
+               dbox_verify_alt_path(ns->list);
        return 0;
  }
  
index c10ddbba993cf0a576edcbd7c7416e34e4ead49a,6bd96852b472133ff138f0770534d46d29d56d28..d150b79b9385cf35f685b4646c64f171cfda1bbf
@@@ -302,11 -302,14 +302,14 @@@ int mdbox_file_create_fd(struct dbox_fi
  {
        struct mdbox_file *mfile = (struct mdbox_file *)file;
        struct mdbox_map *map = mfile->storage->map;
 -      mode_t create_mode, old_mask;
 -      gid_t create_gid;
 -      const char *create_gid_origin, *p, *dir, *error;
++      struct mailbox_permissions perm;
 +      mode_t old_mask;
 +      const char *p, *dir;
        int fd;
  
-       old_mask = umask(0666 & ~map->perm.file_create_mode);
 -      mdbox_map_get_create_mode(map, &create_mode, &create_gid,
 -                                &create_gid_origin);
 -      old_mask = umask(0666 & ~create_mode);
++      mailbox_list_get_root_permissions(map->root_list, &perm);
++
++      old_mask = umask(0666 & ~perm.file_create_mode);
        fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
        umask(old_mask);
        if (fd == -1 && errno == ENOENT && parents &&
                        return -1;
                }
                /* try again */
-               old_mask = umask(0666 & ~map->perm.file_create_mode);
 -              old_mask = umask(0666 & ~create_mode);
++              old_mask = umask(0666 & ~perm.file_create_mode);
                fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
                umask(old_mask);
        }
        if (fd == -1) {
                mail_storage_set_critical(&file->storage->storage,
                        "open(%s, O_CREAT) failed: %m", path);
-       } else if (map->perm.file_create_gid == (gid_t)-1) {
 -      } else if (create_gid == (gid_t)-1) {
++      } else if (perm.file_create_gid == (gid_t)-1) {
                /* no group change */
-       } else if (fchown(fd, (uid_t)-1, map->perm.file_create_gid) < 0) {
 -      } else if (fchown(fd, (uid_t)-1, create_gid) < 0) {
++      } else if (fchown(fd, (uid_t)-1, perm.file_create_gid) < 0) {
                if (errno == EPERM) {
                        mail_storage_set_critical(&file->storage->storage, "%s",
                                eperm_error_get_chgrp("fchown", path,
-                                       map->perm.file_create_gid,
-                                       map->perm.file_create_gid_origin));
 -                                                    create_gid,
 -                                                    create_gid_origin));
++                                      perm.file_create_gid,
++                                      perm.file_create_gid_origin));
                } else {
                        mail_storage_set_critical(&file->storage->storage,
                                "fchown(%s, -1, %ld) failed: %m",
-                               path, (long)map->perm.file_create_gid);
 -                              path, (long)create_gid);
++                              path, (long)perm.file_create_gid);
                }
                /* continue anyway */
        }
index 146c22f67ebf4ee1bcdb8ce0919d03b853b9f496,5d4b7e65ab437fed65ee5a6f3a405005ec6925fe..261c236ac9973c235f7bd33359b1a837769d76ba
@@@ -20,9 -20,12 +20,8 @@@ struct mdbox_map 
        uint32_t map_ext_id, ref_ext_id;
  
        struct mailbox_list *root_list;
-       struct mailbox_permissions perm;
 -      mode_t _create_mode;
 -      gid_t _create_gid;
 -      char *_create_gid_origin;
  
        unsigned int verify_existing_file_ids:1;
 -      unsigned int create_mode_set:1;
  };
  
  struct mdbox_map_append {
index 65f37335bf11402839c6dfa2639a3f9d70edf0bb,7bc20a7b001370778ab3010460ccd7ffd6ef096b..8f1d05d2dac98bc54c02bbc08477c0b7f3e11fe0
@@@ -140,6 -168,9 +135,7 @@@ static void mdbox_map_cleanup(struct md
  static int mdbox_map_open_internal(struct mdbox_map *map, bool create_missing)
  {
        enum mail_index_open_flags open_flags;
 -      mode_t create_mode;
 -      gid_t create_gid;
 -      const char *create_gid_origin;
++      struct mailbox_permissions perm;
        int ret = 0;
  
        if (map->view != NULL) {
                return 1;
        }
  
 -      mdbox_map_get_create_mode(map, &create_mode, &create_gid,
 -                                &create_gid_origin);
 -      mail_index_set_permissions(map->index, create_mode,
 -                                 create_gid, create_gid_origin);
++      mailbox_list_get_root_permissions(map->root_list, &perm);
++      mail_index_set_permissions(map->index, perm.file_create_mode,
++                                 perm.file_create_gid,
++                                 perm.file_create_gid_origin);
        open_flags = MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY |
                mail_storage_settings_to_index_flags(MAP_STORAGE(map)->set);
        if (create_missing) {
Simple merge
index 7bbf220c8f4970318efc6161dc74ffb4b8def486,7e5e21662be2e78981faad2b9de8099f408f714b..e45676f1829964f683fd4f723bb35321ac0d1a3e
@@@ -756,11 -777,18 +762,18 @@@ fs_list_iter_next(struct mailbox_list_i
        if (ret <= 0)
                return NULL;
  
 -      if (_ctx->list->ns->type == NAMESPACE_SHARED &&
++      if (_ctx->list->ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
+           !_ctx->list->ns->list->mail_set->mail_shared_explicit_inbox &&
 -          strlen(ctx->info.name) < _ctx->list->ns->prefix_len) {
++          strlen(ctx->info.vname) < _ctx->list->ns->prefix_len) {
+               /* shared/user INBOX, IMAP code already lists it */
+               return fs_list_iter_next(_ctx);
+       }
        if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) != 0) {
                mailbox_list_set_subscription_flags(ctx->ctx.list,
 -                                                  ctx->info.name,
 +                                                  ctx->info.vname,
                                                    &ctx->info.flags);
        }
 -      i_assert(ctx->info.name != NULL);
 +      i_assert(ctx->info.vname != NULL);
        return &ctx->info;
  }
Simple merge
Simple merge
index 8df0bc77b0f9e084bcb51f8acea732de95f19899,0000000000000000000000000000000000000000..a0c1597aaa19c14999f1b229ab9421b30720ef54
mode 100644,000000..100644
--- /dev/null
@@@ -1,85 -1,0 +1,87 @@@
-       /* For mailbox_list_iter_init_namespaces(): Skip namespaces that
 +#ifndef MAILBOX_LIST_ITER_H
 +#define MAILBOX_LIST_ITER_H
 +
 +#include "mail-namespace.h"
 +#include "mailbox-list.h"
 +
 +enum mailbox_list_iter_flags {
 +      /* Ignore index file and ACLs (used by ACL plugin internally) */
 +      MAILBOX_LIST_ITER_RAW_LIST              = 0x000001,
 +      /* Don't list autocreated mailboxes (e.g. INBOX) unless they
 +         physically exist */
 +      MAILBOX_LIST_ITER_NO_AUTO_BOXES         = 0x000004,
 +
++      /* Skip all kinds of mailbox aliases. This typically includes symlinks
++         that point to the same directory. Also when iterating with
++         mailbox_list_iter_init_namespaces() skip namespaces that
 +         have alias_for set. */
 +      MAILBOX_LIST_ITER_SKIP_ALIASES          = 0x000008,
 +      /* For mailbox_list_iter_init_namespaces(): '*' in a pattern doesn't
 +         match beyond namespace boundary (e.g. "foo*" or "*o" doesn't match
 +         "foo." namespace's mailboxes, but "*.*" does). also '%' can't match
 +         namespace prefixes, if there exists a parent namespace whose children
 +         it matches. */
 +      MAILBOX_LIST_ITER_STAR_WITHIN_NS        = 0x000010,
 +
 +      /* List only subscribed mailboxes */
 +      MAILBOX_LIST_ITER_SELECT_SUBSCRIBED     = 0x000100,
 +      /* Return MAILBOX_CHILD_* if mailbox's children match selection
 +         criteria, even if the mailbox itself wouldn't match. */
 +      MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH = 0x000200,
 +      /* Return only mailboxes that have special use flags */
 +      MAILBOX_LIST_ITER_SELECT_SPECIALUSE     = 0x000400,
 +
 +      /* Don't return any flags unless it can be done without cost */
 +      MAILBOX_LIST_ITER_RETURN_NO_FLAGS       = 0x001000,
 +      /* Return MAILBOX_SUBSCRIBED flag */
 +      MAILBOX_LIST_ITER_RETURN_SUBSCRIBED     = 0x002000,
 +      /* Return children flags */
 +      MAILBOX_LIST_ITER_RETURN_CHILDREN       = 0x004000,
 +      /* Return IMAP special use flags */
 +      MAILBOX_LIST_ITER_RETURN_SPECIALUSE     = 0x008000
 +};
 +
 +struct mailbox_info {
 +      const char *vname;
 +      const char *special_use;
 +      enum mailbox_info_flags flags;
 +
 +      struct mail_namespace *ns;
 +};
 +
 +/* Returns a single pattern from given reference and pattern. */
 +const char *mailbox_list_join_refpattern(struct mailbox_list *list,
 +                                       const char *ref, const char *pattern);
 +
 +/* Initialize new mailbox list request. Pattern may contain '%' and '*'
 +   wildcards as defined by RFC-3501. */
 +struct mailbox_list_iterate_context *
 +mailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
 +                     enum mailbox_list_iter_flags flags);
 +/* Like mailbox_list_iter_init(), but support multiple patterns. Patterns is
 +   a NULL-terminated list of strings. It must contain at least one pattern. */
 +struct mailbox_list_iterate_context *
 +mailbox_list_iter_init_multiple(struct mailbox_list *list,
 +                              const char *const *patterns,
 +                              enum mailbox_list_iter_flags flags);
 +/* List mailbox_list_iter_init_multiple(), but list mailboxes from all the
 +   specified namespaces. */
 +struct mailbox_list_iterate_context *
 +mailbox_list_iter_init_namespaces(struct mail_namespace *namespaces,
 +                                const char *const *patterns,
 +                                enum mail_namespace_type type_mask,
 +                                enum mailbox_list_iter_flags flags);
 +/* Get next mailbox. Returns the mailbox name */
 +const struct mailbox_info *
 +mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx);
 +/* Deinitialize mailbox list request. Returns -1 if some error
 +   occurred while listing. */
 +int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **ctx);
 +/* List one mailbox. Returns 1 if info returned, 0 if mailbox doesn't exist,
 +   -1 if error. */
 +int mailbox_list_mailbox(struct mailbox_list *list, const char *name,
 +                       enum mailbox_info_flags *flags_r);
 +/* Returns 1 if mailbox has children, 0 if not, -1 if error. */
 +int mailbox_has_children(struct mailbox_list *list, const char *name);
 +
 +#endif
index aead168c408bbb7b6eb76db4864a88b6686e3762,5c5a2922e04ae436d78f239d64cfe997f9dacb31..813450d29b6b2c545c0b5dfa12f84e3a9af40b47
@@@ -184,8 -192,13 +184,11 @@@ int mailbox_list_iter_subscriptions_ref
  
  bool mailbox_list_name_is_too_large(const char *name, char sep);
  enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d);
+ int mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list,
+                                        const char *dir_path,
+                                        const struct dirent *d);
  bool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
                                        const char **name);
 -int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
 -                                        const char *name);
  
  void mailbox_list_add_change(struct mailbox_list *list,
                             enum mailbox_log_record_type type,
Simple merge
index d6c9086f0f652410869b8f6e4503a27486e907e7,1d0c61cd07c08b847a15020d471f3c9d7c7c9e52..1dbda64dbe66c5930ef0c3f46d1dd4fffef5f343
@@@ -105,8 -145,18 +105,10 @@@ struct mailbox_list_settings 
        char escape_char;
        /* Use UTF-8 mailbox names on filesystem instead of mUTF-7 */
        bool utf8;
+       /* Don't check/create the alt-dir symlink. */
+       bool alt_dir_nocheck;
  };
  
 -struct mailbox_info {
 -      const char *name;
 -      const char *special_use;
 -      enum mailbox_info_flags flags;
 -
 -      struct mail_namespace *ns;
 -};
 -
  struct mailbox_permissions {
        /* The actual uid/gid of the mailbox */
        uid_t file_uid;
diff --cc src/lib/hash.c
index 816b8b9ab316d3b647920b0e3055a4f82dcca67e,7c52b7cbd7cc73e3285b90a158a3d49c24863a6c..fbd45c94692278ea67be279b394d5d4a7482c7e9
@@@ -8,24 -8,8 +8,24 @@@
  
  #include <ctype.h>
  
- #define HASH_TABLE_MIN_SIZE 131
+ #define HASH_TABLE_MIN_SIZE 67
  
 +#undef hash_table_create
 +#undef hash_table_create_direct
 +#undef hash_table_destroy
 +#undef hash_table_clear
 +#undef hash_table_lookup
 +#undef hash_table_lookup_full
 +#undef hash_table_insert
 +#undef hash_table_update
 +#undef hash_table_remove
 +#undef hash_table_count
 +#undef hash_table_iterate_init
 +#undef hash_table_iterate
 +#undef hash_table_freeze
 +#undef hash_table_thaw
 +#undef hash_table_copy
 +
  struct hash_node {
        struct hash_node *next;
        void *key;
Simple merge
Simple merge
index eb4400c6cfce78f206696089be3f433ac2c9e7af,b7e3ae6c4842b3b19b189dd5b38550e2c2d3ce38..c699ed81df77e8673abe425979fe6f7200a678dd
@@@ -59,9 -59,9 +59,10 @@@ struct service_settings lmtp_service_se
  static const struct setting_define lmtp_setting_defines[] = {
        DEF(SET_BOOL, lmtp_proxy),
        DEF(SET_BOOL, lmtp_save_to_detail_mailbox),
 -      DEF(SET_STR_VARS, login_greeting),
+       DEF(SET_BOOL, lmtp_rcpt_check_quota),
        DEF(SET_STR, lmtp_address_translate),
 +      DEF(SET_STR_VARS, login_greeting),
 +      DEF(SET_STR, login_trusted_networks),
  
        SETTING_DEFINE_LIST_END
  };
  static const struct lmtp_settings lmtp_default_settings = {
        .lmtp_proxy = FALSE,
        .lmtp_save_to_detail_mailbox = FALSE,
+       .lmtp_rcpt_check_quota = FALSE,
 +      .lmtp_address_translate = "",
        .login_greeting = PACKAGE_NAME" ready.",
 -      .lmtp_address_translate = ""
 +      .login_trusted_networks = ""
  };
  
  static const struct setting_parser_info *lmtp_setting_dependencies[] = {
index 57178484d1200ed3cf24c02bf00a77c1ca1f79cf,92d8c4f5bd5b81ebabf51f5a437c114503123c16..b01a4740c4a302e7cd08d2501e6a385d78868c36
@@@ -7,9 -7,9 +7,10 @@@ struct lmtp_settings
  struct lmtp_settings {
        bool lmtp_proxy;
        bool lmtp_save_to_detail_mailbox;
 -      const char *login_greeting;
+       bool lmtp_rcpt_check_quota;
        const char *lmtp_address_translate;
 +      const char *login_greeting;
 +      const char *login_trusted_networks;
  };
  
  extern const struct setting_parser_info lmtp_setting_parser_info;
Simple merge
index 0000000000000000000000000000000000000000,86e60f15d60311cdde5b3e93a32fee3a38f31ff3..43e4b46f48fbfe1203835f72df5905c691ca2093
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,335 +1,334 @@@
 -      ARRAY_DEFINE(aliases, struct mailbox_alias);
+ /* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+ #include "lib.h"
+ #include "str.h"
+ #include "mail-storage-hooks.h"
+ #include "mail-storage-private.h"
+ #include "mailbox-list-private.h"
+ #include "mailbox-alias-plugin.h"
+ #define MAILBOX_ALIAS_USER_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, mailbox_alias_user_module)
+ #define MAILBOX_ALIAS_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, mailbox_alias_storage_module)
+ #define MAILBOX_ALIAS_LIST_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
+ struct mailbox_alias {
+       const char *old_vname, *new_vname;
+ };
+ struct mailbox_alias_user {
+       union mail_user_module_context module_ctx;
 -      ret = abox->module_ctx.super.create(box, update, directory);
++      ARRAY(struct mailbox_alias) aliases;
+ };
+ struct mailbox_alias_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+ };
+ struct mailbox_alias_mailbox {
+       union mailbox_module_context module_ctx;
+ };
+ enum mailbox_symlink_existence {
+       MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT,
+       MAILBOX_SYMLINK_EXISTENCE_SYMLINK,
+       MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK
+ };
+ static MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
+                                 &mail_user_module_register);
+ static MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
+                                 &mail_storage_module_register);
+ static MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
+                                 &mailbox_list_module_register);
+ const char *mailbox_alias_plugin_version = DOVECOT_VERSION;
+ static const char *
+ mailbox_alias_find_new(struct mail_user *user, const char *new_vname)
+ {
+       struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
+       const struct mailbox_alias *alias;
+       array_foreach(&auser->aliases, alias) {
+               if (strcmp(alias->new_vname, new_vname) == 0)
+                       return alias->old_vname;
+       }
+       return NULL;
+ }
+ static int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
+                                 enum mailbox_symlink_existence *existence_r)
+ {
+       struct mailbox_alias_mailbox_list *alist =
+               MAILBOX_ALIAS_LIST_CONTEXT(list);
+       struct stat st;
+       const char *symlink_name, *symlink_path;
+       symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
+       symlink_path = mailbox_list_get_path(list, symlink_name,
+                                            MAILBOX_LIST_PATH_TYPE_DIR);
+       if (lstat(symlink_path, &st) < 0) {
+               if (errno == ENOENT) {
+                       *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
+                       return 0;
+               }
+               mailbox_list_set_critical(list,
+                                         "lstat(%s) failed: %m", symlink_path);
+               return -1;
+       }
+       if (S_ISLNK(st.st_mode))
+               *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
+       else
+               *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
+       return 0;
+ }
+ static int mailbox_is_alias_symlink(struct mailbox *box)
+ {
+       enum mailbox_symlink_existence existence;
+       if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
+               return 0;
+       if (mailbox_symlink_exists(box->list, box->vname, &existence) < 0) {
+               mail_storage_copy_list_error(box->storage, box->list);
+               return -1;
+       }
+       return existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
+ }
+ static int
+ mailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
+ {
+       struct mailbox_alias_user *auser =
+               MAILBOX_ALIAS_USER_CONTEXT(list->ns->user);
+       const struct mailbox_alias *alias;
+       enum mailbox_symlink_existence existence;
+       int ret = 0;
+       array_foreach(&auser->aliases, alias) {
+               if (strcmp(alias->old_vname, old_vname) == 0) {
+                       if (mailbox_symlink_exists(list, alias->new_vname,
+                                                  &existence) < 0)
+                               ret = -1;
+                       if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
+                               return 1;
+               }
+       }
+       return ret;
+ }
+ static int
+ mailbox_alias_create_symlink(struct mailbox *box,
+                            const char *old_name, const char *new_name)
+ {
+       const char *old_path, *new_path, *fname;
+       old_path = mailbox_list_get_path(box->list, old_name,
+                                        MAILBOX_LIST_PATH_TYPE_DIR);
+       new_path = mailbox_list_get_path(box->list, new_name,
+                                        MAILBOX_LIST_PATH_TYPE_DIR);
+       fname = strrchr(old_path, '/');
+       i_assert(fname != NULL);
+       fname++;
+       i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
+       if (symlink(fname, new_path) < 0) {
+               if (errno == EEXIST) {
+                       mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
+                                              "Mailbox already exists");
+                       return -1;
+               }
+               mail_storage_set_critical(box->storage,
+                       "symlink(%s, %s) failed: %m", fname, new_path);
+               return -1;
+       }
+       return 0;
+ }
+ static const char *
+ mailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
+ {
+       struct mailbox_alias_mailbox_list *alist =
+               MAILBOX_ALIAS_LIST_CONTEXT(list);
+       const char *old_vname;
+       enum mailbox_symlink_existence existence;
+       /* access the old mailbox so that e.g. full text search won't
+          index the mailbox twice. this also means that deletion must be
+          careful to delete the symlink, box->name. */
+       old_vname = mailbox_alias_find_new(list->ns->user, vname);
+       if (old_vname != NULL &&
+           mailbox_symlink_exists(list, vname, &existence) == 0 &&
+           existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
+               vname = old_vname;
+       return alist->module_ctx.super.get_storage_name(list, vname);
+ }
+ static int
+ mailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
+                    bool directory)
+ {
+       struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
+       struct mailbox_alias_mailbox_list *alist =
+               MAILBOX_ALIAS_LIST_CONTEXT(box->list);
+       const char *symlink_name;
+       int ret;
 -      return abox->module_ctx.super.delete(box);
++      ret = abox->module_ctx.super.create_box(box, update, directory);
+       if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
+               return ret;
+       if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
+               return ret;
+       /* all the code so far has actually only created the original
+          mailbox. now we'll create the symlink if it's missing. */
+       symlink_name = alist->module_ctx.super.
+               get_storage_name(box->list, box->vname);
+       return mailbox_alias_create_symlink(box, box->name, symlink_name);
+ }
+ static int mailbox_alias_delete(struct mailbox *box)
+ {
+       struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
+       struct mailbox_alias_mailbox_list *alist =
+               MAILBOX_ALIAS_LIST_CONTEXT(box->list);
+       const char *symlink_name;
+       int ret;
+       ret = mailbox_has_aliases(box->list, box->vname);
+       if (ret < 0)
+               return -1;
+       if (ret > 0) {
+               mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+                       "Can't delete mailbox while it has aliases");
+               return -1;
+       }
+       if (mailbox_is_alias_symlink(box)) {
+               /* we're deleting an alias mailbox. we'll need to handle this
+                  explicitly since box->name points to the original mailbox */
+               symlink_name = alist->module_ctx.super.
+                       get_storage_name(box->list, box->vname);
+               if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
+                       mail_storage_copy_list_error(box->storage, box->list);
+                       return -1;
+               }
+               return 0;
+       }
 -static int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest,
 -                              bool rename_children)
++      return abox->module_ctx.super.delete_box(box);
+ }
 -      return abox->module_ctx.super.rename(src, dest, rename_children);
++static int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest)
+ {
+       struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
+       int ret;
+       if (mailbox_is_alias_symlink(src)) {
+               mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
+                                      "Can't rename alias mailboxes");
+               return -1;
+       }
+       if (mailbox_is_alias_symlink(dest)) {
+               mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
+                                      "Can't rename to mailbox alias");
+               return -1;
+       }
+       ret = mailbox_has_aliases(src->list, src->vname);
+       if (ret < 0)
+               return -1;
+       if (ret > 0) {
+               mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
+                       "Can't rename mailbox while it has aliases");
+               return -1;
+       }
 -      v->create = mailbox_alias_create;
 -      v->delete = mailbox_alias_delete;
 -      v->rename = mailbox_alias_rename;
++      return abox->module_ctx.super.rename_box(src, dest);
+ }
+ static void mailbox_alias_mail_user_created(struct mail_user *user)
+ {
+       struct mail_user_vfuncs *v = user->vlast;
+       struct mailbox_alias_user *auser;
+       struct mailbox_alias *alias;
+       string_t *oldkey, *newkey;
+       const char *old_vname, *new_vname;
+       unsigned int i;
+       auser = p_new(user->pool, struct mailbox_alias_user, 1);
+       auser->module_ctx.super = *v;
+       user->vlast = &auser->module_ctx.super;
+       p_array_init(&auser->aliases, user->pool, 8);
+       oldkey = t_str_new(32);
+       newkey = t_str_new(32);
+       str_append(oldkey, "mailbox_alias_old");
+       str_append(newkey, "mailbox_alias_new");
+       for (i = 2;; i++) {
+               old_vname = mail_user_plugin_getenv(user, str_c(oldkey));
+               new_vname = mail_user_plugin_getenv(user, str_c(newkey));
+               if (old_vname == NULL || new_vname == NULL)
+                       break;
+               alias = array_append_space(&auser->aliases);
+               alias->old_vname = old_vname;
+               alias->new_vname = new_vname;
+               str_truncate(oldkey, 0);
+               str_truncate(newkey, 0);
+               str_printfa(oldkey, "mailbox_alias_old%u", i);
+               str_printfa(newkey, "mailbox_alias_new%u", i);
+       }
+       MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
+ }
+ static void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
+ {
+       struct mailbox_list_vfuncs *v = list->vlast;
+       struct mailbox_alias_mailbox_list *alist;
+       alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
+       alist->module_ctx.super = *v;
+       list->vlast = &alist->module_ctx.super;
+       v->get_storage_name = mailbox_alias_get_storage_name;
+       MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
+ }
+ static void mailbox_alias_mailbox_allocated(struct mailbox *box)
+ {
+       struct mailbox_vfuncs *v = box->vlast;
+       struct mailbox_alias_mailbox *abox;
+       abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
+       abox->module_ctx.super = *v;
+       box->vlast = &abox->module_ctx.super;
++      v->create_box = mailbox_alias_create;
++      v->delete_box = mailbox_alias_delete;
++      v->rename_box = mailbox_alias_rename;
+       MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
+ }
+ static struct mail_storage_hooks mailbox_alias_mail_storage_hooks = {
+       .mail_user_created = mailbox_alias_mail_user_created,
+       .mailbox_list_created = mailbox_alias_mailbox_list_created,
+       .mailbox_allocated = mailbox_alias_mailbox_allocated
+ };
+ void mailbox_alias_plugin_init(struct module *module)
+ {
+       mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);
+ }
+ void mailbox_alias_plugin_deinit(void)
+ {
+       mail_storage_hooks_remove(&mailbox_alias_mail_storage_hooks);
+ }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge