1 #ifndef MAIL_NAMESPACE_H
2 #define MAIL_NAMESPACE_H
3 
4 #include "mail-user.h"
5 
6 struct mail_storage_callbacks;
7 
8 enum mail_namespace_type {
9 	MAIL_NAMESPACE_TYPE_PRIVATE	= 0x01,
10 	MAIL_NAMESPACE_TYPE_SHARED	= 0x02,
11 	MAIL_NAMESPACE_TYPE_PUBLIC	= 0x04
12 #define MAIL_NAMESPACE_TYPE_MASK_ALL \
13 	(MAIL_NAMESPACE_TYPE_PRIVATE | MAIL_NAMESPACE_TYPE_SHARED | \
14 	 MAIL_NAMESPACE_TYPE_PUBLIC)
15 };
16 
17 enum namespace_flags {
18 	/* Namespace contains the user's INBOX mailbox. Normally only a single
19 	   namespace has this flag set, but when using alias_for for the INBOX
20 	   namespace the flag gets copied to the alias namespace as well */
21 	NAMESPACE_FLAG_INBOX_USER	= 0x01,
22 	/* Namespace contains someone's INBOX. This is set for both user's
23 	   INBOX namespace and also for any other users' shared namespaces. */
24 	NAMESPACE_FLAG_INBOX_ANY	= 0x02,
25 	/* Namespace is visible only by explicitly using its full prefix */
26 	NAMESPACE_FLAG_HIDDEN		= 0x04,
27 	/* Namespace prefix is visible with LIST */
28 	NAMESPACE_FLAG_LIST_PREFIX	= 0x08,
29 	/* Namespace prefix isn't visible with LIST, but child mailboxes are */
30 	NAMESPACE_FLAG_LIST_CHILDREN	= 0x10,
31 	/* Namespace uses its own subscriptions. */
32 	NAMESPACE_FLAG_SUBSCRIPTIONS	= 0x20,
33 
34 	/* Namespace was created automatically (for shared mailboxes) */
35 	NAMESPACE_FLAG_AUTOCREATED	= 0x1000,
36 	/* Namespace has at least some usable mailboxes. Autocreated namespaces
37 	   that don't have usable mailboxes may be removed automatically. */
38 	NAMESPACE_FLAG_USABLE		= 0x2000,
39 	/* Automatically created namespace for a user that doesn't exist. */
40 	NAMESPACE_FLAG_UNUSABLE		= 0x4000,
41 	/* Don't track quota for this namespace */
42 	NAMESPACE_FLAG_NOQUOTA		= 0x8000,
43 	/* Don't enforce ACLs for this namespace */
44 	NAMESPACE_FLAG_NOACL		= 0x10000
45 };
46 
47 struct mail_namespace {
48 	/* Namespaces are sorted by their prefix length, "" comes first */
49 	struct mail_namespace *next;
50 	int refcount;
51 
52         enum mail_namespace_type type;
53 	enum namespace_flags flags;
54 
55 	char *prefix;
56 	size_t prefix_len;
57 
58 	/* If non-NULL, this points to a namespace with identical mail location
59 	   and it should be considered as the primary way to access the
60 	   mailboxes. This allows for example FTS plugin to avoid duplicating
61 	   indexes for same mailboxes when they're accessed via different
62 	   namespaces. */
63 	struct mail_namespace *alias_for;
64 	/* alias_for->alias_chain_next starts each chain. The chain goes
65 	   through all namespaces that have the same alias_for. */
66 	struct mail_namespace *alias_chain_next;
67 
68 	struct mail_user *user, *owner;
69 	struct mailbox_list *list;
70 	struct mail_storage *storage; /* default storage */
71 	ARRAY(struct mail_storage *) all_storages;
72 
73 	/* This may point to user->set, but it may also point to
74 	   namespace-specific settings. When accessing namespace-specific
75 	   settings it should be done through here instead of through the
76 	   mail_user. */
77 	struct mail_user_settings *user_set;
78 
79 	const struct mail_namespace_settings *set, *unexpanded_set;
80 	const struct mail_storage_settings *mail_set;
81 
82 	bool special_use_mailboxes:1;
83 	bool destroyed:1;
84 };
85 
86 /* Returns TRUE when namespace can be removed without consequence. */
mail_namespace_is_removable(const struct mail_namespace * ns)87 static inline bool mail_namespace_is_removable(const struct mail_namespace *ns)
88 {
89 	return ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
90 		(ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0);
91 }
92 
93 /* Allocate a new namespace, and fill it based on the passed in settings.
94    This is the most low-level namespace creation function. The storage isn't
95    initialized for the namespace.
96 
97    user_all_settings normally points to user->set. If you want to override
98    settings for the created namespace, you can duplicate the user's settings
99    and provide a pointer to it here. Note that the pointer must contain
100    ALL the settings, including the dynamic driver-specific settings, so it
101    needs to created via settings-parser API. */
102 int mail_namespace_alloc(struct mail_user *user,
103 			 void *user_all_settings,
104 			 struct mail_namespace_settings *ns_set,
105 			 struct mail_namespace_settings *unexpanded_set,
106 			 struct mail_namespace **ns_r,
107 			 const char **error_r);
108 
109 /* Add and initialize namespaces to user based on namespace settings. */
110 int mail_namespaces_init(struct mail_user *user, const char **error_r);
111 /* Add and initialize INBOX namespace to user based on the given location. */
112 int mail_namespaces_init_location(struct mail_user *user, const char *location,
113 				  const char **error_r) ATTR_NULL(2);
114 /* Add an empty namespace to user. */
115 struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user);
116 /* Deinitialize all namespaces. mail_user_deinit() calls this automatically
117    for user's namespaces. */
118 void mail_namespaces_deinit(struct mail_namespace **namespaces);
119 
120 /* Allocate a new namespace and initialize it. This is called automatically by
121    mail_namespaces_init(). */
122 int mail_namespaces_init_add(struct mail_user *user,
123 			     struct mail_namespace_settings *ns_set,
124 			     struct mail_namespace_settings *unexpanded_ns_set,
125 			     struct mail_namespace **ns_p, const char **error_r);
126 int mail_namespaces_init_finish(struct mail_namespace *namespaces,
127 				const char **error_r);
128 
129 void mail_namespace_ref(struct mail_namespace *ns);
130 void mail_namespace_unref(struct mail_namespace **ns);
131 
132 /* Set storage callback functions to use in all namespaces. */
133 void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces,
134 					   struct mail_storage_callbacks *callbacks,
135 					   void *context);
136 
137 /* Add a new storage to namespace. */
138 void mail_namespace_add_storage(struct mail_namespace *ns,
139 				struct mail_storage *storage);
140 /* Destroy a single namespace and remove it from user's namespaces list. */
141 void mail_namespace_destroy(struct mail_namespace *ns);
142 
143 /* Returns the default storage to use for newly created mailboxes. */
144 struct mail_storage *
145 mail_namespace_get_default_storage(struct mail_namespace *ns);
146 
147 /* Return namespace's hierarchy separator. */
148 char mail_namespace_get_sep(struct mail_namespace *ns);
149 /* Returns the hierarchy separator for mailboxes that are listed at root. */
150 char mail_namespaces_get_root_sep(struct mail_namespace *namespaces)
151 	ATTR_PURE;
152 
153 /* Returns namespace based on the mailbox name's prefix. Note that there is
154    always a prefix="" namespace, so for this function NULL is never returned. */
155 struct mail_namespace *
156 mail_namespace_find(struct mail_namespace *namespaces, const char *mailbox);
157 /* Same as mail_namespace_find(), but if the namespace has alias_for set,
158    return that namespace instead and change mailbox name to be a valid
159    inside it. */
160 struct mail_namespace *
161 mail_namespace_find_unalias(struct mail_namespace *namespaces,
162 			    const char **mailbox);
163 
164 /* Like mail_namespace_find(), but ignore hidden namespaces. */
165 struct mail_namespace *
166 mail_namespace_find_visible(struct mail_namespace *namespaces,
167 			    const char *mailbox);
168 /* Like mail_namespace_find(), but find only from namespaces with
169    subscriptions=yes. */
170 struct mail_namespace *
171 mail_namespace_find_subscribable(struct mail_namespace *namespaces,
172 				 const char *mailbox);
173 /* Like mail_namespace_find(), but find only from namespaces with
174    subscriptions=no. */
175 struct mail_namespace *
176 mail_namespace_find_unsubscribable(struct mail_namespace *namespaces,
177 				   const char *mailbox);
178 /* Returns the INBOX namespace. It always exists, so NULL is never returned. */
179 struct mail_namespace *
180 mail_namespace_find_inbox(struct mail_namespace *namespaces);
181 /* Find a namespace with given prefix. */
182 struct mail_namespace *
183 mail_namespace_find_prefix(struct mail_namespace *namespaces,
184 			   const char *prefix);
185 /* Like _find_prefix(), but ignore trailing separator */
186 struct mail_namespace *
187 mail_namespace_find_prefix_nosep(struct mail_namespace *namespaces,
188 				 const char *prefix);
189 
190 /* Called internally by mailbox_list_create(). */
191 void mail_namespace_finish_list_init(struct mail_namespace *ns,
192 				     struct mailbox_list *list);
193 
194 /* Returns TRUE if this is the root of a type=shared namespace that is actually
195    used for accessing shared users' mailboxes (as opposed to marking a
196    type=public namespace "wrong"). */
197 bool mail_namespace_is_shared_user_root(struct mail_namespace *ns);
198 
199 /* Returns TRUE if namespace includes INBOX that should be \Noinferiors.
200    This happens when the namespace has a prefix, which is not empty and not
201    "INBOX". This happens, because if storage_name=INBOX/foo it would be
202    converted to vname=prefix/INBOX/foo. */
203 static inline bool
mail_namespace_is_inbox_noinferiors(struct mail_namespace * ns)204 mail_namespace_is_inbox_noinferiors(struct mail_namespace *ns)
205 {
206 	return (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
207 		ns->prefix_len > 0 &&
208 		strncmp(ns->prefix, "INBOX", ns->prefix_len-1) != 0;
209 }
210 
211 /* Returns TRUE if namespace prefix is INBOX. */
212 static inline bool
mail_namespace_prefix_is_inbox(struct mail_namespace * ns)213 mail_namespace_prefix_is_inbox(struct mail_namespace *ns)
214 {
215 	return (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
216 	       (ns->prefix_len == 6) &&
217 	       (strncasecmp(ns->prefix, "INBOX", 5) == 0) &&
218 	       (ns->prefix[5] == mail_namespace_get_sep(ns));
219 }
220 
221 #endif
222