1 #ifndef INDEX_MAIL_H
2 #define INDEX_MAIL_H
3 
4 #include "message-size.h"
5 #include "mail-cache.h"
6 #include "mail-storage-private.h"
7 
8 enum index_cache_field {
9 	/* fixed size fields */
10 	MAIL_CACHE_FLAGS = 0,
11 	MAIL_CACHE_SENT_DATE,
12 	MAIL_CACHE_RECEIVED_DATE,
13 	MAIL_CACHE_SAVE_DATE,
14 	MAIL_CACHE_VIRTUAL_FULL_SIZE,
15 	MAIL_CACHE_PHYSICAL_FULL_SIZE,
16 
17 	/* variable sized field */
18 	MAIL_CACHE_IMAP_BODY,
19 	MAIL_CACHE_IMAP_BODYSTRUCTURE,
20 	MAIL_CACHE_IMAP_ENVELOPE,
21 	MAIL_CACHE_POP3_UIDL,
22 	MAIL_CACHE_POP3_ORDER,
23 	MAIL_CACHE_GUID,
24 	MAIL_CACHE_MESSAGE_PARTS,
25 	MAIL_CACHE_BINARY_PARTS,
26 	MAIL_CACHE_BODY_SNIPPET,
27 
28 	MAIL_INDEX_CACHE_FIELD_COUNT
29 };
30 extern struct mail_cache_field
31 	global_cache_fields[MAIL_INDEX_CACHE_FIELD_COUNT];
32 
33 #define IMAP_BODY_PLAIN_7BIT_ASCII \
34 	"\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\""
35 
36 enum mail_cache_record_flag {
37 	/* If binary flags are set, it's not checked whether mail is
38 	   missing CRs. So this flag may be set as an optimization for
39 	   regular non-binary mails as well if it's known that it contains
40 	   valid CR+LF line breaks. */
41 	MAIL_CACHE_FLAG_BINARY_HEADER		= 0x0001,
42 	MAIL_CACHE_FLAG_BINARY_BODY		= 0x0002,
43 
44 	/* Mail header or body is known to contain NUL characters. */
45 	MAIL_CACHE_FLAG_HAS_NULS		= 0x0004,
46 	/* Mail header or body is known to not contain NUL characters. */
47 	MAIL_CACHE_FLAG_HAS_NO_NULS		= 0x0020,
48 	/* obsolete _HAS_NO_NULS flag, which was being set incorrectly */
49 	MAIL_CACHE_FLAG_HAS_NO_NULS_BROKEN	= 0x0008,
50 
51 	/* BODY is IMAP_BODY_PLAIN_7BIT_ASCII and rest of BODYSTRUCTURE
52 	   fields are NIL */
53 	MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII	= 0x0010
54 };
55 
56 enum index_mail_access_part {
57 	READ_HDR	= 0x01,
58 	READ_BODY	= 0x02,
59 	PARSE_HDR	= 0x04,
60 	PARSE_BODY	= 0x08
61 };
62 
63 struct mail_sent_date {
64 	uint32_t time;
65 	int32_t timezone;
66 };
67 
68 struct index_mail_line {
69 	unsigned int field_idx;
70 	uint32_t start_pos, end_pos;
71 	uint32_t line_num;
72 };
73 
74 struct message_header_line;
75 
76 struct index_mail_data {
77 	time_t date, received_date, save_date;
78 	uoff_t virtual_size, physical_size;
79 
80 	struct mail_sent_date sent_date;
81 	struct index_mail_line parse_line;
82 	uint32_t parse_line_num;
83 
84 	struct message_part *parts;
85 	struct message_binary_part *bin_parts;
86 	const char *envelope, *body, *bodystructure, *guid, *filename;
87 	const char *from_envelope, *body_snippet;
88 	struct message_part_envelope *envelope_data;
89 
90 	uint32_t seq;
91 	uint32_t cache_flags;
92 	uint64_t modseq, pvt_modseq;
93 	enum index_mail_access_part access_part;
94 	/* dont_cache_fields overrides cache_fields */
95 	enum mail_fetch_field cache_fetch_fields, dont_cache_fetch_fields;
96 	unsigned int dont_cache_field_idx;
97 	enum mail_fetch_field wanted_fields;
98 	struct mailbox_header_lookup_ctx *wanted_headers;
99 
100 	buffer_t *search_results;
101 
102 	struct istream *stream, *filter_stream;
103 	struct tee_istream *tee_stream;
104 	struct message_size hdr_size, body_size;
105 	struct istream *parser_input;
106 	struct message_parser_ctx *parser_ctx;
107 	int parsing_count;
108 	ARRAY_TYPE(keywords) keywords;
109 	ARRAY_TYPE(keyword_indexes) keyword_indexes;
110 
111 	bool initialized:1;
112 	bool save_sent_date:1;
113 	bool sent_date_parsed:1;
114 	bool save_envelope:1;
115 	bool save_bodystructure_header:1;
116 	bool save_bodystructure_body:1;
117 	bool save_message_parts:1;
118 	bool save_body_snippet:1;
119 	bool stream_has_only_header:1;
120 	bool parsed_bodystructure:1;
121 	bool parsed_bodystructure_header:1;
122 	bool hdr_size_set:1;
123 	bool body_size_set:1;
124 	bool messageparts_saved_to_cache:1;
125 	bool header_parsed:1;
126 	bool no_caching:1;
127 	bool forced_no_caching:1;
128 	bool istream_error_logged:1;
129 	bool destroying_stream:1;
130 	bool initialized_wrapper_stream:1;
131 	bool destroy_callback_set:1;
132 	bool prefetch_sent:1;
133 	bool header_parser_initialized:1;
134 	/* virtual_size and physical_size may not match the stream size.
135 	   Try to avoid trusting them too much. */
136 	bool inexact_total_sizes:1;
137 };
138 
139 struct index_mail {
140         struct mail_private mail;
141 	struct index_mail_data data;
142 	struct index_mailbox_context *ibox;
143 
144 	int pop3_state;
145 
146 	/* per-mail variables, here for performance reasons: */
147 	uint32_t header_seq;
148 	string_t *header_data;
149 	ARRAY(struct index_mail_line) header_lines;
150 #define HEADER_MATCH_FLAG_FOUND 1
151 #define HEADER_MATCH_SKIP_COUNT 2
152 #define HEADER_MATCH_USABLE(mail, num) \
153 	((num & ~1U) == (mail)->header_match_value)
154 	ARRAY(uint8_t) header_match;
155 	ARRAY(unsigned int) header_match_lines;
156 	uint8_t header_match_value;
157 
158 	bool pop3_state_set:1;
159 	/* close() is being called from mail_free() */
160 	bool freeing:1;
161 };
162 
163 #define INDEX_MAIL(s)	container_of(s, struct index_mail, mail.mail)
164 
165 struct mail *
166 index_mail_alloc(struct mailbox_transaction_context *t,
167 		 enum mail_fetch_field wanted_fields,
168 		 struct mailbox_header_lookup_ctx *wanted_headers);
169 void index_mail_init(struct index_mail *mail,
170 		     struct mailbox_transaction_context *_t,
171 		     enum mail_fetch_field wanted_fields,
172 		     struct mailbox_header_lookup_ctx *_wanted_headers,
173 		     struct pool *mail_pool,
174 		     struct pool *data_pool);
175 
176 void index_mail_set_seq(struct mail *mail, uint32_t seq, bool saving);
177 bool index_mail_set_uid(struct mail *mail, uint32_t uid);
178 void index_mail_set_uid_cache_updates(struct mail *mail, bool set);
179 bool index_mail_prefetch(struct mail *mail);
180 void index_mail_add_temp_wanted_fields(struct mail *mail,
181 				       enum mail_fetch_field fields,
182 				       struct mailbox_header_lookup_ctx *headers);
183 void index_mail_update_access_parts_pre(struct mail *mail);
184 void index_mail_update_access_parts_post(struct mail *_mail);
185 void index_mail_close(struct mail *mail);
186 void index_mail_close_streams(struct index_mail *mail);
187 void index_mail_free(struct mail *mail);
188 void index_mail_set_message_parts_corrupted(struct mail *mail, const char *error);
189 
190 bool index_mail_want_parse_headers(struct index_mail *mail);
191 void index_mail_parse_header_init(struct index_mail *mail,
192 				  struct mailbox_header_lookup_ctx *headers)
193 	ATTR_NULL(2);
194 void index_mail_parse_header(struct message_part *part,
195 			     struct message_header_line *hdr,
196 			     struct index_mail *mail) ATTR_NULL(1);
197 int index_mail_parse_headers(struct index_mail *mail,
198 			     struct mailbox_header_lookup_ctx *headers,
199 			     const char *reason)
200 	ATTR_NULL(2);
201 void index_mail_parse_header_deinit(struct index_mail *mail);
202 /* Same as index_mail_parse_headers(), but assume that the stream is
203    already opened. */
204 int index_mail_parse_headers_internal(struct index_mail *mail,
205 				      struct mailbox_header_lookup_ctx *headers)
206 	ATTR_NULL(2);
207 int index_mail_headers_get_envelope(struct index_mail *mail);
208 
209 int index_mail_get_first_header(struct mail *_mail, const char *field,
210 				bool decode_to_utf8, const char **value_r);
211 int index_mail_get_headers(struct mail *_mail, const char *field,
212 			   bool decode_to_utf8, const char *const **value_r);
213 int index_mail_get_header_stream(struct mail *_mail,
214 				 struct mailbox_header_lookup_ctx *headers,
215 				 struct istream **stream_r);
216 void index_mail_set_read_buffer_size(struct mail *mail, struct istream *input);
217 
218 enum mail_flags index_mail_get_flags(struct mail *_mail);
219 uint64_t index_mail_get_modseq(struct mail *_mail);
220 uint64_t index_mail_get_pvt_modseq(struct mail *_mail);
221 const char *const *index_mail_get_keywords(struct mail *_mail);
222 const ARRAY_TYPE(keyword_indexes) *
223 index_mail_get_keyword_indexes(struct mail *_mail);
224 int index_mail_get_parts(struct mail *_mail, struct message_part **parts_r);
225 int index_mail_get_received_date(struct mail *_mail, time_t *date_r);
226 int index_mail_get_save_date(struct mail *_mail, time_t *date_r);
227 int index_mail_get_date(struct mail *_mail, time_t *date_r, int *timezone_r);
228 int index_mail_get_virtual_size(struct mail *mail, uoff_t *size_r);
229 int index_mail_get_physical_size(struct mail *mail, uoff_t *size_r);
230 int index_mail_init_stream(struct index_mail *mail,
231 			   struct message_size *hdr_size,
232 			   struct message_size *body_size,
233 			   struct istream **stream_r) ATTR_NULL(2, 3);
234 int index_mail_get_binary_stream(struct mail *_mail,
235 				 const struct message_part *part,
236 				 bool include_hdr, uoff_t *size_r,
237 				 unsigned int *body_lines_r, bool *binary_r,
238 				 struct istream **stream_r);
239 int index_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
240 			   const char **value_r);
241 int index_mail_get_backend_mail(struct mail *mail, struct mail **real_mail_r);
242 
243 void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
244 			     enum mail_flags flags);
245 void index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
246 				struct mail_keywords *keywords);
247 void index_mail_update_modseq(struct mail *mail, uint64_t min_modseq);
248 void index_mail_update_pvt_modseq(struct mail *mail, uint64_t min_pvt_modseq);
249 void index_mail_expunge(struct mail *mail);
250 int index_mail_precache(struct mail *mail);
251 void index_mail_set_cache_corrupted(struct mail *mail,
252 				    enum mail_fetch_field field,
253 				    const char *reason);
254 int index_mail_opened(struct mail *mail, struct istream **stream);
255 int index_mail_stream_check_failure(struct index_mail *mail);
256 void index_mail_stream_log_failure_for(struct index_mail *mail,
257 				       struct istream *input);
258 void index_mail_refresh_expunged(struct mail *mail);
259 struct index_mail *index_mail_get_index_mail(struct mail *mail);
260 
261 bool index_mail_get_cached_uoff_t(struct index_mail *mail,
262 				  enum index_cache_field field, uoff_t *size_r);
263 bool index_mail_get_cached_virtual_size(struct index_mail *mail,
264 					uoff_t *size_r);
265 bool index_mail_get_cached_body(struct index_mail *mail, const char **value_r);
266 bool index_mail_get_cached_bodystructure(struct index_mail *mail,
267 					 const char **value_r);
268 const uint32_t *index_mail_get_vsize_extension(struct mail *_mail);
269 
270 bool index_mail_want_cache(struct index_mail *mail, enum index_cache_field field);
271 void index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
272 			  const void *data, size_t data_size);
273 void index_mail_cache_add_idx(struct index_mail *mail, unsigned int field_idx,
274 			      const void *data, size_t data_size);
275 
276 void index_mail_cache_pop3_data(struct mail *_mail,
277 				const char *uidl, uint32_t order);
278 
279 struct istream *index_mail_cache_parse_init(struct mail *mail,
280 					    struct istream *input);
281 void index_mail_cache_parse_continue(struct mail *mail);
282 void index_mail_cache_parse_deinit(struct mail *mail, time_t received_date,
283 				   bool success);
284 
285 int index_mail_cache_lookup_field(struct index_mail *mail, buffer_t *buf,
286 				  unsigned int field_idx);
287 void index_mail_save_finish(struct mail_save_context *ctx);
288 
289 const char *index_mail_cache_reason(struct mail *mail, const char *reason);
290 
291 #endif
292