diff options
Diffstat (limited to 'src/lib-storage/mail-namespace.h')
-rw-r--r-- | src/lib-storage/mail-namespace.h | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/lib-storage/mail-namespace.h b/src/lib-storage/mail-namespace.h new file mode 100644 index 0000000..ae54f59 --- /dev/null +++ b/src/lib-storage/mail-namespace.h @@ -0,0 +1,221 @@ +#ifndef MAIL_NAMESPACE_H +#define MAIL_NAMESPACE_H + +#include "mail-user.h" + +struct mail_storage_callbacks; + +enum mail_namespace_type { + MAIL_NAMESPACE_TYPE_PRIVATE = 0x01, + MAIL_NAMESPACE_TYPE_SHARED = 0x02, + MAIL_NAMESPACE_TYPE_PUBLIC = 0x04 +#define MAIL_NAMESPACE_TYPE_MASK_ALL \ + (MAIL_NAMESPACE_TYPE_PRIVATE | MAIL_NAMESPACE_TYPE_SHARED | \ + MAIL_NAMESPACE_TYPE_PUBLIC) +}; + +enum namespace_flags { + /* Namespace contains the user's INBOX mailbox. Normally only a single + namespace has this flag set, but when using alias_for for the INBOX + namespace the flag gets copied to the alias namespace as well */ + NAMESPACE_FLAG_INBOX_USER = 0x01, + /* Namespace contains someone's INBOX. This is set for both user's + INBOX namespace and also for any other users' shared namespaces. */ + NAMESPACE_FLAG_INBOX_ANY = 0x02, + /* Namespace is visible only by explicitly using its full prefix */ + NAMESPACE_FLAG_HIDDEN = 0x04, + /* Namespace prefix is visible with LIST */ + NAMESPACE_FLAG_LIST_PREFIX = 0x08, + /* Namespace prefix isn't visible with LIST, but child mailboxes are */ + NAMESPACE_FLAG_LIST_CHILDREN = 0x10, + /* Namespace uses its own subscriptions. */ + NAMESPACE_FLAG_SUBSCRIPTIONS = 0x20, + + /* Namespace was created automatically (for shared mailboxes) */ + NAMESPACE_FLAG_AUTOCREATED = 0x1000, + /* Namespace has at least some usable mailboxes. Autocreated namespaces + that don't have usable mailboxes may be removed automatically. */ + NAMESPACE_FLAG_USABLE = 0x2000, + /* Automatically created namespace for a user that doesn't exist. */ + NAMESPACE_FLAG_UNUSABLE = 0x4000, + /* Don't track quota for this namespace */ + NAMESPACE_FLAG_NOQUOTA = 0x8000, + /* Don't enforce ACLs for this namespace */ + NAMESPACE_FLAG_NOACL = 0x10000 +}; + +struct mail_namespace { + /* Namespaces are sorted by their prefix length, "" comes first */ + struct mail_namespace *next; + int refcount; + + enum mail_namespace_type type; + enum namespace_flags flags; + + char *prefix; + size_t prefix_len; + + /* If non-NULL, this points to a namespace with identical mail location + and it should be considered as the primary way to access the + mailboxes. This allows for example FTS plugin to avoid duplicating + indexes for same mailboxes when they're accessed via different + namespaces. */ + struct mail_namespace *alias_for; + /* alias_for->alias_chain_next starts each chain. The chain goes + through all namespaces that have the same alias_for. */ + struct mail_namespace *alias_chain_next; + + struct mail_user *user, *owner; + struct mailbox_list *list; + struct mail_storage *storage; /* default storage */ + ARRAY(struct mail_storage *) all_storages; + + /* This may point to user->set, but it may also point to + namespace-specific settings. When accessing namespace-specific + settings it should be done through here instead of through the + mail_user. */ + struct mail_user_settings *user_set; + + const struct mail_namespace_settings *set, *unexpanded_set; + const struct mail_storage_settings *mail_set; + + bool special_use_mailboxes:1; + bool destroyed:1; +}; + +/* Returns TRUE when namespace can be removed without consequence. */ +static inline bool mail_namespace_is_removable(const struct mail_namespace *ns) +{ + return ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 && + (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0); +} + +/* Allocate a new namespace, and fill it based on the passed in settings. + This is the most low-level namespace creation function. The storage isn't + initialized for the namespace. + + user_all_settings normally points to user->set. If you want to override + settings for the created namespace, you can duplicate the user's settings + and provide a pointer to it here. Note that the pointer must contain + ALL the settings, including the dynamic driver-specific settings, so it + needs to created via settings-parser API. */ +int mail_namespace_alloc(struct mail_user *user, + void *user_all_settings, + struct mail_namespace_settings *ns_set, + struct mail_namespace_settings *unexpanded_set, + struct mail_namespace **ns_r, + const char **error_r); + +/* Add and initialize namespaces to user based on namespace settings. */ +int mail_namespaces_init(struct mail_user *user, const char **error_r); +/* Add and initialize INBOX namespace to user based on the given location. */ +int mail_namespaces_init_location(struct mail_user *user, const char *location, + const char **error_r) ATTR_NULL(2); +/* Add an empty namespace to user. */ +struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user); +/* Deinitialize all namespaces. mail_user_deinit() calls this automatically + for user's namespaces. */ +void mail_namespaces_deinit(struct mail_namespace **namespaces); + +/* Allocate a new namespace and initialize it. This is called automatically by + mail_namespaces_init(). */ +int mail_namespaces_init_add(struct mail_user *user, + struct mail_namespace_settings *ns_set, + struct mail_namespace_settings *unexpanded_ns_set, + struct mail_namespace **ns_p, const char **error_r); +int mail_namespaces_init_finish(struct mail_namespace *namespaces, + const char **error_r); + +void mail_namespace_ref(struct mail_namespace *ns); +void mail_namespace_unref(struct mail_namespace **ns); + +/* Set storage callback functions to use in all namespaces. */ +void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces, + struct mail_storage_callbacks *callbacks, + void *context); + +/* Add a new storage to namespace. */ +void mail_namespace_add_storage(struct mail_namespace *ns, + struct mail_storage *storage); +/* Destroy a single namespace and remove it from user's namespaces list. */ +void mail_namespace_destroy(struct mail_namespace *ns); + +/* Returns the default storage to use for newly created mailboxes. */ +struct mail_storage * +mail_namespace_get_default_storage(struct mail_namespace *ns); + +/* Return namespace's hierarchy separator. */ +char mail_namespace_get_sep(struct mail_namespace *ns); +/* Returns the hierarchy separator for mailboxes that are listed at root. */ +char mail_namespaces_get_root_sep(struct mail_namespace *namespaces) + ATTR_PURE; + +/* Returns namespace based on the mailbox name's prefix. Note that there is + always a prefix="" namespace, so for this function NULL is never returned. */ +struct mail_namespace * +mail_namespace_find(struct mail_namespace *namespaces, const char *mailbox); +/* Same as mail_namespace_find(), but if the namespace has alias_for set, + return that namespace instead and change mailbox name to be a valid + inside it. */ +struct mail_namespace * +mail_namespace_find_unalias(struct mail_namespace *namespaces, + const char **mailbox); + +/* Like mail_namespace_find(), but ignore hidden namespaces. */ +struct mail_namespace * +mail_namespace_find_visible(struct mail_namespace *namespaces, + const char *mailbox); +/* Like mail_namespace_find(), but find only from namespaces with + subscriptions=yes. */ +struct mail_namespace * +mail_namespace_find_subscribable(struct mail_namespace *namespaces, + const char *mailbox); +/* Like mail_namespace_find(), but find only from namespaces with + subscriptions=no. */ +struct mail_namespace * +mail_namespace_find_unsubscribable(struct mail_namespace *namespaces, + const char *mailbox); +/* Returns the INBOX namespace. It always exists, so NULL is never returned. */ +struct mail_namespace * +mail_namespace_find_inbox(struct mail_namespace *namespaces); +/* Find a namespace with given prefix. */ +struct mail_namespace * +mail_namespace_find_prefix(struct mail_namespace *namespaces, + const char *prefix); +/* Like _find_prefix(), but ignore trailing separator */ +struct mail_namespace * +mail_namespace_find_prefix_nosep(struct mail_namespace *namespaces, + const char *prefix); + +/* Called internally by mailbox_list_create(). */ +void mail_namespace_finish_list_init(struct mail_namespace *ns, + struct mailbox_list *list); + +/* Returns TRUE if this is the root of a type=shared namespace that is actually + used for accessing shared users' mailboxes (as opposed to marking a + type=public namespace "wrong"). */ +bool mail_namespace_is_shared_user_root(struct mail_namespace *ns); + +/* Returns TRUE if namespace includes INBOX that should be \Noinferiors. + This happens when the namespace has a prefix, which is not empty and not + "INBOX". This happens, because if storage_name=INBOX/foo it would be + converted to vname=prefix/INBOX/foo. */ +static inline bool +mail_namespace_is_inbox_noinferiors(struct mail_namespace *ns) +{ + return (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && + ns->prefix_len > 0 && + strncmp(ns->prefix, "INBOX", ns->prefix_len-1) != 0; +} + +/* Returns TRUE if namespace prefix is INBOX. */ +static inline bool +mail_namespace_prefix_is_inbox(struct mail_namespace *ns) +{ + return (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && + (ns->prefix_len == 6) && + (strncasecmp(ns->prefix, "INBOX", 5) == 0) && + (ns->prefix[5] == mail_namespace_get_sep(ns)); +} + +#endif |