1 /**
2  * @file
3  * API for mx backends
4  *
5  * @authors
6  * Copyright (C) 1996-2000,2010,2013 Michael R. Elkins <me@mutt.org>
7  * Copyright (C) 2018-2019 Richard Russon <rich@flatcap.org>
8  *
9  * @copyright
10  * This program is free software: you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License as published by the Free Software
12  * Foundation, either version 2 of the License, or (at your option) any later
13  * version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef MUTT_CORE_MXAPI_H
25 #define MUTT_CORE_MXAPI_H
26 
27 #include "config.h"
28 #include <stdbool.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include "mailbox.h"
33 
34 struct Account;
35 struct Email;
36 struct stat;
37 
38 /**
39  * struct Message - A local copy of an email
40  */
41 struct Message
42 {
43   FILE *fp;             ///< pointer to the message data
44   char *path;           ///< path to temp file
45   char *committed_path; ///< the final path generated by mx_msg_commit()
46   bool write;           ///< nonzero if message is open for writing
47   struct
48   {
49     bool read : 1;    ///< Message has been read
50     bool flagged : 1; ///< Message is flagged
51     bool replied : 1; ///< Message has been replied to
52     bool draft : 1;   ///< Message has been read
53   } flags;            ///< Flags for the Message
54   time_t received;    ///< Time at which this message was received
55 };
56 
57 
58 /* flags for mutt_open_mailbox() */
59 typedef uint8_t OpenMailboxFlags;   ///< Flags for mutt_open_mailbox(), e.g. #MUTT_NOSORT
60 #define MUTT_OPEN_NO_FLAGS       0  ///< No flags are set
61 #define MUTT_NOSORT        (1 << 0) ///< Do not sort the mailbox after opening it
62 #define MUTT_APPEND        (1 << 1) ///< Open mailbox for appending messages
63 #define MUTT_READONLY      (1 << 2) ///< Open in read-only mode
64 #define MUTT_QUIET         (1 << 3) ///< Do not print any messages
65 #define MUTT_NEWFOLDER     (1 << 4) ///< Create a new folder - same as #MUTT_APPEND,
66                                     ///< but uses mutt_file_fopen() with mode "w" for mbox-style folders.
67                                     ///< This will truncate an existing file.
68 #define MUTT_PEEK          (1 << 5) ///< Revert atime back after taking a look (if applicable)
69 #define MUTT_APPENDNEW     (1 << 6) ///< Set in mx_open_mailbox_append if the mailbox doesn't exist.
70                                     ///< Used by maildir/mh to create the mailbox.
71 /**
72  * enum MxStatus - Return values from mbox_check(), mbox_check_stats(),
73  * mbox_snc(), and mbox_close()
74  */
75 enum MxStatus
76 {
77   MX_STATUS_ERROR = -1, ///< An error occurred
78   MX_STATUS_OK,         ///< No changes
79   MX_STATUS_NEW_MAIL,   ///< New mail received in Mailbox
80   MX_STATUS_LOCKED,     ///< Couldn't lock the Mailbox
81   MX_STATUS_REOPENED,   ///< Mailbox was reopened
82   MX_STATUS_FLAGS,      ///< Nondestructive flags change (IMAP)
83 };
84 
85 /**
86  * enum MxOpenReturns - Return values for mbox_open()
87  */
88 enum MxOpenReturns
89 {
90   MX_OPEN_OK,           ///< Open succeeded
91   MX_OPEN_ERROR,        ///< Open failed with an error
92   MX_OPEN_ABORT,        ///< Open was aborted
93 };
94 
95 /**
96  * @defgroup mx_api Mailbox API
97  *
98  * The Mailbox API
99  *
100  * Each backend provides a set of functions through which the Mailbox, messages,
101  * tags and paths are manipulated.
102  */
103 struct MxOps
104 {
105   enum MailboxType type;  ///< Mailbox type, e.g. #MUTT_IMAP
106   const char *name;       ///< Mailbox name, e.g. "imap"
107   bool is_local;          ///< True, if Mailbox type has local files/dirs
108 
109   /**
110    * @defgroup mx_ac_owns_path ac_owns_path()
111    * @ingroup mx_api
112    *
113    * ac_owns_path - Check whether an Account owns a Mailbox path
114    * @param a    Account
115    * @param path Mailbox Path
116    * @retval true  Account handles path
117    * @retval false Account does not handle path
118    *
119    * **Contract**
120    * - @a a    is not NULL
121    * - @a path is not NULL
122    */
123   bool (*ac_owns_path)(struct Account *a, const char *path);
124 
125   /**
126    * @defgroup mx_ac_add ac_add()
127    * @ingroup mx_api
128    *
129    * ac_add - Add a Mailbox to an Account
130    * @param a Account to add to
131    * @param m Mailbox to add
132    * @retval true  Success
133    * @retval false Error
134    *
135    * **Contract**
136    * - @a a is not NULL
137    * - @a m is not NULL
138    */
139   bool (*ac_add)(struct Account *a, struct Mailbox *m);
140 
141   /**
142    * @defgroup mx_mbox_open mbox_open()
143    * @ingroup mx_api
144    *
145    * mbox_open - Open a Mailbox
146    * @param m Mailbox to open
147    * @retval enum #MxOpenReturns
148    *
149    * **Contract**
150    * - @a m is not NULL
151    */
152   enum MxOpenReturns (*mbox_open)(struct Mailbox *m);
153 
154   /**
155    * @defgroup mx_mbox_open_append mbox_open_append()
156    * @ingroup mx_api
157    *
158    * mbox_open_append - Open a Mailbox for appending
159    * @param m     Mailbox to open
160    * @param flags Flags, see #OpenMailboxFlags
161    * @retval true Success
162    * @retval false Failure
163    *
164    * **Contract**
165    * - @a m is not NULL
166    */
167   bool (*mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags);
168 
169   /**
170    * @defgroup mx_mbox_check mbox_check()
171    * @ingroup mx_api
172    *
173    * mbox_check - Check for new mail
174    * @param m Mailbox
175    * @retval enum #MxStatus
176    *
177    * **Contract**
178    * - @a m is not NULL
179    */
180   enum MxStatus (*mbox_check)(struct Mailbox *m);
181 
182   /**
183    * @defgroup mx_mbox_check_stats mbox_check_stats()
184    * @ingroup mx_api
185    *
186    * mbox_check_stats - Check the Mailbox statistics
187    * @param m     Mailbox to check
188    * @param flags Function flags
189    * @retval enum #MxStatus
190    *
191    * **Contract**
192    * - @a m is not NULL
193    */
194   enum MxStatus (*mbox_check_stats)(struct Mailbox *m, uint8_t flags);
195 
196   /**
197    * @defgroup mx_mbox_sync mbox_sync()
198    * @ingroup mx_api
199    *
200    * mbox_sync - Save changes to the Mailbox
201    * @param m Mailbox to sync
202    * @retval enum #MxStatus
203    *
204    * **Contract**
205    * - @a m is not NULL
206    */
207   enum MxStatus (*mbox_sync)(struct Mailbox *m);
208 
209   /**
210    * @defgroup mx_mbox_close mbox_close()
211    * @ingroup mx_api
212    *
213    * mbox_close - Close a Mailbox
214    * @param m Mailbox to close
215    * @retval enum #MxStatus
216    *
217    * **Contract**
218    * - @a m is not NULL
219    */
220   enum MxStatus (*mbox_close)(struct Mailbox *m);
221 
222   /**
223    * @defgroup mx_msg_open msg_open()
224    * @ingroup mx_api
225    *
226    * msg_open - Open an email message in a Mailbox
227    * @param m     Mailbox
228    * @param msg   Message to open
229    * @param msgno Index of message to open
230    * @retval true Success
231    * @retval false Error
232    *
233    * **Contract**
234    * - @a m   is not NULL
235    * - @a msg is not NULL
236    * - 0 <= @a msgno < msg->msg_count
237    */
238   bool (*msg_open)(struct Mailbox *m, struct Message *msg, int msgno);
239 
240   /**
241    * @defgroup mx_msg_open_new msg_open_new()
242    * @ingroup mx_api
243    *
244    * msg_open_new - Open a new message in a Mailbox
245    * @param m   Mailbox
246    * @param msg Message to open
247    * @param e   Email
248    * @retval true Success
249    * @retval false Failure
250    *
251    * **Contract**
252    * - @a m   is not NULL
253    * - @a msg is not NULL
254    */
255   bool (*msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e);
256 
257   /**
258    * @defgroup mx_msg_commit msg_commit()
259    * @ingroup mx_api
260    *
261    * msg_commit - Save changes to an email
262    * @param m   Mailbox
263    * @param msg Message to commit
264    * @retval  0 Success
265    * @retval -1 Failure
266    *
267    * **Contract**
268    * - @a m   is not NULL
269    * - @a msg is not NULL
270    */
271   int (*msg_commit)      (struct Mailbox *m, struct Message *msg);
272 
273   /**
274    * @defgroup mx_msg_close msg_close()
275    * @ingroup mx_api
276    *
277    * msg_close - Close an email
278    * @param m   Mailbox
279    * @param msg Message to close
280    * @retval  0 Success
281    * @retval -1 Failure
282    *
283    * **Contract**
284    * - @a m   is not NULL
285    * - @a msg is not NULL
286    */
287   int (*msg_close)       (struct Mailbox *m, struct Message *msg);
288 
289   /**
290    * @defgroup mx_msg_padding_size msg_padding_size()
291    * @ingroup mx_api
292    *
293    * msg_padding_size - Bytes of padding between messages
294    * @param m Mailbox
295    * @retval num Bytes of padding
296    *
297    * **Contract**
298    * - @a m is not NULL
299    */
300   int (*msg_padding_size)(struct Mailbox *m);
301 
302   /**
303    * @defgroup mx_msg_save_hcache msg_save_hcache()
304    * @ingroup mx_api
305    *
306    * msg_save_hcache - Save message to the header cache
307    * @param m Mailbox
308    * @param e Email
309    * @retval  0 Success
310    * @retval -1 Failure
311    *
312    * **Contract**
313    * - @a m is not NULL
314    * - @a e is not NULL
315    */
316   int (*msg_save_hcache) (struct Mailbox *m, struct Email *e);
317 
318   /**
319    * @defgroup mx_tags_edit tags_edit()
320    * @ingroup mx_api
321    *
322    * tags_edit - Prompt and validate new messages tags
323    * @param m      Mailbox
324    * @param tags   Existing tags
325    * @param buf    Buffer to store the tags
326    * @param buflen Length of buffer
327    * @retval -1 Error
328    * @retval  0 No valid user input
329    * @retval  1 Buf set
330    *
331    * **Contract**
332    * - @a m   is not NULL
333    * - @a buf is not NULL
334    */
335   int (*tags_edit)       (struct Mailbox *m, const char *tags, char *buf, size_t buflen);
336 
337   /**
338    * @defgroup mx_tags_commit tags_commit()
339    * @ingroup mx_api
340    *
341    * tags_commit - Save the tags to a message
342    * @param m Mailbox
343    * @param e Email
344    * @param buf Buffer containing tags
345    * @retval  0 Success
346    * @retval -1 Failure
347    *
348    * **Contract**
349    * - @a m   is not NULL
350    * - @a e   is not NULL
351    * - @a buf is not NULL
352    */
353   int (*tags_commit)     (struct Mailbox *m, struct Email *e, char *buf);
354 
355   /**
356    * @defgroup mx_path_probe path_probe()
357    * @ingroup mx_api
358    *
359    * path_probe - Does this Mailbox type recognise this path?
360    * @param path Path to examine
361    * @param st   stat buffer (for local filesystems)
362    * @retval num Type, e.g. #MUTT_IMAP
363    *
364    * **Contract**
365    * - @a path is not NULL
366    */
367   enum MailboxType (*path_probe)(const char *path, const struct stat *st);
368 
369   /**
370    * @defgroup mx_path_canon path_canon()
371    * @ingroup mx_api
372    *
373    * path_canon - Canonicalise a Mailbox path
374    * @param buf    Path to modify
375    * @param buflen Length of buffer
376    * @retval  0 Success
377    * @retval -1 Failure
378    *
379    * **Contract**
380    * - @a buf is not NULL
381    */
382   int (*path_canon)      (char *buf, size_t buflen);
383 
384   /**
385    * @defgroup mx_path_pretty path_pretty()
386    * @ingroup mx_api
387    *
388    * path_pretty - Abbreviate a Mailbox path
389    * @param buf    Path to modify
390    * @param buflen Length of buffer
391    * @param folder Base path for '=' substitution
392    * @retval  0 Success
393    * @retval -1 Failure
394    *
395    * **Contract**
396    * - @a buf is not NULL
397    */
398   int (*path_pretty)     (char *buf, size_t buflen, const char *folder);
399 
400   /**
401    * @defgroup mx_path_parent path_parent()
402    * @ingroup mx_api
403    *
404    * path_parent - Find the parent of a Mailbox path
405    * @param buf    Path to modify
406    * @param buflen Length of buffer
407    * @retval  0 Success
408    * @retval -1 Failure
409    *
410    * **Contract**
411    * - @a buf is not NULL
412    */
413   int (*path_parent)     (char *buf, size_t buflen);
414 
415   /**
416    * @defgroup mx_path_is_empty path_is_empty()
417    * @ingroup mx_api
418    *
419    * path_is_empty - Is the Mailbox empty?
420    * @param path Mailbox to check
421    * @retval 1 Mailbox is empty
422    * @retval 0 Mailbox contains mail
423    * @retval -1 Error
424    *
425    * **Contract**
426    * - @a path is not NULL and not empty
427    */
428   int (*path_is_empty)     (const char *path);
429 };
430 
431 #endif /* MUTT_CORE_MXAPI_H */
432 
433