1 /*
2  * LibSylph -- E-Mail client library
3  * Copyright (C) 1999-2013 Hiroyuki Yamamoto
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #ifndef __PROCMSG_H__
21 #define __PROCMSG_H__
22 
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26 
27 #include <glib.h>
28 #include <stdio.h>
29 #include <time.h>
30 #include <sys/types.h>
31 #include <string.h>
32 
33 typedef struct _MsgInfo		MsgInfo;
34 typedef struct _MsgFlags	MsgFlags;
35 typedef struct _MsgFileInfo	MsgFileInfo;
36 typedef struct _MsgEncryptInfo	MsgEncryptInfo;
37 
38 #include "folder.h"
39 #include "procmime.h"
40 #include "utils.h"
41 
42 typedef enum
43 {
44 	DATA_READ,
45 	DATA_WRITE,
46 	DATA_APPEND
47 } DataOpenMode;
48 
49 #define MSG_NEW			(1U << 0)
50 #define MSG_UNREAD		(1U << 1)
51 #define MSG_MARKED		(1U << 2)
52 #define MSG_DELETED		(1U << 3)
53 #define MSG_REPLIED		(1U << 4)
54 #define MSG_FORWARDED		(1U << 5)
55 
56 #define MSG_CLABEL_SBIT	(7)		/* start bit of color label */
57 #define MAKE_MSG_CLABEL(h, m, l)	(((h) << (MSG_CLABEL_SBIT + 2)) | \
58 					 ((m) << (MSG_CLABEL_SBIT + 1)) | \
59 					 ((l) << (MSG_CLABEL_SBIT + 0)))
60 
61 #define MSG_CLABEL_NONE		MAKE_MSG_CLABEL(0U, 0U, 0U)
62 #define MSG_CLABEL_1		MAKE_MSG_CLABEL(0U, 0U, 1U)
63 #define MSG_CLABEL_2		MAKE_MSG_CLABEL(0U, 1U, 0U)
64 #define MSG_CLABEL_3		MAKE_MSG_CLABEL(0U, 1U, 1U)
65 #define MSG_CLABEL_4		MAKE_MSG_CLABEL(1U, 0U, 0U)
66 #define MSG_CLABEL_5		MAKE_MSG_CLABEL(1U, 0U, 1U)
67 #define MSG_CLABEL_6		MAKE_MSG_CLABEL(1U, 1U, 0U)
68 #define MSG_CLABEL_7		MAKE_MSG_CLABEL(1U, 1U, 1U)
69 
70 #define MSG_CLABEL_ORANGE	MSG_CLABEL_1
71 #define MSG_CLABEL_RED		MSG_CLABEL_2
72 #define MSG_CLABEL_PINK		MSG_CLABEL_3
73 #define MSG_CLABEL_SKYBLUE	MSG_CLABEL_4
74 #define MSG_CLABEL_BLUE		MSG_CLABEL_5
75 #define MSG_CLABEL_GREEN	MSG_CLABEL_6
76 #define MSG_CLABEL_BROWN	MSG_CLABEL_7
77 
78 /* RESERVED */
79 #define	MSG_RESERVED		(1U << 31)
80 
81 #define MSG_CLABEL_FLAG_MASK	(MSG_CLABEL_7)
82 
83 typedef guint32 MsgPermFlags;
84 
85 #define MSG_MOVE		(1U << 0)
86 #define MSG_COPY		(1U << 1)
87 #define MSG_QUEUED		(1U << 16)
88 #define MSG_DRAFT		(1U << 17)
89 #define MSG_ENCRYPTED		(1U << 18)
90 #define MSG_IMAP		(1U << 19)
91 #define MSG_NEWS		(1U << 20)
92 #define MSG_SIGNED		(1U << 21)
93 #define MSG_MIME_HTML		(1U << 26)
94 #define MSG_FLAG_CHANGED	(1U << 27)
95 #define MSG_CACHED		(1U << 28)
96 #define MSG_MIME		(1U << 29)
97 #define MSG_INVALID		(1U << 30)
98 #define MSG_RECEIVED		(1U << 31)
99 
100 #define MSG_CACHED_FLAG_MASK	(MSG_MIME|MSG_MIME_HTML)
101 
102 typedef guint32 MsgTmpFlags;
103 
104 #define MSG_SET_FLAGS(msg, flags)	{ (msg) |= (flags); }
105 #define MSG_UNSET_FLAGS(msg, flags)	{ (msg) &= ~(flags); }
106 #define MSG_SET_PERM_FLAGS(msg, flags) \
107 	MSG_SET_FLAGS((msg).perm_flags, flags)
108 #define MSG_SET_TMP_FLAGS(msg, flags) \
109 	MSG_SET_FLAGS((msg).tmp_flags, flags)
110 #define MSG_UNSET_PERM_FLAGS(msg, flags) \
111 	MSG_UNSET_FLAGS((msg).perm_flags, flags)
112 #define MSG_UNSET_TMP_FLAGS(msg, flags) \
113 	MSG_UNSET_FLAGS((msg).tmp_flags, flags)
114 
115 #define MSG_IS_NEW(msg)			(((msg).perm_flags & MSG_NEW) != 0)
116 #define MSG_IS_UNREAD(msg)		(((msg).perm_flags & MSG_UNREAD) != 0)
117 #define MSG_IS_MARKED(msg)		(((msg).perm_flags & MSG_MARKED) != 0)
118 #define MSG_IS_DELETED(msg)		(((msg).perm_flags & MSG_DELETED) != 0)
119 #define MSG_IS_REPLIED(msg)		(((msg).perm_flags & MSG_REPLIED) != 0)
120 #define MSG_IS_FORWARDED(msg)		(((msg).perm_flags & MSG_FORWARDED) != 0)
121 
122 #define MSG_GET_COLORLABEL(msg)		(((msg).perm_flags & MSG_CLABEL_FLAG_MASK))
123 #define MSG_GET_COLORLABEL_VALUE(msg)	(MSG_GET_COLORLABEL(msg) >> MSG_CLABEL_SBIT)
124 #define MSG_SET_COLORLABEL_VALUE(msg, val) \
125 	MSG_SET_PERM_FLAGS(msg, ((((guint)(val)) & 7) << MSG_CLABEL_SBIT))
126 
127 #define MSG_IS_MOVE(msg)		(((msg).tmp_flags & MSG_MOVE) != 0)
128 #define MSG_IS_COPY(msg)		(((msg).tmp_flags & MSG_COPY) != 0)
129 
130 #define MSG_IS_QUEUED(msg)		(((msg).tmp_flags & MSG_QUEUED) != 0)
131 #define MSG_IS_DRAFT(msg)		(((msg).tmp_flags & MSG_DRAFT) != 0)
132 #define MSG_IS_ENCRYPTED(msg)		(((msg).tmp_flags & MSG_ENCRYPTED) != 0)
133 #define MSG_IS_IMAP(msg)		(((msg).tmp_flags & MSG_IMAP) != 0)
134 #define MSG_IS_NEWS(msg)		(((msg).tmp_flags & MSG_NEWS) != 0)
135 #define MSG_IS_SIGNED(msg)		(((msg).tmp_flags & MSG_SIGNED) != 0)
136 #define MSG_IS_MIME_HTML(msg)		(((msg).tmp_flags & MSG_MIME_HTML) != 0)
137 #define MSG_IS_FLAG_CHANGED(msg)	(((msg).tmp_flags & MSG_FLAG_CHANGED) != 0)
138 #define MSG_IS_CACHED(msg)		(((msg).tmp_flags & MSG_CACHED) != 0)
139 #define MSG_IS_MIME(msg)		(((msg).tmp_flags & MSG_MIME) != 0)
140 #define MSG_IS_INVALID(msg)		(((msg).tmp_flags & MSG_INVALID) != 0)
141 #define MSG_IS_RECEIVED(msg)		(((msg).tmp_flags & MSG_RECEIVED) != 0)
142 
143 #define WRITE_CACHE_DATA_INT(n, fp)		\
144 {						\
145 	guint32 idata;				\
146 						\
147 	idata = (guint32)n;			\
148 	fwrite(&idata, sizeof(idata), 1, fp);	\
149 }
150 
151 #define WRITE_CACHE_DATA(data, fp)			\
152 {							\
153 	size_t len;					\
154 							\
155 	if (data == NULL) {				\
156 		len = 0;				\
157 		WRITE_CACHE_DATA_INT(len, fp);		\
158 	} else {					\
159 		len = strlen(data);			\
160 		WRITE_CACHE_DATA_INT(len, fp);		\
161 		if (len > 0)				\
162 			fwrite(data, len, 1, fp);	\
163 	}						\
164 }
165 
166 struct _MsgFlags
167 {
168 	MsgPermFlags perm_flags;
169 	MsgTmpFlags  tmp_flags;
170 };
171 
172 struct _MsgInfo
173 {
174 	guint  msgnum;
175 	gsize  size;
176 	stime_t mtime;
177 	stime_t date_t;
178 
179 	MsgFlags flags;
180 
181 	gchar *fromname;
182 
183 	gchar *date;
184 	gchar *from;
185 	gchar *to;
186 	gchar *cc;
187 	gchar *newsgroups;
188 	gchar *subject;
189 	gchar *msgid;
190 	gchar *inreplyto;
191 
192 	GSList *references;
193 
194 	FolderItem *folder;
195 	FolderItem *to_folder;
196 
197 	gchar *xface;
198 
199 	/* used only for temporary messages */
200 	gchar *file_path;
201 
202 	/* used only for encrypted (and signed) messages */
203 	MsgEncryptInfo *encinfo;
204 };
205 
206 struct _MsgFileInfo
207 {
208 	gchar *file;
209 	MsgFlags *flags;
210 };
211 
212 struct _MsgEncryptInfo
213 {
214 	gchar *plaintext_file;
215 	gchar *sigstatus;
216 	gchar *sigstatus_full;
217 	gboolean decryption_failed;
218 };
219 
220 typedef FILE * (*DecryptMessageFunc)		(MsgInfo	*msginfo,
221 						 MimeInfo      **mimeinfo);
222 
223 GHashTable *procmsg_msg_hash_table_create	(GSList		*mlist);
224 void procmsg_msg_hash_table_append		(GHashTable	*msg_table,
225 						 GSList		*mlist);
226 GHashTable *procmsg_to_folder_hash_table_create	(GSList		*mlist);
227 
228 gint procmsg_read_cache_data_str	(FILE		*fp,
229 					 gchar	       **str);
230 
231 GSList *procmsg_read_cache		(FolderItem	*item,
232 					 gboolean	 scan_file);
233 void	procmsg_set_flags		(GSList		*mlist,
234 					 FolderItem	*item);
235 void	procmsg_mark_all_read		(FolderItem	*item);
236 GSList *procmsg_sort_msg_list		(GSList		*mlist,
237 					 FolderSortKey	 sort_key,
238 					 FolderSortType	 sort_type);
239 gint	procmsg_get_last_num_in_msg_list(GSList		*mlist);
240 void	procmsg_msg_list_free		(GSList		*mlist);
241 
242 void	procmsg_write_cache		(MsgInfo	*msginfo,
243 					 FILE		*fp);
244 void	procmsg_write_flags		(MsgInfo	*msginfo,
245 					 FILE		*fp);
246 void	procmsg_write_cache_list	(FolderItem	*item,
247 					 GSList		*mlist);
248 void	procmsg_write_flags_list	(FolderItem	*item,
249 					 GSList		*mlist);
250 void	procmsg_write_flags_for_multiple_folders
251 					(GSList		*mlist);
252 
253 void	procmsg_flaginfo_list_free	(GSList		*flaglist);
254 
255 void	procmsg_flush_mark_queue	(FolderItem	*item,
256 					 FILE		*fp);
257 void	procmsg_add_mark_queue		(FolderItem	*item,
258 					 gint		 num,
259 					 MsgFlags	 flags);
260 void	procmsg_flush_cache_queue	(FolderItem	*item,
261 					 FILE		*fp);
262 void	procmsg_add_cache_queue		(FolderItem	*item,
263 					 gint		 num,
264 					 MsgInfo	*msginfo);
265 
266 gboolean procmsg_flush_folder		(FolderItem	*item);
267 void	procmsg_flush_folder_foreach	(GHashTable	*folder_table);
268 
269 void	procmsg_add_flags		(FolderItem	*item,
270 					 gint		 num,
271 					 MsgFlags	 flags);
272 
273 void	procmsg_get_mark_sum		(FolderItem	*item,
274 					 gint		*new,
275 					 gint		*unread,
276 					 gint		*total,
277 					 gint		*min,
278 					 gint		*max,
279 					 gint		 first);
280 
281 FILE   *procmsg_open_data_file		(const gchar	*file,
282 					 guint		 version,
283 					 DataOpenMode	 mode,
284 					 gchar		*buf,
285 					 size_t		 buf_size);
286 
287 FILE   *procmsg_open_cache_file		(FolderItem	*item,
288 					 DataOpenMode	 mode);
289 FILE   *procmsg_open_mark_file		(FolderItem	*item,
290 					 DataOpenMode	 mode);
291 
292 void	procmsg_clear_cache		(FolderItem	*item);
293 void	procmsg_clear_mark		(FolderItem	*item);
294 
295 GNode  *procmsg_get_thread_tree		(GSList		*mlist);
296 guint	procmsg_get_thread_date		(GNode		*node);
297 
298 gint	procmsg_move_messages		(GSList		*mlist);
299 gint	procmsg_copy_messages		(GSList		*mlist);
300 
301 gint	procmsg_add_messages_from_queue	(FolderItem	*dest,
302 					 GSList		*mlist,
303 					 gboolean	 is_move);
304 
305 gchar  *procmsg_get_message_file_path	(MsgInfo	*msginfo);
306 gchar  *procmsg_get_message_file	(MsgInfo	*msginfo);
307 GSList *procmsg_get_message_file_list	(GSList		*mlist);
308 void	procmsg_message_file_list_free	(GSList		*file_list);
309 FILE   *procmsg_open_message		(MsgInfo	*msginfo);
310 
311 void procmsg_set_decrypt_message_func	(DecryptMessageFunc	 func);
312 void procmsg_set_auto_decrypt_message	(gboolean	 enabled);
313 FILE   *procmsg_open_message_decrypted	(MsgInfo	*msginfo,
314 					 MimeInfo      **mimeinfo);
315 
316 gboolean procmsg_msg_exist		(MsgInfo	*msginfo);
317 
318 gboolean procmsg_trash_messages_exist	(void);
319 void	procmsg_empty_trash		(FolderItem	*trash);
320 void	procmsg_empty_all_trash		(void);
321 
322 void	procmsg_remove_all_cached_messages
323 					(Folder		*folder);
324 
325 gint	procmsg_save_to_outbox		(FolderItem	*outbox,
326 					 const gchar	*file);
327 void	procmsg_print_message		(MsgInfo	*msginfo,
328 					 const gchar	*cmdline,
329 					 gboolean	 all_headers);
330 void	procmsg_print_message_part	(MsgInfo	*msginfo,
331 					 MimeInfo	*partinfo,
332 					 const gchar	*cmdline,
333 					 gboolean	 all_headers);
334 
335 gint	procmsg_save_message_as_text	(MsgInfo	*msginfo,
336 					 const gchar	*dest,
337 					 const gchar	*encoding,
338 					 gboolean	 all_headers);
339 
340 gint	procmsg_concat_partial_messages	(GSList		*mlist,
341 					 const gchar	*file);
342 
343 MsgInfo *procmsg_get_msginfo		(FolderItem	*item,
344 					 gint		 num);
345 
346 MsgInfo *procmsg_msginfo_copy		(MsgInfo	*msginfo);
347 MsgInfo *procmsg_msginfo_get_full_info	(MsgInfo	*msginfo);
348 gboolean procmsg_msginfo_equal		(MsgInfo	*msginfo_a,
349 					 MsgInfo	*msginfo_b);
350 void	 procmsg_msginfo_free		(MsgInfo	*msginfo);
351 
352 gint procmsg_cmp_msgnum_for_sort	(gconstpointer	 a,
353 					 gconstpointer	 b);
354 
355 #endif /* __PROCMSG_H__ */
356