1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright 2001-2003 Ximian, Inc. (www.ximian.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
27 #include "camel-digest-folder.h"
28 #include "camel-digest-summary.h"
29 #include "camel-exception.h"
30 #include "camel-folder-search.h"
31 #include "camel-mime-message.h"
32 #include "camel-multipart.h"
36 #define _PRIVATE(o) (((CamelDigestFolder *)(o))->priv)
38 struct _CamelDigestFolderPrivate {
39 CamelMimeMessage *message;
40 CamelFolderSearch *search;
44 #define CAMEL_DIGEST_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelDigestFolder *)f)->priv->l))
45 #define CAMEL_DIGEST_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelDigestFolder *)f)->priv->l))
47 static CamelFolderClass *parent_class = NULL;
49 static void digest_refresh_info (CamelFolder *folder, CamelException *ex);
50 static void digest_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
51 static const char *digest_get_full_name (CamelFolder *folder);
52 static void digest_expunge (CamelFolder *folder, CamelException *ex);
54 /* message manipulation */
55 static CamelMimeMessage *digest_get_message (CamelFolder *folder, const gchar *uid,
57 static void digest_append_message (CamelFolder *folder, CamelMimeMessage *message,
58 const CamelMessageInfo *info, char **appended_uid, CamelException *ex);
59 static void digest_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
60 CamelFolder *dest, GPtrArray **transferred_uids,
61 gboolean delete_originals, CamelException *ex);
63 static GPtrArray *digest_search_by_expression (CamelFolder *folder, const char *expression,
66 static GPtrArray *digest_search_by_uids (CamelFolder *folder, const char *expression,
67 GPtrArray *uids, CamelException *ex);
69 static void digest_search_free (CamelFolder *folder, GPtrArray *result);
72 camel_digest_folder_class_init (CamelDigestFolderClass *camel_digest_folder_class)
74 CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_digest_folder_class);
76 parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
78 /* virtual method definition */
80 /* virtual method overload */
81 camel_folder_class->refresh_info = digest_refresh_info;
82 camel_folder_class->sync = digest_sync;
83 camel_folder_class->expunge = digest_expunge;
84 camel_folder_class->get_full_name = digest_get_full_name;
86 camel_folder_class->get_message = digest_get_message;
87 camel_folder_class->append_message = digest_append_message;
88 camel_folder_class->transfer_messages_to = digest_transfer_messages_to;
90 camel_folder_class->search_by_expression = digest_search_by_expression;
91 camel_folder_class->search_by_uids = digest_search_by_uids;
92 camel_folder_class->search_free = digest_search_free;
96 camel_digest_folder_init (gpointer object, gpointer klass)
98 CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
99 CamelFolder *folder = CAMEL_FOLDER (object);
101 folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
103 folder->summary = camel_digest_summary_new ();
105 digest_folder->priv = g_new (struct _CamelDigestFolderPrivate, 1);
106 digest_folder->priv->message = NULL;
107 digest_folder->priv->search = NULL;
108 digest_folder->priv->search_lock = g_mutex_new ();
112 digest_finalize (CamelObject *object)
114 CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
115 CamelFolder *folder = CAMEL_FOLDER (object);
117 if (folder->summary) {
118 camel_object_unref (folder->summary);
119 folder->summary = NULL;
122 camel_object_unref (digest_folder->priv->message);
124 if (digest_folder->priv->search)
125 camel_object_unref (digest_folder->priv->search);
127 g_mutex_free (digest_folder->priv->search_lock);
129 g_free (digest_folder->priv);
133 camel_digest_folder_get_type (void)
135 static CamelType type = CAMEL_INVALID_TYPE;
137 if (type == CAMEL_INVALID_TYPE) {
138 type = camel_type_register (CAMEL_FOLDER_TYPE,
140 sizeof (CamelDigestFolder),
141 sizeof (CamelDigestFolderClass),
142 (CamelObjectClassInitFunc) camel_digest_folder_class_init,
144 (CamelObjectInitFunc) camel_digest_folder_init,
145 (CamelObjectFinalizeFunc) digest_finalize);
152 multipart_contains_message_parts (CamelMultipart *multipart)
154 gboolean has_message_parts = FALSE;
155 CamelDataWrapper *wrapper;
159 parts = camel_multipart_get_number (multipart);
160 for (i = 0; i < parts && !has_message_parts; i++) {
161 part = camel_multipart_get_part (multipart, i);
162 wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
163 if (CAMEL_IS_MULTIPART (wrapper)) {
164 has_message_parts = multipart_contains_message_parts (CAMEL_MULTIPART (wrapper));
165 } else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
166 has_message_parts = TRUE;
170 return has_message_parts;
174 digest_add_multipart (CamelFolder *folder, CamelMultipart *multipart, const char *preuid)
176 CamelDataWrapper *wrapper;
177 CamelMessageInfo *info;
182 parts = camel_multipart_get_number (multipart);
183 for (i = 0; i < parts; i++) {
184 part = camel_multipart_get_part (multipart, i);
186 wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
188 if (CAMEL_IS_MULTIPART (wrapper)) {
189 uid = g_strdup_printf ("%s%d.", preuid, i);
190 digest_add_multipart (folder, CAMEL_MULTIPART (wrapper), uid);
193 } else if (!CAMEL_IS_MIME_MESSAGE (wrapper)) {
197 info = camel_folder_summary_info_new_from_message (folder->summary, CAMEL_MIME_MESSAGE (wrapper));
199 info->uid = g_strdup_printf ("%s%d", preuid, i);
200 camel_folder_summary_add (folder->summary, info);
205 construct_summary (CamelFolder *folder, CamelMultipart *multipart)
207 digest_add_multipart (folder, multipart, "");
211 camel_digest_folder_new (CamelStore *parent_store, CamelMimeMessage *message)
213 CamelDigestFolder *digest_folder;
214 CamelDataWrapper *wrapper;
217 wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
218 if (!wrapper || !CAMEL_IS_MULTIPART (wrapper))
221 /* Make sure we have a multipart/digest subpart or at least some message/rfc822 attachments... */
222 if (!camel_content_type_is (CAMEL_DATA_WRAPPER (message)->mime_type, "multipart", "digest")) {
223 if (!multipart_contains_message_parts (CAMEL_MULTIPART (wrapper)))
227 folder = CAMEL_FOLDER (camel_object_new (camel_digest_folder_get_type ()));
228 digest_folder = CAMEL_DIGEST_FOLDER (folder);
230 camel_folder_construct (folder, parent_store, "folder_name", "short_name");
232 camel_object_ref (message);
233 digest_folder->priv->message = message;
235 construct_summary (folder, CAMEL_MULTIPART (wrapper));
241 digest_refresh_info (CamelFolder *folder, CamelException *ex)
247 digest_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
253 digest_expunge (CamelFolder *folder, CamelException *ex)
259 digest_get_full_name (CamelFolder *folder)
261 return folder->full_name;
265 digest_append_message (CamelFolder *folder, CamelMimeMessage *message,
266 const CamelMessageInfo *info, char **appended_uid,
271 *appended_uid = NULL;
275 digest_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
276 CamelFolder *dest, GPtrArray **transferred_uids,
277 gboolean delete_originals, CamelException *ex)
280 if (transferred_uids)
281 *transferred_uids = NULL;
284 static CamelMimeMessage *
285 digest_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
287 CamelDigestFolder *digest = CAMEL_DIGEST_FOLDER (folder);
288 CamelDataWrapper *wrapper;
289 CamelMimeMessage *message;
294 part = CAMEL_MIME_PART (digest->priv->message);
295 wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
298 id = strtoul (uid, &subuid, 10);
299 if (!CAMEL_IS_MULTIPART (wrapper))
302 part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), id);
303 wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
305 } while (*subuid == '.');
307 if (!CAMEL_IS_MIME_MESSAGE (wrapper))
310 message = CAMEL_MIME_MESSAGE (wrapper);
311 camel_object_ref (message);
317 digest_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
319 CamelDigestFolder *df = (CamelDigestFolder *) folder;
322 CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
324 if (!df->priv->search)
325 df->priv->search = camel_folder_search_new ();
327 camel_folder_search_set_folder (df->priv->search, folder);
328 matches = camel_folder_search_search(df->priv->search, expression, NULL, ex);
330 CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
336 digest_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
338 CamelDigestFolder *df = (CamelDigestFolder *) folder;
342 return g_ptr_array_new();
344 CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
346 if (!df->priv->search)
347 df->priv->search = camel_folder_search_new ();
349 camel_folder_search_set_folder (df->priv->search, folder);
350 matches = camel_folder_search_search(df->priv->search, expression, NULL, ex);
352 CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
358 digest_search_free (CamelFolder *folder, GPtrArray *result)
360 CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (folder);
362 CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
364 camel_folder_search_free_result (digest_folder->priv->search, result);
366 CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);