1 #ifndef IMAPC_STORAGE_H
2 #define IMAPC_STORAGE_H
3 
4 #include "index-storage.h"
5 #include "imapc-settings.h"
6 #include "imapc-client.h"
7 
8 #define IMAPC_STORAGE_NAME "imapc"
9 /* storage_name separator */
10 #define IMAPC_LIST_STORAGE_NAME_ESCAPE_CHAR '%'
11 /* fs_name separator */
12 #define IMAPC_LIST_FS_NAME_ESCAPE_CHAR '%'
13 /* vname separator */
14 #define IMAPC_LIST_VNAME_ESCAPE_CHAR '~'
15 
16 struct imap_arg;
17 struct imapc_untagged_reply;
18 struct imapc_command_reply;
19 struct imapc_mailbox;
20 struct imapc_storage_client;
21 
22 typedef void imapc_storage_callback_t(const struct imapc_untagged_reply *reply,
23 				      struct imapc_storage_client *client);
24 typedef void imapc_mailbox_callback_t(const struct imapc_untagged_reply *reply,
25 				      struct imapc_mailbox *mbox);
26 
27 struct imapc_storage_event_callback {
28 	char *name;
29 	imapc_storage_callback_t *callback;
30 };
31 
32 struct imapc_mailbox_event_callback {
33 	const char *name;
34 	imapc_mailbox_callback_t *callback;
35 };
36 
37 #define IMAPC_HAS_FEATURE(mstorage, feature) \
38 	(((mstorage)->set->parsed_features & feature) != 0)
39 #define IMAPC_BOX_HAS_FEATURE(mbox, feature) \
40 	(((mbox)->storage->set->parsed_features & feature) != 0)
41 
42 struct imapc_namespace {
43 	const char *prefix;
44 	char separator;
45 	enum mail_namespace_type type;
46 };
47 
48 struct imapc_storage_client {
49 	int refcount;
50 
51 	/* either one of these may not be available: */
52 	struct imapc_storage *_storage;
53 	struct imapc_mailbox_list *_list;
54 
55 	struct imapc_client *client;
56 
57 	ARRAY(struct imapc_storage_event_callback) untagged_callbacks;
58 
59 	/* IMAPC_COMMAND_STATE_OK if no auth failure (yet), otherwise result to
60 	   the LOGIN/AUTHENTICATE command. */
61 	enum imapc_command_state auth_failed_state;
62 	char *auth_failed_reason;
63 
64 	/* Authentication reply was received (success or failure) */
65 	bool auth_returned:1;
66 	bool destroying:1;
67 };
68 
69 struct imapc_storage {
70 	struct mail_storage storage;
71 	const struct imapc_settings *set;
72 
73 	struct ioloop *root_ioloop;
74 	struct imapc_storage_client *client;
75 
76 	struct imapc_mailbox *cur_status_box;
77 	struct mailbox_status *cur_status;
78 	unsigned int reopen_count;
79 
80 	ARRAY(struct imapc_namespace) remote_namespaces;
81 
82 	bool namespaces_requested:1;
83 };
84 
85 struct imapc_mail_cache {
86 	uint32_t uid;
87 
88 	/* either fd != -1 or buf != NULL */
89 	int fd;
90 	buffer_t *buf;
91 };
92 
93 struct imapc_fetch_request {
94 	ARRAY(struct imapc_mail *) mails;
95 };
96 
97 struct imapc_mailbox {
98 	struct mailbox box;
99 	struct imapc_storage *storage;
100 	struct imapc_client_mailbox *client_box;
101 	enum imapc_capability capabilities;
102 
103 	struct mail_index_transaction *delayed_sync_trans;
104 	struct mail_index_view *sync_view, *delayed_sync_view;
105 	struct mail_cache_view *delayed_sync_cache_view;
106 	struct mail_cache_transaction_ctx *delayed_sync_cache_trans;
107 	struct timeout *to_idle_check, *to_idle_delay;
108 
109 	ARRAY(struct imapc_fetch_request *) fetch_requests;
110 	/* if non-empty, contains the latest FETCH command we're going to be
111 	   sending soon (but still waiting to see if we can increase its
112 	   UID range) */
113 	string_t *pending_fetch_cmd;
114 	struct imapc_fetch_request *pending_fetch_request;
115 	struct timeout *to_pending_fetch_send;
116 
117 	ARRAY(struct imapc_mailbox_event_callback) untagged_callbacks;
118 	ARRAY(struct imapc_mailbox_event_callback) resp_text_callbacks;
119 
120 	enum mail_flags permanent_flags;
121 	uint32_t highest_nonrecent_uid;
122 
123 	ARRAY(uint64_t) rseq_modseqs;
124 	ARRAY_TYPE(seq_range) delayed_expunged_uids;
125 	uint32_t sync_uid_validity;
126 	uint32_t sync_uid_next;
127 	uint64_t sync_highestmodseq;
128 	uint32_t sync_fetch_first_uid;
129 	uint32_t sync_next_lseq;
130 	uint32_t sync_next_rseq;
131 	uint32_t exists_count;
132 	uint32_t min_append_uid;
133 	char *sync_gmail_pop3_search_tag;
134 
135 	/* keep the previous fetched message body cached,
136 	   mainly for partial IMAP fetches */
137 	struct imapc_mail_cache prev_mail_cache;
138 
139 	uint32_t prev_skipped_rseq, prev_skipped_uid;
140 	struct imapc_sync_context *sync_ctx;
141 
142 	const char *guid_fetch_field_name;
143 	struct imapc_search_context *search_ctx;
144 
145 	bool selecting:1;
146 	bool syncing:1;
147 	bool initial_sync_done:1;
148 	bool selected:1;
149 	bool exists_received:1;
150 	bool state_fetching_uid1:1;
151 	bool state_fetched_success:1;
152 };
153 
154 struct imapc_simple_context {
155 	struct imapc_storage_client *client;
156 	int ret;
157 };
158 
159 #define IMAPC_STORAGE(s)	container_of(s, struct imapc_storage, storage)
160 #define IMAPC_MAILBOX(s)	container_of(s, struct imapc_mailbox, box)
161 
162 int imapc_storage_client_create(struct mail_namespace *ns,
163 				const struct imapc_settings *imapc_set,
164 				const struct mail_storage_settings *mail_set,
165 				struct imapc_storage_client **client_r,
166 				const char **error_r);
167 void imapc_storage_client_unref(struct imapc_storage_client **client);
168 bool imapc_storage_client_handle_auth_failure(struct imapc_storage_client *client);
169 
170 struct mail_save_context *
171 imapc_save_alloc(struct mailbox_transaction_context *_t);
172 int imapc_save_begin(struct mail_save_context *ctx, struct istream *input);
173 int imapc_save_continue(struct mail_save_context *ctx);
174 int imapc_save_finish(struct mail_save_context *ctx);
175 void imapc_save_cancel(struct mail_save_context *ctx);
176 int imapc_copy(struct mail_save_context *ctx, struct mail *mail);
177 
178 int imapc_transaction_save_commit_pre(struct mail_save_context *ctx);
179 void imapc_transaction_save_commit_post(struct mail_save_context *ctx,
180 					struct mail_index_transaction_commit_result *result);
181 void imapc_transaction_save_rollback(struct mail_save_context *ctx);
182 
183 void imapc_mailbox_run(struct imapc_mailbox *mbox);
184 void imapc_mailbox_run_nofetch(struct imapc_mailbox *mbox);
185 void imapc_mail_cache_free(struct imapc_mail_cache *cache);
186 int imapc_mailbox_select(struct imapc_mailbox *mbox);
187 void imap_mailbox_select_finish(struct imapc_mailbox *mbox);
188 
189 bool imapc_mailbox_has_modseqs(struct imapc_mailbox *mbox);
190 bool imapc_resp_text_code_parse(const char *str, enum mail_error *error_r);
191 bool imapc_mail_error_to_resp_text_code(enum mail_error error, const char **str_r);
192 void imapc_copy_error_from_reply(struct imapc_storage *storage,
193 				 enum mail_error default_error,
194 				 const struct imapc_command_reply *reply);
195 void imapc_simple_context_init(struct imapc_simple_context *sctx,
196 			       struct imapc_storage_client *client);
197 void imapc_simple_run(struct imapc_simple_context *sctx,
198 		      struct imapc_command **cmd);
199 void imapc_simple_callback(const struct imapc_command_reply *reply,
200 			   void *context);
201 int imapc_mailbox_commit_delayed_trans(struct imapc_mailbox *mbox,
202 				       bool force, bool *changes_r);
203 bool imapc_mailbox_name_equals(struct imapc_mailbox *mbox,
204 			       const char *remote_name);
205 void imapc_mailbox_noop(struct imapc_mailbox *mbox);
206 void imapc_mailbox_set_corrupted(struct imapc_mailbox *mbox,
207 				 const char *reason, ...) ATTR_FORMAT(2, 3);
208 const char *imapc_mailbox_get_remote_name(struct imapc_mailbox *mbox);
209 
210 void imapc_storage_client_register_untagged(struct imapc_storage_client *client,
211 					    const char *name,
212 					    imapc_storage_callback_t *callback);
213 void imapc_storage_client_unregister_untagged(struct imapc_storage_client *client,
214 					      const char *name);
215 void imapc_mailbox_register_untagged(struct imapc_mailbox *mbox,
216 				     const char *name,
217 				     imapc_mailbox_callback_t *callback);
218 void imapc_mailbox_register_resp_text(struct imapc_mailbox *mbox,
219 				      const char *key,
220 				      imapc_mailbox_callback_t *callback);
221 
222 void imapc_mailbox_register_callbacks(struct imapc_mailbox *mbox);
223 
224 #endif
225