1 #ifndef MAILBOX_LIST_H
2 #define MAILBOX_LIST_H
3 
4 #include "mail-error.h"
5 
6 #ifdef PATH_MAX
7 #  define MAILBOX_LIST_NAME_MAX_LENGTH PATH_MAX
8 #else
9 #  define MAILBOX_LIST_NAME_MAX_LENGTH 4096
10 #endif
11 
12 struct fs;
13 struct mail_namespace;
14 struct mail_storage;
15 struct mailbox_list;
16 
17 enum mailbox_list_properties {
18 	/* maildir_name must always be empty */
19 	MAILBOX_LIST_PROP_NO_MAILDIR_NAME	= 0x01,
20 	/* alt directories not supported */
21 	MAILBOX_LIST_PROP_NO_ALT_DIR		= 0x02,
22 	/* no support for \noselect directories, only mailboxes */
23 	MAILBOX_LIST_PROP_NO_NOSELECT		= 0x04,
24 	/* mail root directory isn't required */
25 	MAILBOX_LIST_PROP_NO_ROOT		= 0x08,
26 	/* Automatically create mailbox directories when needed. Normally it's
27 	   assumed that if a mailbox directory doesn't exist, the mailbox
28 	   doesn't exist either. */
29 	MAILBOX_LIST_PROP_AUTOCREATE_DIRS	= 0x10,
30 	/* Explicitly disable mailbox list index */
31 	MAILBOX_LIST_PROP_NO_LIST_INDEX		= 0x20,
32 	/* Disable checking mailbox_list.is_internal_name(). The layout is
33 	   implemented in a way that there aren't any such reserved internal
34 	   names. For example Maildir++ prefixes all mailboxes with "." */
35 	MAILBOX_LIST_PROP_NO_INTERNAL_NAMES	= 0x40,
36 };
37 
38 enum mailbox_list_flags {
39 	/* Mailboxes are files, not directories. */
40 	MAILBOX_LIST_FLAG_MAILBOX_FILES		= 0x01,
41 	/* Namespace already has a mailbox list, don't assign this
42 	   mailbox list to it. */
43 	MAILBOX_LIST_FLAG_SECONDARY		= 0x02,
44 	/* There are no mail files, only index and/or control files. */
45 	MAILBOX_LIST_FLAG_NO_MAIL_FILES		= 0x04,
46 	/* LAYOUT=index: Don't delete any files in delete_mailbox(). */
47 	MAILBOX_LIST_FLAG_NO_DELETES		= 0x08
48 };
49 
50 enum mailbox_info_flags {
51 	MAILBOX_NOSELECT		= 0x001,
52 	MAILBOX_NONEXISTENT		= 0x002,
53 	MAILBOX_CHILDREN		= 0x004,
54 	MAILBOX_NOCHILDREN		= 0x008,
55 	MAILBOX_NOINFERIORS		= 0x010,
56 	MAILBOX_MARKED			= 0x020,
57 	MAILBOX_UNMARKED		= 0x040,
58 	MAILBOX_SUBSCRIBED		= 0x080,
59 	MAILBOX_CHILD_SUBSCRIBED	= 0x100,
60 	MAILBOX_CHILD_SPECIALUSE	= 0x200,
61 
62 	/* Internally used by lib-storage, use mailbox_info.special_use
63 	   to actually access these: */
64 	MAILBOX_SPECIALUSE_ALL		= 0x00010000,
65 	MAILBOX_SPECIALUSE_ARCHIVE	= 0x00020000,
66 	MAILBOX_SPECIALUSE_DRAFTS	= 0x00040000,
67 	MAILBOX_SPECIALUSE_FLAGGED	= 0x00080000,
68 	MAILBOX_SPECIALUSE_JUNK		= 0x00100000,
69 	MAILBOX_SPECIALUSE_SENT		= 0x00200000,
70 	MAILBOX_SPECIALUSE_TRASH	= 0x00400000,
71 	MAILBOX_SPECIALUSE_IMPORTANT	= 0x00800000,
72 #define MAILBOX_SPECIALUSE_MASK		  0x00ff0000
73 
74 	/* Internally used by lib-storage: */
75 	MAILBOX_SELECT			= 0x20000000,
76 	MAILBOX_MATCHED			= 0x40000000
77 };
78 
79 enum mailbox_list_path_type {
80 	/* Return directory's path (eg. ~/dbox/INBOX) */
81 	MAILBOX_LIST_PATH_TYPE_DIR,
82 	MAILBOX_LIST_PATH_TYPE_ALT_DIR,
83 	/* Return mailbox path (eg. ~/dbox/INBOX/dbox-Mails) */
84 	MAILBOX_LIST_PATH_TYPE_MAILBOX,
85 	MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
86 	/* Return control directory */
87 	MAILBOX_LIST_PATH_TYPE_CONTROL,
88 	/* Return index directory ("" for in-memory) */
89 	MAILBOX_LIST_PATH_TYPE_INDEX,
90 	/* Return the private index directory (NULL if none) */
91 	MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
92 	/* Return the index cache directory (usually same as
93 	   MAILBOX_LIST_PATH_TYPE_INDEX) */
94 	MAILBOX_LIST_PATH_TYPE_INDEX_CACHE,
95 	/* Return mailbox list index directory (usually same as
96 	   MAILBOX_LIST_PATH_TYPE_INDEX) */
97 	MAILBOX_LIST_PATH_TYPE_LIST_INDEX,
98 };
99 
100 enum mailbox_list_file_type {
101 	MAILBOX_LIST_FILE_TYPE_UNKNOWN = 0,
102 	MAILBOX_LIST_FILE_TYPE_FILE,
103 	MAILBOX_LIST_FILE_TYPE_DIR,
104 	MAILBOX_LIST_FILE_TYPE_SYMLINK,
105 	MAILBOX_LIST_FILE_TYPE_OTHER
106 };
107 
108 struct mailbox_list_settings {
109 	const char *layout; /* FIXME: shouldn't be here */
110 	const char *root_dir;
111 	const char *index_dir;
112 	const char *index_pvt_dir;
113 	const char *index_cache_dir;
114 	const char *control_dir;
115 	const char *alt_dir; /* FIXME: dbox-specific.. */
116 	/* Backend-local directory where volatile data, such as lock files,
117 	   can be temporarily created. This setting allows specifying a
118 	   separate directory for them to reduce disk I/O on the real storage.
119 	   The volatile_dir can point to an in-memory filesystem. */
120 	const char *volatile_dir;
121 
122 	const char *inbox_path;
123 	const char *subscription_fname;
124 	const char *list_index_fname;
125 	/* Mailbox list index directory. NULL defaults to index directory.
126 	   The path may be relative to the index directory. */
127 	const char *list_index_dir;
128 	/* If non-empty, it means that mails exist in a maildir_name
129 	   subdirectory. eg. if you have a directory containing directories:
130 
131 	   mail/
132 	   mail/foo/
133 	   mail/foo/Maildir
134 
135 	   If mailbox_name is empty, you have mailboxes "mail", "mail/foo" and
136 	   "mail/foo/Maildir".
137 
138 	   If mailbox_name is "Maildir", you have a non-selectable mailbox
139 	   "mail" and a selectable mailbox "mail/foo". */
140 	const char *maildir_name;
141 	/* if set, store mailboxes under root_dir/mailbox_dir_name/.
142 	   this setting contains either "" or "dir/". */
143 	const char *mailbox_dir_name;
144 
145 	/* Used for escaping the mailbox name in storage (storage_name). If the
146 	   UTF-8 vname has characters that can't reversibly (or safely) be
147 	   converted to storage_name and back, encode the problematic parts
148 	   using <storage_name_escape_char><hex>. The storage_name_escape_char
149 	   itself also has to be encoded the same way. For example
150 	   { vname="A/B.C%D", storage_name_escape_char='%', namespace_sep='/',
151 	   storage_sep='.' } -> storage_name="A.B%2eC%25D". */
152 	char storage_name_escape_char;
153 	/* Used for escaping the user/client-visible UTF-8 vname. If the
154 	   storage_name can't be converted reversibly to the vname and back,
155 	   encode the problematic parts using <vname_escape_char><hex>. The
156 	   vname_escape_char itself also has to be encoded the same way. For
157 	   example { storage_name="A/B.C%D", vname_escape_char='%',
158 	   namespace_sep='/', storage_sep='.' } -> vname="A%2fB/C%25D".
159 
160 	   Note that it's possible for escape_char and broken_char to be the
161 	   same character. They're just used for different directions in
162 	   conversion. */
163 	char vname_escape_char;
164 	/* Use UTF-8 mailbox names on filesystem instead of mUTF-7 */
165 	bool utf8;
166 	/* Don't check/create the alt-dir symlink. */
167 	bool alt_dir_nocheck;
168 	/* Use maildir_name also for index/control directories. This should
169 	   have been the default since the beginning, but for backwards
170 	   compatibility it had to be made an option. */
171 	bool index_control_use_maildir_name;
172 	/* Perform mailbox iteration using the index directory instead of the
173 	   mail root directory. This can be helpful if the indexes are on a
174 	   faster storage. This could perhaps be made the default at some point,
175 	   but for now since it's less tested it's optional. */
176 	bool iter_from_index_dir;
177 	/* Avoid creating or listing \NoSelect mailboxes. */
178 	bool no_noselect;
179 	/* Do not validate names as fs names (allows weird names) */
180 	bool no_fs_validation;
181 };
182 
183 struct mailbox_permissions {
184 	/* The actual uid/gid of the mailbox */
185 	uid_t file_uid;
186 	gid_t file_gid;
187 
188 	/* mode and GID to use for newly created files/dirs.
189 	   (gid_t)-1 is used if the default GID can be used. */
190 	mode_t file_create_mode, dir_create_mode;
191 	gid_t file_create_gid;
192 	/* origin (e.g. path) where the file_create_gid was got from */
193 	const char *file_create_gid_origin;
194 
195 	bool gid_origin_is_mailbox_path;
196 	bool mail_index_permissions_set;
197 };
198 
199 /* register all drivers */
200 void mailbox_list_register_all(void);
201 
202 void mailbox_list_register(const struct mailbox_list *list);
203 void mailbox_list_unregister(const struct mailbox_list *list);
204 
205 const struct mailbox_list *
206 mailbox_list_find_class(const char *driver);
207 
208 /* Returns 0 if ok, -1 if driver was unknown. */
209 int mailbox_list_create(const char *driver, struct mail_namespace *ns,
210 			const struct mailbox_list_settings *set,
211 			enum mailbox_list_flags flags,
212 			struct mailbox_list **list_r, const char **error_r);
213 void mailbox_list_destroy(struct mailbox_list **list);
214 
215 const char *
216 mailbox_list_get_driver_name(const struct mailbox_list *list) ATTR_PURE;
217 const struct mailbox_list_settings *
218 mailbox_list_get_settings(const struct mailbox_list *list) ATTR_PURE;
219 enum mailbox_list_flags
220 mailbox_list_get_flags(const struct mailbox_list *list) ATTR_PURE;
221 struct mail_namespace *
222 mailbox_list_get_namespace(const struct mailbox_list *list) ATTR_PURE;
223 struct mail_user *
224 mailbox_list_get_user(const struct mailbox_list *list) ATTR_PURE;
225 int mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
226 			     struct mail_storage **storage_r);
227 void mailbox_list_get_default_storage(struct mailbox_list *list,
228 				      struct mail_storage **storage);
229 char mailbox_list_get_hierarchy_sep(struct mailbox_list *list);
230 
231 /* Returns the mode and GID that should be used when creating new files and
232    directories to the specified mailbox. (gid_t)-1 is returned if it's not
233    necessary to change the default gid. */
234 void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
235 				  struct mailbox_permissions *permissions_r);
236 /* Like mailbox_list_get_permissions(), but for creating files/dirs to the
237    mail root directory (or even the root dir itself). */
238 void mailbox_list_get_root_permissions(struct mailbox_list *list,
239 				       struct mailbox_permissions *permissions_r);
240 /* mkdir() a root directory of given type with proper permissions. The path can
241    be either the root itself or point to a directory under the root. */
242 int mailbox_list_mkdir_root(struct mailbox_list *list, const char *path,
243 			    enum mailbox_list_path_type type);
244 /* Like mailbox_list_mkdir_root(), but don't log an error if it fails. */
245 int mailbox_list_try_mkdir_root(struct mailbox_list *list, const char *path,
246 				enum mailbox_list_path_type type,
247 				const char **error_r);
248 /* Call mailbox_list_mkdir_root() for index, unless the index root is the
249    same as mailbox root. Returns 1 if ok, 0 if there are no indexes, -1 if
250    error. Calling this multiple times does the check only once. */
251 int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list);
252 /* Like mailbox_list_mkdir_missing_index_root(), but for mailbox list
253    index root. */
254 int mailbox_list_mkdir_missing_list_index_root(struct mailbox_list *list);
255 
256 /* Returns TRUE if name is ok, FALSE if it can't be safely passed to
257    mailbox_list_*() functions */
258 bool mailbox_list_is_valid_name(struct mailbox_list *list,
259 				const char *name, const char **error_r);
260 
261 const char *mailbox_list_get_storage_name(struct mailbox_list *list,
262 					  const char *vname);
263 const char *mailbox_list_get_vname(struct mailbox_list *list, const char *name);
264 
265 /* Get path to specified type of files in mailbox. Returns -1 if an error
266    occurred (e.g. mailbox no longer exists), 0 if there are no files of this
267    type (in-memory index, no alt dir, storage with no files), 1 if path was
268    returned successfully. The path is set to NULL when returning -1/0. */
269 int mailbox_list_get_path(struct mailbox_list *list, const char *name,
270 			  enum mailbox_list_path_type type,
271 			  const char **path_r);
272 /* Get path to the root directory for files of specified type. Returns TRUE
273    if path was returned, FALSE if there are no files of this type. */
274 bool mailbox_list_get_root_path(struct mailbox_list *list,
275 				enum mailbox_list_path_type type,
276 				const char **path_r);
277 /* Like mailbox_list_get_root_path(), but assume that the root directory
278    exists (assert crash if not) */
279 const char *mailbox_list_get_root_forced(struct mailbox_list *list,
280 					 enum mailbox_list_path_type type);
281 /* Returns mailbox's change log, or NULL if it doesn't have one. */
282 struct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list);
283 /* Specify timestamp to use when writing mailbox changes to changelog.
284    The same timestamp is used until stamp is set to (time_t)-1, after which
285    current time is used */
286 void mailbox_list_set_changelog_timestamp(struct mailbox_list *list,
287 					  time_t stamp);
288 
289 /* Returns a prefix that temporary files should use without conflicting
290    with the namespace. */
291 const char *mailbox_list_get_temp_prefix(struct mailbox_list *list);
292 /* Returns prefix that's common to all get_temp_prefix() calls.
293    Typically this returns either "temp." or ".temp.". */
294 const char *mailbox_list_get_global_temp_prefix(struct mailbox_list *list);
295 
296 /* Subscribe/unsubscribe mailbox. There should be no error when
297    subscribing to already subscribed mailbox. Subscribing to
298    unexisting mailboxes is optional. */
299 int mailbox_list_set_subscribed(struct mailbox_list *list,
300 				const char *name, bool set);
301 
302 /* Delete a non-selectable mailbox. Fail if the mailbox is selectable. */
303 int mailbox_list_delete_dir(struct mailbox_list *list, const char *name);
304 /* Delete a symlinked mailbox. Fail if the mailbox isn't a symlink. */
305 int mailbox_list_delete_symlink(struct mailbox_list *list, const char *name);
306 
307 /* Returns the error message of last occurred error. */
308 const char * ATTR_NOWARN_UNUSED_RESULT
309 mailbox_list_get_last_error(struct mailbox_list *list,
310 			    enum mail_error *error_r);
311 /* Wrapper for mailbox_list_get_last_error() */
312 enum mail_error mailbox_list_get_last_mail_error(struct mailbox_list *list);
313 
314 const char * ATTR_NOWARN_UNUSED_RESULT
315 mailbox_list_get_last_internal_error(struct mailbox_list *list,
316 				     enum mail_error *error_r);
317 
318 /* Save the last error until it's popped. This is useful for cases where the
319    list operation has already failed, but the cleanup code path changes the
320    error to something else unwanted. */
321 void mailbox_list_last_error_push(struct mailbox_list *list);
322 void mailbox_list_last_error_pop(struct mailbox_list *list);
323 
324 /* Create a fs based on the settings in the given mailbox_list. If event_parent
325    is NULL, use user->event as the parent. */
326 int mailbox_list_init_fs(struct mailbox_list *list, struct event *event_parent,
327 			 const char *driver,
328 			 const char *args, const char *root_dir,
329 			 struct fs **fs_r, const char **error_r);
330 /* Return mailbox_list that was used to create the fs via
331    mailbox_list_init_fs(). */
332 struct mailbox_list *mailbox_list_fs_get_list(struct fs *fs);
333 
334 /* Escape/Unescape mailbox name in place. */
335 void mailbox_list_name_unescape(const char **name, char escape_char);
336 void mailbox_list_name_escape(const char *name, const char *escape_chars,
337 			      string_t *dest);
338 
339 #endif
340