[evolution-data-server/wip/camel-more-gobject: 16/16] Bug 764065 (part 1) - [Camel] Port more classes to GObject
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/camel-more-gobject: 16/16] Bug 764065 (part 1) - [Camel] Port more classes to GObject
- Date: Tue, 11 Oct 2016 20:20:07 +0000 (UTC)
commit 6bffc8c0c72f420bff31257abfb876e796ec9c1c
Author: Milan Crha <mcrha redhat com>
Date: Tue Oct 11 21:46:17 2016 +0200
Bug 764065 (part 1) - [Camel] Port more classes to GObject
CMakeLists.txt | 2 +-
src/camel/CMakeLists.txt | 12 +
src/camel/camel-charset-map.c | 12 +-
src/camel/camel-cipher-context.c | 8 +-
src/camel/camel-db.c | 162 +-
src/camel/camel-db.h | 14 +-
src/camel/camel-filter-driver.c | 21 +-
src/camel/camel-filter-driver.h | 2 +-
src/camel/camel-filter-search.c | 97 +-
src/camel/camel-folder-search.c | 7 +-
src/camel/camel-folder-summary.c | 2587 ++----------------
src/camel/camel-folder-summary.h | 385 +---
src/camel/camel-folder-thread.c | 62 +-
src/camel/camel-folder.c | 71 +-
src/camel/camel-folder.h | 22 +-
src/camel/camel-index.h | 2 +-
src/camel/camel-message-info-base.c | 877 ++++++
src/camel/camel-message-info-base.h | 67 +
src/camel/camel-message-info.c | 2979 ++++++++++++++++++++
src/camel/camel-message-info.h | 328 +++
src/camel/camel-mime-filter-yenc.c | 30 +-
src/camel/camel-mime-message.c | 2 +-
src/camel/camel-mime-parser.c | 8 +-
src/camel/camel-mime-parser.h | 2 +-
src/camel/camel-mime-part-utils.c | 189 +-
src/camel/camel-mime-part-utils.h | 35 +-
src/camel/camel-mime-part.c | 8 +-
src/camel/camel-mime-part.h | 2 +-
src/camel/camel-mime-utils.c | 119 +-
src/camel/camel-mime-utils.h | 28 +-
src/camel/camel-movemail.c | 2 +-
src/camel/camel-msgport.c | 1 +
src/camel/camel-name-value-array.c | 633 +++++
src/camel/camel-name-value-array.h | 96 +
src/camel/camel-named-flags.c | 317 +++
src/camel/camel-named-flags.h | 62 +
src/camel/camel-provider.c | 4 +-
src/camel/camel-sasl-gssapi.c | 4 +-
src/camel/camel-sasl.c | 2 +-
src/camel/camel-service.c | 6 +-
src/camel/camel-session.c | 2 +-
src/camel/camel-sexp.h | 6 +-
src/camel/camel-store-summary.c | 2 +-
src/camel/camel-store-summary.h | 4 +-
src/camel/camel-store.c | 6 +-
src/camel/camel-store.h | 8 +
src/camel/camel-stream-buffer.c | 2 +-
src/camel/camel-stream.c | 6 +-
src/camel/camel-subscribable.c | 4 +-
src/camel/camel-trie.c | 6 +-
src/camel/camel-url-scanner.c | 11 +
src/camel/camel-url.c | 42 +-
src/camel/camel-url.h | 6 +-
src/camel/camel-utils.c | 173 ++
src/camel/camel-utils.h | 40 +
src/camel/camel-vee-data-cache.h | 4 +-
src/camel/camel-vee-folder.c | 28 +-
src/camel/camel-vee-folder.h | 2 +-
src/camel/camel-vee-message-info.c | 532 ++++
src/camel/camel-vee-message-info.h | 77 +
src/camel/camel-vee-store.c | 14 +-
src/camel/camel-vee-summary.c | 293 +--
src/camel/camel-vee-summary.h | 10 +-
src/camel/camel-vtrash-folder.c | 12 +-
src/camel/camel.h | 6 +
src/camel/providers/imapx/CMakeLists.txt | 2 +
src/camel/providers/imapx/camel-imapx-command.c | 4 +-
src/camel/providers/imapx/camel-imapx-folder.c | 4 +-
.../providers/imapx/camel-imapx-message-info.c | 435 +++
.../providers/imapx/camel-imapx-message-info.h | 87 +
src/camel/providers/imapx/camel-imapx-search.c | 3 +-
src/camel/providers/imapx/camel-imapx-server.c | 416 ++--
src/camel/providers/imapx/camel-imapx-summary.c | 242 +--
src/camel/providers/imapx/camel-imapx-summary.h | 14 -
src/camel/providers/imapx/camel-imapx-utils.c | 171 +-
src/camel/providers/imapx/camel-imapx-utils.h | 17 +-
src/camel/providers/local/CMakeLists.txt | 4 +
src/camel/providers/local/camel-local-summary.c | 144 +-
src/camel/providers/local/camel-local-summary.h | 16 +-
src/camel/providers/local/camel-maildir-folder.c | 46 +-
.../providers/local/camel-maildir-message-info.c | 251 ++
.../providers/local/camel-maildir-message-info.h | 71 +
src/camel/providers/local/camel-maildir-summary.c | 173 +-
src/camel/providers/local/camel-maildir-summary.h | 15 +-
src/camel/providers/local/camel-mbox-folder.c | 59 +-
.../providers/local/camel-mbox-message-info.c | 255 ++
.../providers/local/camel-mbox-message-info.h | 67 +
src/camel/providers/local/camel-mbox-summary.c | 339 +--
src/camel/providers/local/camel-mbox-summary.h | 6 -
src/camel/providers/local/camel-mh-folder.c | 4 +-
src/camel/providers/local/camel-mh-summary.c | 32 +-
src/camel/providers/local/camel-spool-summary.c | 9 +-
src/camel/providers/local/camel-spool-summary.h | 2 +-
src/camel/providers/nntp/camel-nntp-folder.c | 18 +-
src/camel/providers/nntp/camel-nntp-summary.c | 35 +-
src/camel/providers/pop3/camel-pop3-folder.c | 6 +-
.../providers/sendmail/camel-sendmail-provider.c | 4 +-
.../providers/sendmail/camel-sendmail-transport.c | 6 +-
src/camel/providers/smtp/camel-smtp-transport.c | 6 +-
src/camel/tests/lib/folders.c | 12 +-
src/vala/Camel-1.2.metadata | 12 +
101 files changed, 8934 insertions(+), 4616 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aec781a..384a5f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,7 +44,7 @@ set(USER_PROMPTER_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.UserPrompter
# ******************************
# Library versioning
# ******************************
-set(LIBCAMEL_CURRENT 59)
+set(LIBCAMEL_CURRENT 60)
set(LIBCAMEL_REVISION 0)
set(LIBCAMEL_AGE 0)
diff --git a/src/camel/CMakeLists.txt b/src/camel/CMakeLists.txt
index 6e7ea43..a0a4f81 100644
--- a/src/camel/CMakeLists.txt
+++ b/src/camel/CMakeLists.txt
@@ -38,6 +38,8 @@ set(SOURCES
camel-medium.c
camel-memchunk.c
camel-mempool.c
+ camel-message-info.c
+ camel-message-info-base.c
camel-mime-filter-basic.c
camel-mime-filter-bestenc.c
camel-mime-filter-canon.c
@@ -64,6 +66,8 @@ set(SOURCES
camel-multipart-encrypted.c
camel-multipart-signed.c
camel-multipart.c
+ camel-named-flags.c
+ camel-name-value-array.c
camel-net-utils.c
camel-network-service.c
camel-network-settings.c
@@ -111,8 +115,10 @@ set(SOURCES
camel-url-scanner.c
camel-url.c
camel-utf8.c
+ camel-utils.c
camel-vee-data-cache.c
camel-vee-folder.c
+ camel-vee-message-info.c
camel-vee-store.c
camel-vee-summary.c
camel-vtrash-folder.c
@@ -167,6 +173,8 @@ set(HEADERS
camel-medium.h
camel-memchunk.h
camel-mempool.h
+ camel-message-info.h
+ camel-message-info-base.h
camel-mime-filter-basic.h
camel-mime-filter-bestenc.h
camel-mime-filter-canon.h
@@ -194,6 +202,8 @@ set(HEADERS
camel-multipart-encrypted.h
camel-multipart-signed.h
camel-multipart.h
+ camel-named-flags.h
+ camel-name-value-array.h
camel-net-utils.h
camel-network-service.h
camel-network-settings.h
@@ -242,8 +252,10 @@ set(HEADERS
camel-url-scanner.h
camel-url.h
camel-utf8.h
+ camel-utils.h
camel-vee-data-cache.h
camel-vee-folder.h
+ camel-vee-message-info.h
camel-vee-store.h
camel-vee-summary.h
camel-vtrash-folder.h
diff --git a/src/camel/camel-charset-map.c b/src/camel/camel-charset-map.c
index 38f4167..1e765c3 100644
--- a/src/camel/camel-charset-map.c
+++ b/src/camel/camel-charset-map.c
@@ -316,6 +316,10 @@ camel_charset_init (CamelCharset *c)
c->level = 0;
}
+/**
+ * camel_charset_step:
+ * @in: (array length=len) (type gchar):
+ **/
void
camel_charset_step (CamelCharset *cc,
const gchar *in,
@@ -381,7 +385,13 @@ camel_charset_best_name (CamelCharset *charset)
return NULL;
}
-/* finds the minimum charset for this string NULL means US-ASCII */
+/**
+ * camel_charset_best:
+ * @in: (array length=len) (type gchar):
+ *
+ * finds the minimum charset for this string NULL means US-ASCII
+ * Returns: (nullable): the minimum charset or NULL for US_ASCII.
+ **/
const gchar *
camel_charset_best (const gchar *in,
gint len)
diff --git a/src/camel/camel-cipher-context.c b/src/camel/camel-cipher-context.c
index 80bcc6c..0fcffff 100644
--- a/src/camel/camel-cipher-context.c
+++ b/src/camel/camel-cipher-context.c
@@ -1232,7 +1232,7 @@ camel_cipher_validity_add_certinfo_ex (CamelCipherValidity *vin,
*
* Gets a named property @name value for the given @info_index of the @mode validity part.
*
- * Returns: Value of a named property of a #CamelCipherCertInfo, or %NULL when no such
+ * Returns: (transfer none) (nullable): Value of a named property of a #CamelCipherCertInfo, or %NULL when
no such
* property exists. The returned value is owned by the associated #CamelCipherCertInfo
* and is valid until the cert info is freed.
*
@@ -1399,9 +1399,9 @@ camel_cipher_validity_free (CamelCipherValidity *validity)
*
* Gets a named property @name value for the given @cert_info.
*
- * Returns: Value of a named property of the @cert_info, or %NULL when no such
- * property exists. The returned value is owned by the @cert_info
- * and is valid until the @cert_info is freed.
+ * Returns: (transfer none) (nullable): Value of a named property of the @cert_info,
+ * or %NULL when no such property exists. The returned value is owned by
+ * the @cert_info and is valid until the @cert_info is freed.
*
* Since: 3.22
**/
diff --git a/src/camel/camel-db.c b/src/camel/camel-db.c
index dffad32..222a880 100644
--- a/src/camel/camel-db.c
+++ b/src/camel/camel-db.c
@@ -1418,104 +1418,6 @@ camel_db_get_folder_deleted_uids (CamelDB *db,
return array;
}
-struct ReadPreviewData
-{
- GHashTable *columns_hash;
- GHashTable *hash;
-};
-
-static gint
-read_preview_callback (gpointer ref,
- gint ncol,
- gchar **cols,
- gchar **name)
-{
- struct ReadPreviewData *rpd = ref;
- const gchar *uid = NULL;
- gchar *msg = NULL;
- gint i;
-
- for (i = 0; i < ncol; ++i) {
- if (!name[i] || !cols[i])
- continue;
-
- switch (camel_db_get_column_ident (&rpd->columns_hash, i, ncol, name)) {
- case CAMEL_DB_COLUMN_UID:
- uid = camel_pstring_strdup (cols[i]);
- break;
- case CAMEL_DB_COLUMN_PREVIEW:
- msg = g_strdup (cols[i]);
- break;
- default:
- g_warn_if_reached ();
- break;
- }
- }
-
- g_hash_table_insert (rpd->hash, (gchar *) uid, msg);
-
- return 0;
-}
-
-/**
- * camel_db_get_folder_preview:
- *
- * Returns: (element-type utf8 utf8) (transfer full):
- *
- * Since: 2.28
- **/
-GHashTable *
-camel_db_get_folder_preview (CamelDB *db,
- const gchar *folder_name,
- GError **error)
-{
- gchar *sel_query;
- gint ret;
- struct ReadPreviewData rpd;
- GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- sel_query = sqlite3_mprintf ("SELECT uid, preview FROM '%q_preview'", folder_name);
-
- rpd.columns_hash = NULL;
- rpd.hash = hash;
-
- ret = camel_db_select (db, sel_query, read_preview_callback, &rpd, error);
- sqlite3_free (sel_query);
-
- if (rpd.columns_hash)
- g_hash_table_destroy (rpd.columns_hash);
-
- if (!g_hash_table_size (hash) || ret != 0) {
- g_hash_table_destroy (hash);
- hash = NULL;
- }
-
- return hash;
-}
-
-/**
- * camel_db_write_preview_record:
- *
- * Since: 2.28
- **/
-gint
-camel_db_write_preview_record (CamelDB *db,
- const gchar *folder_name,
- const gchar *uid,
- const gchar *msg,
- GError **error)
-{
- gchar *query;
- gint ret;
-
- query = sqlite3_mprintf ("INSERT OR REPLACE INTO '%q_preview' VALUES(%Q,%Q)", folder_name, uid, msg);
-
- ret = camel_db_add_to_transaction (db, query, error);
- sqlite3_free (query);
-
- return ret;
-}
-
/**
* camel_db_create_folders_table:
*
@@ -1598,19 +1500,6 @@ camel_db_create_message_info_table (CamelDB *cdb,
ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
sqlite3_free (table_creation_query);
- table_creation_query = sqlite3_mprintf (
- "CREATE TABLE IF NOT EXISTS '%q_bodystructure' ( "
- "uid TEXT PRIMARY KEY , "
- "bodystructure TEXT )",
- folder_name);
- ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
- sqlite3_free (table_creation_query);
-
- /* Create message preview table. */
- table_creation_query = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS '%q_preview' ( uid TEXT PRIMARY
KEY , preview TEXT)", folder_name);
- ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
- sqlite3_free (table_creation_query);
-
/* FIXME: sqlize folder_name before you create the index */
safe_index = g_strdup_printf ("SINDEX-%s", folder_name);
table_creation_query = sqlite3_mprintf ("DROP INDEX IF EXISTS %Q", safe_index);
@@ -1618,13 +1507,6 @@ camel_db_create_message_info_table (CamelDB *cdb,
g_free (safe_index);
sqlite3_free (table_creation_query);
- /* INDEX on preview */
- safe_index = g_strdup_printf ("SINDEX-%s-preview", folder_name);
- table_creation_query = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS %Q ON '%q_preview' (uid,
preview)", safe_index, folder_name);
- ret = camel_db_add_to_transaction (cdb, table_creation_query, error);
- g_free (safe_index);
- sqlite3_free (table_creation_query);
-
/* Index on deleted*/
safe_index = g_strdup_printf ("DELINDEX-%s", folder_name);
table_creation_query = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS %Q ON %Q (deleted)", safe_index,
folder_name);
@@ -1974,8 +1856,8 @@ write_mir (CamelDB *cdb,
record->attachment,
record->dirty,
record->size,
- (gint64) record->dsent,
- (gint64) record->dreceived,
+ record->dsent,
+ record->dreceived,
record->subject,
record->from,
record->to,
@@ -1994,15 +1876,6 @@ write_mir (CamelDB *cdb,
sqlite3_free (ins_query);
- if (ret == 0) {
- ins_query = sqlite3_mprintf (
- "INSERT OR REPLACE INTO "
- "'%q_bodystructure' VALUES (%Q, %Q )",
- folder_name, record->uid, record->bodystructure);
- ret = camel_db_add_to_transaction (cdb, ins_query, error);
- sqlite3_free (ins_query);
- }
-
return ret;
}
@@ -2242,10 +2115,6 @@ camel_db_delete_uid (CamelDB *cdb,
camel_db_begin_transaction (cdb, error);
- tab = sqlite3_mprintf ("DELETE FROM '%q_bodystructure' WHERE uid = %Q", folder, uid);
- ret = camel_db_add_to_transaction (cdb, tab, error);
- sqlite3_free (tab);
-
tab = sqlite3_mprintf ("DELETE FROM %Q WHERE uid = %Q", folder, uid);
ret = camel_db_add_to_transaction (cdb, tab, error);
sqlite3_free (tab);
@@ -2342,23 +2211,19 @@ camel_db_clear_folder_summary (CamelDB *cdb,
gint ret;
gchar *folders_del;
gchar *msginfo_del;
- gchar *bstruct_del;
folders_del = sqlite3_mprintf ("DELETE FROM folders WHERE folder_name = %Q", folder);
msginfo_del = sqlite3_mprintf ("DELETE FROM %Q ", folder);
- bstruct_del = sqlite3_mprintf ("DELETE FROM '%q_bodystructure' ", folder);
camel_db_begin_transaction (cdb, error);
camel_db_add_to_transaction (cdb, msginfo_del, error);
camel_db_add_to_transaction (cdb, folders_del, error);
- camel_db_add_to_transaction (cdb, bstruct_del, error);
ret = camel_db_end_transaction (cdb, error);
sqlite3_free (folders_del);
sqlite3_free (msginfo_del);
- sqlite3_free (bstruct_del);
return ret;
}
@@ -2386,10 +2251,6 @@ camel_db_delete_folder (CamelDB *cdb,
ret = camel_db_add_to_transaction (cdb, del, error);
sqlite3_free (del);
- del = sqlite3_mprintf ("DROP TABLE '%q_bodystructure' ", folder);
- ret = camel_db_add_to_transaction (cdb, del, error);
- sqlite3_free (del);
-
ret = camel_db_end_transaction (cdb, error);
CAMEL_DB_RELEASE_SQLITE_MEMORY;
@@ -2444,20 +2305,19 @@ camel_db_camel_mir_free (CamelMIRecord *record)
{
if (record) {
camel_pstring_free (record->uid);
- camel_pstring_free (record->subject);
- camel_pstring_free (record->from);
- camel_pstring_free (record->to);
- camel_pstring_free (record->cc);
- camel_pstring_free (record->mlist);
- camel_pstring_free (record->followup_flag);
- camel_pstring_free (record->followup_completed_on);
- camel_pstring_free (record->followup_due_by);
+ g_free (record->subject);
+ g_free (record->from);
+ g_free (record->to);
+ g_free (record->cc);
+ g_free (record->mlist);
+ g_free (record->followup_flag);
+ g_free (record->followup_completed_on);
+ g_free (record->followup_due_by);
g_free (record->part);
g_free (record->labels);
g_free (record->usertags);
g_free (record->cinfo);
g_free (record->bdata);
- g_free (record->bodystructure);
g_free (record);
}
@@ -2624,7 +2484,6 @@ static struct _known_column_names {
} known_column_names[] = {
{ "attachment", CAMEL_DB_COLUMN_ATTACHMENT },
{ "bdata", CAMEL_DB_COLUMN_BDATA },
- { "bodystructure", CAMEL_DB_COLUMN_BODYSTRUCTURE },
{ "cinfo", CAMEL_DB_COLUMN_CINFO },
{ "deleted", CAMEL_DB_COLUMN_DELETED },
{ "deleted_count", CAMEL_DB_COLUMN_DELETED_COUNT },
@@ -2646,7 +2505,6 @@ static struct _known_column_names {
{ "mlist", CAMEL_DB_COLUMN_MLIST },
{ "nextuid", CAMEL_DB_COLUMN_NEXTUID },
{ "part", CAMEL_DB_COLUMN_PART },
- { "preview", CAMEL_DB_COLUMN_PREVIEW },
{ "read", CAMEL_DB_COLUMN_READ },
{ "replied", CAMEL_DB_COLUMN_REPLIED },
{ "saved_count", CAMEL_DB_COLUMN_SAVED_COUNT },
diff --git a/src/camel/camel-db.h b/src/camel/camel-db.h
index b454af9..726686c 100644
--- a/src/camel/camel-db.h
+++ b/src/camel/camel-db.h
@@ -161,7 +161,6 @@ struct _CamelDB {
* content info string - composite string
* @bdata:
* provider specific data
- * @bodystructure:
*
* The extensive DB format, supporting basic searching and sorting.
*
@@ -179,8 +178,8 @@ typedef struct _CamelMIRecord {
gboolean junk;
gboolean attachment;
guint32 size;
- time_t dsent;
- time_t dreceived;
+ gint64 dsent; /* time_t */
+ gint64 dreceived; /* time_t */
gchar *subject;
gchar *from;
gchar *to;
@@ -194,7 +193,6 @@ typedef struct _CamelMIRecord {
gchar *usertags;
gchar *cinfo;
gchar *bdata;
- gchar *bodystructure;
} CamelMIRecord;
/**
@@ -228,7 +226,6 @@ typedef enum {
CAMEL_DB_COLUMN_UNKNOWN = -1,
CAMEL_DB_COLUMN_ATTACHMENT,
CAMEL_DB_COLUMN_BDATA,
- CAMEL_DB_COLUMN_BODYSTRUCTURE,
CAMEL_DB_COLUMN_CINFO,
CAMEL_DB_COLUMN_DELETED,
CAMEL_DB_COLUMN_DELETED_COUNT,
@@ -250,7 +247,6 @@ typedef enum {
CAMEL_DB_COLUMN_MLIST,
CAMEL_DB_COLUMN_NEXTUID,
CAMEL_DB_COLUMN_PART,
- CAMEL_DB_COLUMN_PREVIEW,
CAMEL_DB_COLUMN_READ,
CAMEL_DB_COLUMN_REPLIED,
CAMEL_DB_COLUMN_SAVED_COUNT,
@@ -272,7 +268,7 @@ CamelDBKnownColumnNames camel_db_get_column_ident (GHashTable **hash, gint index
*
* Since: 2.24
**/
-typedef gint (*CamelDBSelectCB) (gpointer data, gint ncol, gchar **colvalues, gchar **colnames);
+typedef gint (*CamelDBSelectCB) (gpointer user_data, gint ncol, gchar **colvalues, gchar **colnames);
CamelDB * camel_db_open (const gchar *path, GError **error);
CamelDB * camel_db_clone (CamelDB *cdb, GError **error);
@@ -332,10 +328,6 @@ gint camel_db_set_collate (CamelDB *cdb, const gchar *col, const gchar *collate,
gint camel_db_start_in_memory_transactions (CamelDB *cdb, GError **error);
gint camel_db_flush_in_memory_transactions (CamelDB *cdb, const gchar * folder_name, GError **error);
-GHashTable *
-camel_db_get_folder_preview (CamelDB *db, const gchar *folder_name, GError **error);
-gint camel_db_write_preview_record (CamelDB *db, const gchar *folder_name, const gchar *uid, const gchar
*msg, GError **error);
-
gint
camel_db_reset_folder_version (CamelDB *cdb, const gchar *folder_name, gint reset_version, GError **error);
diff --git a/src/camel/camel-filter-driver.c b/src/camel/camel-filter-driver.c
index b0e73b4..ed32998 100644
--- a/src/camel/camel-filter-driver.c
+++ b/src/camel/camel-filter-driver.c
@@ -1345,7 +1345,7 @@ camel_filter_driver_flush (CamelFilterDriver *driver,
static gint
decode_flags_from_xev (const gchar *xev,
- CamelMessageInfoBase *mi)
+ CamelMessageInfo *mi)
{
guint32 uid, flags = 0;
gchar *header;
@@ -1359,7 +1359,8 @@ decode_flags_from_xev (const gchar *xev,
}
g_free (header);
- mi->flags = flags;
+ camel_message_info_set_flags (mi, ~0, flags);
+
return 0;
}
@@ -1452,9 +1453,9 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver,
/* Try and see if it has X-Evolution headers */
xev = camel_header_raw_find (&mime_part->headers, "X-Evolution", NULL);
if (xev)
- decode_flags_from_xev (xev, (CamelMessageInfoBase *) info);
+ decode_flags_from_xev (xev, info);
- ((CamelMessageInfoBase *) info)->size = camel_mime_parser_tell (mp) - last;
+ camel_message_info_set_size (info, camel_mime_parser_tell (mp) - last);
last = camel_mime_parser_tell (mp);
status = camel_filter_driver_filter_message (
@@ -1466,7 +1467,7 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver,
report_status (
driver, CAMEL_FILTER_STATUS_END,
100, _("Failed on message %d"), i);
- camel_message_info_unref (info);
+ g_clear_object (&info);
g_propagate_error (error, local_error);
goto fail;
}
@@ -1476,7 +1477,7 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver,
/* skip over the FROM_END state */
camel_mime_parser_step (mp, NULL, NULL);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_operation_progress (cancellable, 100);
@@ -1565,7 +1566,7 @@ camel_filter_driver_filter_folder (CamelFilterDriver *driver,
store_uid, store_uid, cancellable, &local_error);
if (camel_folder_has_summary_capability (folder))
- camel_message_info_unref (info);
+ g_clear_object (&info);
if (local_error != NULL || status == -1) {
report_status (
@@ -1690,7 +1691,7 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver,
g_return_val_if_fail (message != NULL || (source != NULL && uid != NULL), -1);
if (info == NULL) {
- struct _camel_header_raw *h;
+ CamelHeaderRaw *h;
if (message) {
g_object_ref (message);
@@ -1865,7 +1866,7 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver,
g_object_unref (driver->priv->message);
if (freeinfo)
- camel_message_info_unref (info);
+ g_clear_object (&info);
return 0;
@@ -1877,7 +1878,7 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver,
g_object_unref (driver->priv->message);
if (freeinfo)
- camel_message_info_unref (info);
+ g_clear_object (&info);
g_propagate_error (error, driver->priv->error);
driver->priv->error = NULL;
diff --git a/src/camel/camel-filter-driver.h b/src/camel/camel-filter-driver.h
index d0b7eda..383b5e0 100644
--- a/src/camel/camel-filter-driver.h
+++ b/src/camel/camel-filter-driver.h
@@ -74,7 +74,7 @@ enum camel_filter_status_t {
};
typedef CamelFolder * (*CamelFilterGetFolderFunc) (CamelFilterDriver *driver, const gchar *uri,
- gpointer data, GError **error);
+ gpointer user_data, GError **error);
/* report status */
typedef void (*CamelFilterStatusFunc) (CamelFilterDriver *driver, enum camel_filter_status_t status,
gint pc, const gchar *desc, gpointer user_data);
diff --git a/src/camel/camel-filter-search.c b/src/camel/camel-filter-search.c
index 68f0b63..b32cb89 100644
--- a/src/camel/camel-filter-search.c
+++ b/src/camel/camel-filter-search.c
@@ -148,16 +148,18 @@ check_header_in_message_info (CamelMessageInfo *info,
{
struct _KnownHeaders {
const gchar *header_name;
- guint info_key;
+ const gchar *info_name;
+ camel_search_t type;
} known_headers[] = {
- { "Subject", CAMEL_MESSAGE_INFO_SUBJECT },
- { "From", CAMEL_MESSAGE_INFO_FROM },
- { "To", CAMEL_MESSAGE_INFO_TO },
- { "Cc", CAMEL_MESSAGE_INFO_CC }
+ { "Subject", "subject", CAMEL_SEARCH_TYPE_ENCODED },
+ { "From", "from", CAMEL_SEARCH_TYPE_ADDRESS_ENCODED },
+ { "To", "to", CAMEL_SEARCH_TYPE_ADDRESS_ENCODED },
+ { "Cc", "cc", CAMEL_SEARCH_TYPE_ADDRESS_ENCODED }
};
- camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED;
- const gchar *name, *value;
+ const gchar *name;
+ gchar *value;
gboolean found = FALSE;
+ camel_search_t use_type;
gint ii;
g_return_val_if_fail (argc > 1, FALSE);
@@ -175,20 +177,20 @@ check_header_in_message_info (CamelMessageInfo *info,
gint jj;
for (jj = 0; jj < G_N_ELEMENTS (known_headers); jj++) {
- value = camel_message_info_get_ptr (info, known_headers[jj].info_key);
+ value = NULL;
+
+ g_object_get (G_OBJECT (info), known_headers[jj].info_name, &value, NULL);
+
if (!value)
continue;
- if (known_headers[jj].info_key == CAMEL_MESSAGE_INFO_SUBJECT)
- type = CAMEL_SEARCH_TYPE_ENCODED;
- else
- type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
-
for (ii = 1; ii < argc && !*matched; ii++) {
if (argv[ii]->type == CAMEL_SEXP_RES_STRING)
- *matched = camel_search_header_match (value, argv[ii]->value.string,
how, type, NULL);
+ *matched = camel_search_header_match (value, argv[ii]->value.string,
how, known_headers[jj].type, NULL);
}
+ g_free (value);
+
if (*matched)
return TRUE;
}
@@ -201,21 +203,24 @@ check_header_in_message_info (CamelMessageInfo *info,
for (ii = 0; ii < G_N_ELEMENTS (known_headers); ii++) {
found = g_ascii_strcasecmp (name, known_headers[ii].header_name) == 0;
if (found) {
- value = camel_message_info_get_ptr (info, known_headers[ii].info_key);
- if (known_headers[ii].info_key != CAMEL_MESSAGE_INFO_SUBJECT)
- type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
+ g_object_get (G_OBJECT (info), known_headers[ii].info_name, &value, NULL);
+ use_type = known_headers[ii].type;
break;
}
}
- if (!found || !value)
+ if (!found || !value) {
+ g_free (value);
return FALSE;
+ }
for (ii = 1; ii < argc && !*matched; ii++) {
if (argv[ii]->type == CAMEL_SEXP_RES_STRING)
- *matched = camel_search_header_match (value, argv[ii]->value.string, how, type, NULL);
+ *matched = camel_search_header_match (value, argv[ii]->value.string, how, use_type,
NULL);
}
+ g_free (value);
+
return TRUE;
}
@@ -249,7 +254,7 @@ check_header (struct _CamelSExp *f,
} else if (fms->message || !check_header_in_message_info (fms->info, argc, argv, how,
&matched)) {
CamelMimeMessage *message;
CamelMimePart *mime_part;
- struct _camel_header_raw *header;
+ CamelHeaderRaw *header;
const gchar *charset = NULL;
camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED;
CamelContentType *ct;
@@ -845,7 +850,7 @@ junk_test (struct _CamelSExp *f,
CamelMimeMessage *message;
CamelJunkStatus status;
const GHashTable *ht;
- const CamelHeaderParam *node;
+ const CamelNameValueArray *info_headers;
gboolean sender_is_known;
gboolean message_is_junk = FALSE;
GError *error = NULL;
@@ -887,34 +892,48 @@ junk_test (struct _CamelSExp *f,
/* Check the headers for a junk designation. */
ht = camel_session_get_junk_headers (fms->session);
- node = camel_message_info_get_headers (info);
- while (node != NULL) {
- const gchar *value = NULL;
+ camel_message_info_property_lock (info);
- if (node->name != NULL)
- value = g_hash_table_lookup (
- (GHashTable *) ht, node->name);
+ info_headers = camel_message_info_get_headers (info);
+ if (info_headers) {
+ guint len, ii;
- message_is_junk =
- (value != NULL) &&
- (camel_strstrcase (node->value, value) != NULL);
+ len = camel_name_value_array_get_length (info_headers);
+ for (ii = 0; ii < len; ii++) {
+ const gchar *hdr_name = NULL;
+ const gchar *hdr_value = NULL;
+ const gchar *junk_value = NULL;
- if (message_is_junk) {
- if (camel_debug ("junk"))
- printf (
- "Message contains \"%s: %s\"",
- node->name, value);
- goto done;
- }
+ if (!camel_name_value_array_get (info_headers, ii, &hdr_name, &hdr_value))
+ continue;
- node = node->next;
+ if (!hdr_name || !hdr_value)
+ continue;
+
+ junk_value = g_hash_table_lookup ((GHashTable *) ht, hdr_name);
+
+ message_is_junk =
+ (junk_value != NULL) &&
+ (camel_strstrcase (hdr_value, junk_value) != NULL);
+
+ if (message_is_junk) {
+ if (camel_debug ("junk"))
+ printf (
+ "Message contains \"%s: %s\"",
+ hdr_name, junk_value);
+ camel_message_info_property_unlock (info);
+ goto done;
+ }
+ }
}
+ camel_message_info_property_unlock (info);
+
/* Not every message info has headers available, thus try headers of the message itself */
message = camel_filter_search_get_message (fms, f);
if (message) {
- struct _camel_header_raw *h;
+ CamelHeaderRaw *h;
for (h = CAMEL_MIME_PART (message)->headers; h; h = h->next) {
const gchar *value;
diff --git a/src/camel/camel-folder-search.c b/src/camel/camel-folder-search.c
index ffb4add..bda0ce6 100644
--- a/src/camel/camel-folder-search.c
+++ b/src/camel/camel-folder-search.c
@@ -272,8 +272,7 @@ get_current_message (CamelFolderSearch *search)
if (!search || !search->folder || !search->current)
return NULL;
- return camel_folder_get_message_sync (
- search->folder, search->current->uid, search->priv->cancellable, NULL);
+ return camel_folder_get_message_sync (search->folder, camel_message_info_get_uid (search->current),
search->priv->cancellable, NULL);
}
static CamelSExpResult *
@@ -299,7 +298,7 @@ check_header (CamelSExp *sexp,
camel_search_t type = CAMEL_SEARCH_TYPE_ASIS;
struct _camel_search_words *words;
CamelMimeMessage *message = NULL;
- struct _camel_header_raw *raw_header;
+ CamelHeaderRaw *raw_header;
/* only a subset of headers are supported .. */
headername = argv[0]->value.string;
@@ -910,7 +909,7 @@ folder_search_match_all (CamelSExp *sexp,
} else {
g_ptr_array_add (r->value.ptrarray, (gchar *) uid);
}
- camel_message_info_unref (search->current);
+ g_clear_object (&search->current);
}
search->current = NULL;
return r;
diff --git a/src/camel/camel-folder-summary.c b/src/camel/camel-folder-summary.c
index aec35e3..237d554 100644
--- a/src/camel/camel-folder-summary.c
+++ b/src/camel/camel-folder-summary.c
@@ -37,6 +37,8 @@
#include "camel-folder-summary.h"
#include "camel-folder.h"
#include "camel-iconv.h"
+#include "camel-message-info.h"
+#include "camel-message-info-base.h"
#include "camel-mime-filter-basic.h"
#include "camel-mime-filter-charset.h"
#include "camel-mime-filter-html.h"
@@ -79,9 +81,6 @@ struct _CamelFolderSummaryPrivate {
GRecMutex summary_lock; /* for the summary hashtable/array */
GRecMutex filter_lock; /* for accessing any of the filtering/indexing stuff, since we share them */
- gboolean need_preview;
- GHashTable *preview_updates;
-
guint32 nextuid; /* next uid? */
guint32 saved_count; /* how many were saved/loaded */
guint32 unread_count; /* handy totals */
@@ -90,8 +89,6 @@ struct _CamelFolderSummaryPrivate {
guint32 junk_not_deleted_count;
guint32 visible_count;
- gboolean build_content; /* do we try and parse/index the content, or not? */
-
GHashTable *uids; /* uids of all known message infos; the 'value' are used flags for the message info
*/
GHashTable *loaded_infos; /* uid->CamelMessageInfo *, those currently in memory */
@@ -116,27 +113,18 @@ struct _node {
static void cfs_schedule_info_release_timer (CamelFolderSummary *summary);
-static struct _node *my_list_append (struct _node **list, struct _node *n);
-static gint my_list_size (struct _node **list);
+static void summary_traverse_content_with_parser (CamelFolderSummary *summary, CamelMessageInfo *msginfo,
CamelMimeParser *mp);
+static void summary_traverse_content_with_part (CamelFolderSummary *summary, CamelMessageInfo *msginfo,
CamelMimePart *object);
-static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *);
+static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, CamelHeaderRaw *);
static CamelMessageInfo * message_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *);
-static CamelMessageInfo * message_info_new_from_message (CamelFolderSummary *summary, CamelMimeMessage *msg,
const gchar *bodystructure);
-static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);
-
-static CamelMessageContentInfo * content_info_new_from_header (CamelFolderSummary *, struct
_camel_header_raw *);
-static CamelMessageContentInfo * content_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *);
-static CamelMessageContentInfo * content_info_new_from_message (CamelFolderSummary *summary, CamelMimePart
*mp);
-static void content_info_free (CamelFolderSummary *, CamelMessageContentInfo *);
+static CamelMessageInfo * message_info_new_from_message (CamelFolderSummary *summary, CamelMimeMessage *msg);
static gint save_message_infos_to_db (CamelFolderSummary *summary, GError **error);
static gint camel_read_mir_callback (gpointer ref, gint ncol, gchar ** cols, gchar ** name);
static gchar *next_uid_string (CamelFolderSummary *summary);
-static CamelMessageContentInfo * summary_build_content_info (CamelFolderSummary *summary, CamelMessageInfo
*msginfo, CamelMimeParser *mp);
-static CamelMessageContentInfo * summary_build_content_info_message (CamelFolderSummary *summary,
CamelMessageInfo *msginfo, CamelMimePart *object);
-
static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *summary, const gchar *uid);
enum {
@@ -147,18 +135,11 @@ enum {
PROP_DELETED_COUNT,
PROP_JUNK_COUNT,
PROP_JUNK_NOT_DELETED_COUNT,
- PROP_VISIBLE_COUNT,
- PROP_BUILD_CONTENT,
- PROP_NEED_PREVIEW
+ PROP_VISIBLE_COUNT
};
G_DEFINE_TYPE (CamelFolderSummary, camel_folder_summary, G_TYPE_OBJECT)
-G_DEFINE_BOXED_TYPE (CamelMessageInfo,
- camel_message_info,
- camel_message_info_ref,
- camel_message_info_unref)
-
static gboolean
remove_each_item (gpointer uid,
gpointer mi,
@@ -182,8 +163,7 @@ remove_all_loaded (CamelFolderSummary *summary)
g_hash_table_foreach_remove (summary->priv->loaded_infos, remove_each_item, &to_remove_infos);
- g_slist_foreach (to_remove_infos, (GFunc) camel_message_info_unref, NULL);
- g_slist_free (to_remove_infos);
+ g_slist_free_full (to_remove_infos, g_object_unref);
camel_folder_summary_unlock (summary);
}
@@ -242,8 +222,6 @@ folder_summary_finalize (GObject *object)
g_hash_table_foreach (priv->filter_charset, free_o_name, NULL);
g_hash_table_destroy (priv->filter_charset);
- g_hash_table_destroy (priv->preview_updates);
-
g_rec_mutex_clear (&priv->summary_lock);
g_rec_mutex_clear (&priv->filter_lock);
@@ -275,18 +253,6 @@ folder_summary_set_property (GObject *object,
CAMEL_FOLDER_SUMMARY (object),
CAMEL_FOLDER (g_value_get_object (value)));
return;
-
- case PROP_BUILD_CONTENT:
- camel_folder_summary_set_build_content (
- CAMEL_FOLDER_SUMMARY (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_NEED_PREVIEW:
- camel_folder_summary_set_need_preview (
- CAMEL_FOLDER_SUMMARY (object),
- g_value_get_boolean (value));
- return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -347,20 +313,6 @@ folder_summary_get_property (GObject *object,
camel_folder_summary_get_visible_count (
CAMEL_FOLDER_SUMMARY (object)));
return;
-
- case PROP_BUILD_CONTENT:
- g_value_set_boolean (
- value,
- camel_folder_summary_get_build_content (
- CAMEL_FOLDER_SUMMARY (object)));
- return;
-
- case PROP_NEED_PREVIEW:
- g_value_set_boolean (
- value,
- camel_folder_summary_get_need_preview (
- CAMEL_FOLDER_SUMMARY (object)));
- return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -553,282 +505,6 @@ summary_header_to_db (CamelFolderSummary *summary,
return record;
}
-static CamelMessageInfo *
-message_info_from_db (CamelFolderSummary *summary,
- CamelMIRecord *record)
-{
- CamelMessageInfoBase *mi;
- gint i;
- gint count;
- gchar *part, *label;
-
- mi = (CamelMessageInfoBase *) camel_message_info_new (summary);
-
- io (printf ("Loading message info from db\n"));
-
- mi->flags = record->flags;
- mi->size = record->size;
- mi->date_sent = record->dsent;
- mi->date_received = record->dreceived;
-
- mi->uid = (gchar *) camel_pstring_strdup (record->uid);
- mi->subject = (gchar *) camel_pstring_add (record->subject, FALSE);
- mi->from = (gchar *) camel_pstring_add (record->from, FALSE);
- mi->to = (gchar *) camel_pstring_add (record->to, FALSE);
- mi->cc = (gchar *) camel_pstring_add (record->cc, FALSE);
- mi->mlist = (gchar *) camel_pstring_add (record->mlist, FALSE);
-
- /* Evolution itself doesn't yet use this, so we ignore it (saving some memory) */
- mi->bodystructure = NULL;
-
- /* Extract Message id & References */
- mi->content = NULL;
- part = record->part;
- if (part) {
- mi->message_id.id.part.hi = bdata_extract_digit (&part);
- mi->message_id.id.part.lo = bdata_extract_digit (&part);
- count = bdata_extract_digit (&part);
-
- if (count > 0) {
- mi->references = g_malloc (sizeof (*mi->references) + ((count - 1) * sizeof
(mi->references->references[0])));
- mi->references->size = count;
- for (i = 0; i < count; i++) {
- mi->references->references[i].id.part.hi = bdata_extract_digit (&part);
- mi->references->references[i].id.part.lo = bdata_extract_digit (&part);
- }
- } else
- mi->references = NULL;
-
- }
-
- /* Extract User flags/labels */
- part = record->labels;
- if (part) {
- label = part;
- for (i = 0; part[i]; i++) {
-
- if (part[i] == ' ') {
- part[i] = 0;
- camel_flag_set (&mi->user_flags, label, TRUE);
- label = &(part[i + 1]);
- }
- }
- camel_flag_set (&mi->user_flags, label, TRUE);
- }
-
- /* Extract User tags */
- part = record->usertags;
- count = bdata_extract_digit (&part);
- for (i = 0; i < count; i++) {
- gchar *name, *value;
-
- name = bdata_extract_string (&part);
- value = bdata_extract_string (&part);
- camel_tag_set (&mi->user_tags, name, value);
-
- g_free (name);
- g_free (value);
- }
-
- return (CamelMessageInfo *) mi;
-}
-
-static CamelMIRecord *
-message_info_to_db (CamelFolderSummary *summary,
- CamelMessageInfo *info)
-{
- CamelMIRecord *record = g_new0 (CamelMIRecord, 1);
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
- GString *tmp;
- CamelFlag *flag;
- CamelTag *tag;
- gint count, i;
-
- /* Assume that we dont have to take care of DB Safeness. It will be done while doing the DB
transaction */
- record->uid = (gchar *) camel_pstring_strdup (camel_message_info_get_uid (info));
- record->flags = mi->flags;
-
- record->read = ((mi->flags & (CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_JUNK))) ? 1
: 0;
- record->deleted = mi->flags & CAMEL_MESSAGE_DELETED ? 1 : 0;
- record->replied = mi->flags & CAMEL_MESSAGE_ANSWERED ? 1 : 0;
- record->important = mi->flags & CAMEL_MESSAGE_FLAGGED ? 1 : 0;
- record->junk = mi->flags & CAMEL_MESSAGE_JUNK ? 1 : 0;
- record->dirty = mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED ? 1 : 0;
- record->attachment = mi->flags & CAMEL_MESSAGE_ATTACHMENTS ? 1 : 0;
-
- record->size = mi->size;
- record->dsent = mi->date_sent;
- record->dreceived = mi->date_received;
-
- record->subject = (gchar *) camel_pstring_strdup (camel_message_info_get_subject (info));
- record->from = (gchar *) camel_pstring_strdup (camel_message_info_get_from (info));
- record->to = (gchar *) camel_pstring_strdup (camel_message_info_get_to (info));
- record->cc = (gchar *) camel_pstring_strdup (camel_message_info_get_cc (info));
- record->mlist = (gchar *) camel_pstring_strdup (camel_message_info_get_mlist (info));
-
- record->followup_flag = (gchar *) camel_pstring_strdup (camel_message_info_get_user_tag (info,
"follow-up"));
- record->followup_completed_on = (gchar *) camel_pstring_strdup (camel_message_info_get_user_tag
(info, "completed-on"));
- record->followup_due_by = (gchar *) camel_pstring_strdup (camel_message_info_get_user_tag (info,
"due-by"));
-
- record->bodystructure = mi->bodystructure ? g_strdup (mi->bodystructure) : NULL;
-
- tmp = g_string_new (NULL);
- if (mi->references) {
- g_string_append_printf (tmp, "%lu %lu %lu", (gulong) mi->message_id.id.part.hi, (gulong)
mi->message_id.id.part.lo, (gulong) mi->references->size);
- for (i = 0; i < mi->references->size; i++)
- g_string_append_printf (tmp, " %lu %lu", (gulong)
mi->references->references[i].id.part.hi, (gulong) mi->references->references[i].id.part.lo);
- } else {
- g_string_append_printf (tmp, "%lu %lu %lu", (gulong) mi->message_id.id.part.hi, (gulong)
mi->message_id.id.part.lo, (gulong) 0);
- }
- record->part = tmp->str;
- g_string_free (tmp, FALSE);
-
- tmp = g_string_new (NULL);
- flag = mi->user_flags;
- while (flag) {
- g_string_append_printf (tmp, "%s ", flag->name);
- flag = flag->next;
- }
-
- /* Strip off the last space */
- if (tmp->len)
- tmp->len--;
-
- record->labels = tmp->str;
- g_string_free (tmp, FALSE);
-
- tmp = g_string_new (NULL);
- count = camel_tag_list_size (&mi->user_tags);
- g_string_append_printf (tmp, "%lu", (gulong) count);
- tag = mi->user_tags;
- while (tag) {
- /* FIXME: Should we handle empty tags? Can it be empty? If it potential crasher ahead*/
- g_string_append_printf (tmp, " %lu-%s %lu-%s", (gulong) strlen (tag->name), tag->name,
(gulong) strlen (tag->value), tag->value);
- tag = tag->next;
- }
- record->usertags = tmp->str;
- g_string_free (tmp, FALSE);
-
- return record;
-}
-
-static CamelMessageContentInfo *
-content_info_from_db (CamelFolderSummary *summary,
- CamelMIRecord *record)
-{
- CamelMessageContentInfo *ci;
- gchar *type, *subtype;
- guint32 count, i;
- CamelContentType *ct;
- gchar *part = record->cinfo;
-
- io (printf ("Loading content info from db\n"));
-
- if (!part)
- return NULL;
-
- ci = camel_folder_summary_content_info_new (summary);
- if (*part == ' ') part++; /* Move off the space in the record */
-
- type = bdata_extract_string (&part);
- subtype = bdata_extract_string (&part);
- ct = camel_content_type_new (type, subtype);
- g_free (type); /* can this be removed? */
- g_free (subtype);
- count = bdata_extract_digit (&part);
-
- for (i = 0; i < count; i++) {
- gchar *name, *value;
- name = bdata_extract_string (&part);
- value = bdata_extract_string (&part);
-
- camel_content_type_set_param (ct, name, value);
- /* TODO: do this so we dont have to double alloc/free */
- g_free (name);
- g_free (value);
- }
- ci->type = ct;
-
- /* FIXME[disk-summary] move all these to camel pstring */
- ci->id = bdata_extract_string (&part);
- ci->description = bdata_extract_string (&part);
- ci->encoding = bdata_extract_string (&part);
- ci->size = bdata_extract_digit (&part);
-
- record->cinfo = part; /* Keep moving the cursor in the record */
-
- ci->childs = NULL;
-
- return ci;
-}
-
-static gboolean
-content_info_to_db (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci,
- CamelMIRecord *record)
-{
- CamelContentType *ct;
- struct _camel_header_param *hp;
- GString *str = g_string_new (NULL);
- gchar *oldr;
-
- io (printf ("Saving content info to db\n"));
-
- ct = ci->type;
- if (ct) {
- if (ct->type)
- g_string_append_printf (str, " %d-%s", (gint) strlen (ct->type), ct->type);
- else
- g_string_append_printf (str, " 0-");
- if (ct->subtype)
- g_string_append_printf (str, " %d-%s", (gint) strlen (ct->subtype), ct->subtype);
- else
- g_string_append_printf (str, " 0-");
- g_string_append_printf (str, " %d", my_list_size ((struct _node **) &ct->params));
- hp = ct->params;
- while (hp) {
- if (hp->name)
- g_string_append_printf (str, " %d-%s", (gint) strlen (hp->name), hp->name);
- else
- g_string_append_printf (str, " 0-");
- if (hp->value)
- g_string_append_printf (str, " %d-%s", (gint) strlen (hp->value), hp->value);
- else
- g_string_append_printf (str, " 0-");
- hp = hp->next;
- }
- } else {
- g_string_append_printf (str, " %d-", 0);
- g_string_append_printf (str, " %d-", 0);
- g_string_append_printf (str, " %d", 0);
- }
-
- if (ci->id)
- g_string_append_printf (str, " %d-%s", (gint) strlen (ci->id), ci->id);
- else
- g_string_append_printf (str, " 0-");
- if (ci->description)
- g_string_append_printf (str, " %d-%s", (gint) strlen (ci->description), ci->description);
- else
- g_string_append_printf (str, " 0-");
- if (ci->encoding)
- g_string_append_printf (str, " %d-%s", (gint) strlen (ci->encoding), ci->encoding);
- else
- g_string_append_printf (str, " 0-");
- g_string_append_printf (str, " %u", ci->size);
-
- if (record->cinfo) {
- oldr = record->cinfo;
- record->cinfo = g_strconcat (oldr, str->str, NULL);
- g_free (oldr); g_string_free (str, TRUE);
- } else {
- record->cinfo = str->str;
- g_string_free (str, FALSE);
- }
-
- return TRUE;
-}
-
/**
* camel_folder_summary_replace_flags:
* @summary: a #CamelFolderSummary
@@ -915,231 +591,6 @@ camel_folder_summary_replace_flags (CamelFolderSummary *summary,
return changed;
}
-static CamelMessageInfo *
-message_info_clone (CamelFolderSummary *summary,
- const CamelMessageInfo *mi)
-{
- CamelMessageInfoBase *to, *from = (CamelMessageInfoBase *) mi;
- CamelFlag *flag;
- CamelTag *tag;
-
- to = (CamelMessageInfoBase *) camel_message_info_new (summary);
-
- to->flags = from->flags;
- to->size = from->size;
- to->date_sent = from->date_sent;
- to->date_received = from->date_received;
- to->refcount = 1;
-
- /* NB: We don't clone the uid */
-
- to->subject = camel_pstring_strdup (from->subject);
- to->from = camel_pstring_strdup (from->from);
- to->to = camel_pstring_strdup (from->to);
- to->cc = camel_pstring_strdup (from->cc);
- to->mlist = camel_pstring_strdup (from->mlist);
- memcpy (&to->message_id, &from->message_id, sizeof (to->message_id));
- to->preview = g_strdup (from->preview);
- if (from->references) {
- gint len = sizeof (*from->references) + ((from->references->size - 1) * sizeof
(from->references->references[0]));
-
- to->references = g_malloc (len);
- memcpy (to->references, from->references, len);
- }
-
- flag = from->user_flags;
- while (flag) {
- camel_flag_set (&to->user_flags, flag->name, TRUE);
- flag = flag->next;
- }
-
- tag = from->user_tags;
- while (tag) {
- camel_tag_set (&to->user_tags, tag->name, tag->value);
- tag = tag->next;
- }
-
- if (from->content) {
- /* FIXME: copy content-infos */
- }
-
- return (CamelMessageInfo *) to;
-}
-
-static gconstpointer
-info_ptr (const CamelMessageInfo *mi,
- gint id)
-{
- switch (id) {
- case CAMEL_MESSAGE_INFO_SUBJECT:
- return ((const CamelMessageInfoBase *) mi)->subject;
- case CAMEL_MESSAGE_INFO_FROM:
- return ((const CamelMessageInfoBase *) mi)->from;
- case CAMEL_MESSAGE_INFO_TO:
- return ((const CamelMessageInfoBase *) mi)->to;
- case CAMEL_MESSAGE_INFO_CC:
- return ((const CamelMessageInfoBase *) mi)->cc;
- case CAMEL_MESSAGE_INFO_MLIST:
- return ((const CamelMessageInfoBase *) mi)->mlist;
- case CAMEL_MESSAGE_INFO_MESSAGE_ID:
- return &((const CamelMessageInfoBase *) mi)->message_id;
- case CAMEL_MESSAGE_INFO_REFERENCES:
- return ((const CamelMessageInfoBase *) mi)->references;
- case CAMEL_MESSAGE_INFO_USER_FLAGS:
- return ((const CamelMessageInfoBase *) mi)->user_flags;
- case CAMEL_MESSAGE_INFO_USER_TAGS:
- return ((const CamelMessageInfoBase *) mi)->user_tags;
- case CAMEL_MESSAGE_INFO_HEADERS:
- return ((const CamelMessageInfoBase *) mi)->headers;
- case CAMEL_MESSAGE_INFO_CONTENT:
- return ((const CamelMessageInfoBase *) mi)->content;
- case CAMEL_MESSAGE_INFO_PREVIEW:
- return ((const CamelMessageInfoBase *) mi)->preview;
- default:
- g_return_val_if_reached (NULL);
- }
-}
-
-static guint32
-info_uint32 (const CamelMessageInfo *mi,
- gint id)
-{
- switch (id) {
- case CAMEL_MESSAGE_INFO_FLAGS:
- return ((const CamelMessageInfoBase *) mi)->flags;
- case CAMEL_MESSAGE_INFO_SIZE:
- return ((const CamelMessageInfoBase *) mi)->size;
- default:
- g_return_val_if_reached (0);
- }
-}
-
-static time_t
-info_time (const CamelMessageInfo *mi,
- gint id)
-{
- switch (id) {
- case CAMEL_MESSAGE_INFO_DATE_SENT:
- return ((const CamelMessageInfoBase *) mi)->date_sent;
- case CAMEL_MESSAGE_INFO_DATE_RECEIVED:
- return ((const CamelMessageInfoBase *) mi)->date_received;
- default:
- g_return_val_if_reached (0);
- }
-}
-
-static gboolean
-info_user_flag (const CamelMessageInfo *mi,
- const gchar *id)
-{
- return camel_flag_get (&((CamelMessageInfoBase *) mi)->user_flags, id);
-}
-
-static const gchar *
-info_user_tag (const CamelMessageInfo *mi,
- const gchar *id)
-{
- return camel_tag_get (&((CamelMessageInfoBase *) mi)->user_tags, id);
-}
-
-static gboolean
-info_set_user_flag (CamelMessageInfo *info,
- const gchar *name,
- gboolean value)
-{
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
- gint res;
-
- res = camel_flag_set (&mi->user_flags, name, value);
-
- if (mi->summary && res && mi->summary->priv->folder && mi->uid
- && camel_folder_summary_check_uid (mi->summary, mi->uid)) {
- CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
-
- mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
- mi->dirty = TRUE;
- camel_folder_summary_touch (mi->summary);
- camel_folder_change_info_change_uid (changes, camel_message_info_get_uid (info));
- camel_folder_changed (mi->summary->priv->folder, changes);
- camel_folder_change_info_free (changes);
- }
-
- return res;
-}
-
-static gboolean
-info_set_user_tag (CamelMessageInfo *info,
- const gchar *name,
- const gchar *value)
-{
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
- gint res;
-
- res = camel_tag_set (&mi->user_tags, name, value);
-
- if (mi->summary && res && mi->summary->priv->folder && mi->uid
- && camel_folder_summary_check_uid (mi->summary, mi->uid)) {
- CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
-
- mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
- mi->dirty = TRUE;
- camel_folder_summary_touch (mi->summary);
- camel_folder_change_info_change_uid (changes, camel_message_info_get_uid (info));
- camel_folder_changed (mi->summary->priv->folder, changes);
- camel_folder_change_info_free (changes);
- }
-
- return res;
-}
-
-static gboolean
-info_set_flags (CamelMessageInfo *info,
- guint32 flags,
- guint32 set)
-{
- guint32 old;
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
- gboolean counts_changed = FALSE;
-
- old = camel_message_info_get_flags (info);
- mi->flags = (old & ~flags) | (set & flags);
- if (old != mi->flags) {
- mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
- mi->dirty = TRUE;
- if (mi->summary)
- camel_folder_summary_touch (mi->summary);
- }
-
- if (mi->summary) {
- camel_folder_summary_lock (mi->summary);
- g_object_freeze_notify (G_OBJECT (mi->summary));
- counts_changed = camel_folder_summary_replace_flags (mi->summary, info);
- }
-
- if (!counts_changed && ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags &
~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK))) {
- if (mi->summary) {
- g_object_thaw_notify (G_OBJECT (mi->summary));
- camel_folder_summary_unlock (mi->summary);
- }
- return FALSE;
- }
-
- if (mi->summary) {
- g_object_thaw_notify (G_OBJECT (mi->summary));
- camel_folder_summary_unlock (mi->summary);
- }
-
- if (mi->summary && mi->summary->priv->folder && mi->uid) {
- CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
-
- camel_folder_change_info_change_uid (changes, camel_message_info_get_uid (info));
- camel_folder_changed (mi->summary->priv->folder, changes);
- camel_folder_change_info_free (changes);
- }
-
- return TRUE;
-}
-
static void
camel_folder_summary_class_init (CamelFolderSummaryClass *class)
{
@@ -1153,41 +604,18 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class)
object_class->dispose = folder_summary_dispose;
object_class->finalize = folder_summary_finalize;
- class->message_info_size = sizeof (CamelMessageInfoBase);
- class->content_info_size = sizeof (CamelMessageContentInfo);
+ class->message_info_type = CAMEL_TYPE_MESSAGE_INFO_BASE;
class->summary_header_from_db = summary_header_from_db;
class->summary_header_to_db = summary_header_to_db;
- class->message_info_from_db = message_info_from_db;
- class->message_info_to_db = message_info_to_db;
- class->content_info_from_db = content_info_from_db;
- class->content_info_to_db = content_info_to_db;
class->message_info_new_from_header = message_info_new_from_header;
class->message_info_new_from_parser = message_info_new_from_parser;
class->message_info_new_from_message = message_info_new_from_message;
- class->message_info_free = message_info_free;
- class->message_info_clone = message_info_clone;
class->message_info_from_uid = message_info_from_uid;
- class->content_info_new_from_header = content_info_new_from_header;
- class->content_info_new_from_parser = content_info_new_from_parser;
- class->content_info_new_from_message = content_info_new_from_message;
- class->content_info_free = content_info_free;
-
class->next_uid_string = next_uid_string;
- class->info_ptr = info_ptr;
- class->info_uint32 = info_uint32;
- class->info_time = info_time;
- class->info_user_flag = info_user_flag;
- class->info_user_tag = info_user_tag;
-
- class->info_set_user_flag = info_set_user_flag;
- class->info_set_user_tag = info_set_user_tag;
-
- class->info_set_flags = info_set_flags;
-
/**
* CamelFolderSummary:folder
*
@@ -1293,35 +721,6 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class)
"How many visible (not deleted and not junk) infos is saved in a summary",
0, G_MAXUINT32,
0, G_PARAM_READABLE));
-
- /**
- * CamelFolderSummary:build-content
- *
- * Whether to build CamelMessageInfo.content.
- **/
- g_object_class_install_property (
- object_class,
- PROP_BUILD_CONTENT,
- g_param_spec_boolean (
- "build-content",
- "Build content",
- "Whether to build CamelMessageInfo.content",
- FALSE,
- G_PARAM_READWRITE));
-
- /**
- * CamelFolderSummary:need-preview
- *
- **/
- g_object_class_install_property (
- object_class,
- PROP_NEED_PREVIEW,
- g_param_spec_boolean (
- "need-preview",
- "Need preview",
- "",
- FALSE,
- G_PARAM_READWRITE));
}
static void
@@ -1336,9 +735,6 @@ camel_folder_summary_init (CamelFolderSummary *summary)
summary->priv->filter_charset = g_hash_table_new (
camel_strcase_hash, camel_strcase_equal);
- summary->priv->need_preview = FALSE;
- summary->priv->preview_updates = g_hash_table_new (g_str_hash, g_str_equal);
-
summary->priv->nextuid = 1;
summary->priv->uids = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)
camel_pstring_free, NULL);
summary->priv->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal);
@@ -1352,7 +748,7 @@ camel_folder_summary_init (CamelFolderSummary *summary)
/**
* camel_folder_summary_new:
- * @folder: parent #CamelFolder object
+ * @folder: (type CamelFolder): parent #CamelFolder object
*
* Create a new #CamelFolderSummary object.
*
@@ -1483,8 +879,6 @@ camel_folder_summary_get_visible_count (CamelFolderSummary *summary)
*
* Set the index used to index body content. If the index is %NULL, or
* not set (the default), no indexing of body content will take place.
- *
- * Unlike earlier behaviour, build_content need not be set to perform indexing.
**/
void
camel_folder_summary_set_index (CamelFolderSummary *summary,
@@ -1518,72 +912,6 @@ camel_folder_summary_get_index (CamelFolderSummary *summary)
}
/**
- * camel_folder_summary_set_build_content:
- * @summary: a #CamelFolderSummary object
- * @state: to build or not to build the content
- *
- * Set a flag to tell the summary to build the content info summary
- * (#CamelMessageInfo.content). The default is not to build content
- * info summaries.
- **/
-void
-camel_folder_summary_set_build_content (CamelFolderSummary *summary,
- gboolean state)
-{
- g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary));
-
- if (summary->priv->build_content == state)
- return;
-
- summary->priv->build_content = state;
-
- g_object_notify (G_OBJECT (summary), "build-content");
-}
-
-/**
- * camel_folder_summary_get_build_content:
- * @summary: a #CamelFolderSummary object
- *
- * Returns: Whether to build #CamelMessageInfo.content.
- *
- * Since: 3.4
- **/
-gboolean
-camel_folder_summary_get_build_content (CamelFolderSummary *summary)
-{
- g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), FALSE);
-
- return summary->priv->build_content;
-}
-
-/**
- * camel_folder_summary_set_need_preview:
- *
- * Since: 2.28
- **/
-void
-camel_folder_summary_set_need_preview (CamelFolderSummary *summary,
- gboolean preview)
-{
- g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary));
-
- summary->priv->need_preview = preview;
-}
-
-/**
- * camel_folder_summary_get_need_preview:
- *
- * Since: 2.28
- **/
-gboolean
-camel_folder_summary_get_need_preview (CamelFolderSummary *summary)
-{
- g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), FALSE);
-
- return summary->priv->need_preview;
-}
-
-/**
* camel_folder_summary_next_uid:
* @summary: a #CamelFolderSummary object
*
@@ -1824,6 +1152,7 @@ camel_folder_summary_get_hash (CamelFolderSummary *summary)
/**
* camel_folder_summary_peek_loaded:
*
+ * Returns: (nullable) (transfer full):
* Since: 2.26
**/
CamelMessageInfo *
@@ -1837,7 +1166,7 @@ camel_folder_summary_peek_loaded (CamelFolderSummary *summary,
info = g_hash_table_lookup (summary->priv->loaded_infos, uid);
if (info)
- camel_message_info_ref (info);
+ g_object_ref (info);
return info;
}
@@ -1906,7 +1235,7 @@ message_info_from_uid (CamelFolderSummary *summary,
}
if (info)
- camel_message_info_ref (info);
+ g_object_ref (info);
camel_folder_summary_unlock (summary);
@@ -1923,7 +1252,7 @@ message_info_from_uid (CamelFolderSummary *summary,
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
*
- * Returns: the summary item, or %NULL if the uid @uid is not available
+ * Returns: (nullable) (transfer full): the summary item, or %NULL if the uid @uid is not available
*
* See camel_folder_summary_get_info_flags().
*
@@ -1978,49 +1307,16 @@ camel_folder_summary_get_info_flags (CamelFolderSummary *summary,
return GPOINTER_TO_UINT (ptr_flags);
}
-static CamelMessageContentInfo *
-perform_content_info_load_from_db (CamelFolderSummary *summary,
- CamelMIRecord *mir)
-{
- gint i;
- guint32 count;
- CamelMessageContentInfo *ci, *pci;
- gchar *part;
-
- ci = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_from_db (summary, mir);
- if (ci == NULL)
- return NULL;
- part = mir->cinfo;
- if (!part)
- return ci;
- if (*part == ' ') part++;
- count = bdata_extract_digit (&part);
-
- mir->cinfo = part;
- for (i = 0; i < count; i++) {
- pci = perform_content_info_load_from_db (summary, mir);
- if (pci ) {
- my_list_append ((struct _node **) &ci->childs, (struct _node *) pci);
- pci->parent = ci;
- } else {
- d (fprintf (stderr, "Summary file format messed up?"));
- camel_folder_summary_content_info_free (summary, ci);
- return NULL;
- }
- }
- return ci;
-}
-
static void
gather_dirty_or_flagged_uids (gpointer key,
gpointer value,
gpointer user_data)
{
const gchar *uid = key;
- CamelMessageInfoBase *info = value;
+ CamelMessageInfo *info = value;
GHashTable *hash = user_data;
- if (info->dirty || (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0)
+ if (camel_message_info_get_dirty (info) || (camel_message_info_get_flags (info) &
CAMEL_MESSAGE_FOLDER_FLAGGED) != 0)
g_hash_table_insert (hash, (gpointer) camel_pstring_strdup (uid), GINT_TO_POINTER (1));
}
@@ -2067,10 +1363,10 @@ camel_folder_summary_get_changed (CamelFolderSummary *summary)
static void
count_changed_uids (gchar *key,
- CamelMessageInfoBase *info,
+ CamelMessageInfo *info,
gint *count)
{
- if (info->dirty)
+ if (camel_message_info_get_dirty (info))
(*count)++;
}
@@ -2088,10 +1384,10 @@ cfs_count_dirty (CamelFolderSummary *summary)
static gboolean
remove_item (gchar *uid,
- CamelMessageInfoBase *info,
+ CamelMessageInfo *info,
GSList **to_remove_infos)
{
- if (info->refcount == 1 && !info->dirty && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) {
+ if (G_OBJECT (info)->ref_count == 1 && !camel_message_info_get_dirty (info) &&
(camel_message_info_get_flags (info) & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) {
*to_remove_infos = g_slist_prepend (*to_remove_infos, info);
return TRUE;
}
@@ -2116,8 +1412,7 @@ remove_cache (CamelSession *session,
g_hash_table_foreach_remove (summary->priv->loaded_infos, (GHRFunc) remove_item, &to_remove_infos);
- g_slist_foreach (to_remove_infos, (GFunc) camel_message_info_unref, NULL);
- g_slist_free (to_remove_infos);
+ g_slist_free_full (to_remove_infos, g_object_unref);
camel_folder_summary_unlock (summary);
@@ -2254,115 +1549,6 @@ cfs_cache_size (CamelFolderSummary *summary)
return g_hash_table_size (summary->priv->uids);
}
-/* Update preview of cached messages */
-
-static void
-msg_update_preview (const gchar *uid,
- gpointer value,
- CamelFolder *folder)
-{
- CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid);
- CamelMimeMessage *msg;
- CamelStore *parent_store;
- const gchar *full_name;
-
- full_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
-
- /* FIXME Pass a GCancellable */
- msg = camel_folder_get_message_sync (folder, uid, NULL, NULL);
- if (msg != NULL) {
- if (camel_mime_message_build_preview ((CamelMimePart *) msg, (CamelMessageInfo *) info) &&
info->preview) {
- if (parent_store && !is_in_memory_summary (folder->summary))
- camel_db_write_preview_record (parent_store->cdb_w, full_name, info->uid,
info->preview, NULL);
- }
- }
- camel_message_info_unref (info);
-}
-
-static void
-pick_uids (const gchar *uid,
- CamelMessageInfoBase *mi,
- GPtrArray *array)
-{
- if (mi->preview)
- g_ptr_array_add (array, (gchar *) camel_pstring_strdup (uid));
-}
-
-static void
-copy_all_uids_to_hash (gpointer uid,
- gpointer hash)
-{
- g_return_if_fail (uid != NULL);
-
- g_hash_table_insert (hash, (gchar *) camel_pstring_strdup (uid), GINT_TO_POINTER (1));
-}
-
-static gboolean
-fill_mi (const gchar *uid,
- const gchar *msg,
- CamelFolder *folder)
-{
- CamelMessageInfoBase *info;
-
- info = g_hash_table_lookup (folder->summary->priv->loaded_infos, uid);
- if (info) /* We re assign the memory of msg */
- info->preview = (gchar *) msg;
- camel_pstring_free (uid); /* unref the uid */
-
- return TRUE;
-}
-
-static void
-preview_update (CamelSession *session,
- GCancellable *cancellable,
- CamelFolder *folder,
- GError **error)
-{
- /* FIXME: Either lock & use or copy & use.*/
- GPtrArray *uids_uncached, *uids_array;
- GHashTable *preview_data, *uids_hash;
- CamelStore *parent_store;
- const gchar *full_name;
- gboolean is_in_memory = is_in_memory_summary (folder->summary);
- gint i;
-
- uids_array = camel_folder_summary_get_array (folder->summary);
- uids_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free,
NULL);
- g_ptr_array_foreach (uids_array, copy_all_uids_to_hash, uids_hash);
- uids_uncached = camel_folder_get_uncached_uids (folder, uids_array, NULL);
- camel_folder_summary_free_array (uids_array);
- uids_array = NULL;
-
- full_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
- preview_data = (!parent_store || is_in_memory) ? NULL : camel_db_get_folder_preview
(parent_store->cdb_r, full_name, NULL);
- if (preview_data) {
- g_hash_table_foreach_remove (preview_data, (GHRFunc) fill_mi, folder);
- g_hash_table_destroy (preview_data);
- }
-
- camel_folder_summary_lock (folder->summary);
- g_hash_table_foreach (folder->summary->priv->loaded_infos, (GHFunc) pick_uids, uids_uncached);
- camel_folder_summary_unlock (folder->summary);
-
- for (i = 0; i < uids_uncached->len; i++) {
- g_hash_table_remove (uids_hash, uids_uncached->pdata[i]);
- }
-
- camel_folder_lock (folder);
- if (parent_store && !is_in_memory)
- camel_db_begin_transaction (parent_store->cdb_w, NULL);
- g_hash_table_foreach (uids_hash, (GHFunc) msg_update_preview, folder);
- if (parent_store && !is_in_memory)
- camel_db_end_transaction (parent_store->cdb_w, NULL);
- camel_folder_unlock (folder);
- camel_folder_free_uids (folder, uids_uncached);
- g_hash_table_destroy (uids_hash);
-}
-
-/* end */
-
static void
cfs_reload_from_db (CamelFolderSummary *summary,
GError **error)
@@ -2398,54 +1584,6 @@ cfs_reload_from_db (CamelFolderSummary *summary,
g_hash_table_destroy (data.columns_hash);
cfs_schedule_info_release_timer (summary);
-
- /* FIXME Convert this to a GTask, submitted through
- * camel_service_queue_task(). Then it won't
- * have to call camel_folder_lock/unlock(). */
- if (summary->priv->need_preview) {
- CamelSession *session;
-
- /* This may not be available in a case of this being called as part
- of CamelSession's dispose, because the CamelService uses GWeakRef
- object which is invalidates its content when it reaches the dispose. */
- session = camel_service_ref_session (CAMEL_SERVICE (parent_store));
- if (session) {
- gchar *description;
-
- /* Translators: The first '%s' is replaced with an account name and the second '%s'
- is replaced with a full path name. The spaces around ':' are intentional, as
- the whole '%s : %s' is meant as an absolute identification of the folder. */
- description = g_strdup_printf (_("Update preview data for folder '%s : %s'"),
- camel_service_get_display_name (CAMEL_SERVICE (parent_store)),
- camel_folder_get_full_name (summary->priv->folder));
-
- camel_session_submit_job (
- session, description,
- (CamelSessionCallback) preview_update,
- g_object_ref (summary->priv->folder),
- (GDestroyNotify) g_object_unref);
-
- g_object_unref (session);
- g_free (description);
- }
- }
-
- return;
-}
-
-/**
- * camel_folder_summary_add_preview:
- *
- * Since: 2.28
- **/
-void
-camel_folder_summary_add_preview (CamelFolderSummary *summary,
- CamelMessageInfo *info)
-{
- camel_folder_summary_lock (summary);
- g_hash_table_insert (summary->priv->preview_updates, (gchar *) info->uid, ((CamelMessageInfoBase *)
info)->preview);
- camel_folder_summary_touch (summary);
- camel_folder_summary_unlock (summary);
}
/**
@@ -2539,6 +1677,7 @@ camel_folder_summary_load_from_db (CamelFolderSummary *summary,
return ret == 0;
}
+/* Beware, it only borrows pointers from 'cols' here */
static void
mir_from_cols (CamelMIRecord *mir,
CamelFolderSummary *summary,
@@ -2555,80 +1694,76 @@ mir_from_cols (CamelMIRecord *mir,
switch (camel_db_get_column_ident (columns_hash, i, ncol, name)) {
case CAMEL_DB_COLUMN_UID:
- mir->uid = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->uid = cols[i];
break;
case CAMEL_DB_COLUMN_FLAGS:
- mir->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+ mir->flags = cols[i] ? g_ascii_strtoull (cols[i], NULL, 10) : 0;
break;
case CAMEL_DB_COLUMN_READ:
- mir->read = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) :
FALSE;
+ mir->read = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_DELETED:
- mir->deleted = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE))
: FALSE;
+ mir->deleted = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_REPLIED:
- mir->replied = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE))
: FALSE;
+ mir->replied = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_IMPORTANT:
- mir->important = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
+ mir->important = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ? TRUE
: FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_JUNK:
- mir->junk = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) :
FALSE;
+ mir->junk = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_ATTACHMENT:
- mir->attachment = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE :
FALSE)) : FALSE;
+ mir->attachment = (cols[i]) ? ( ((g_ascii_strtoull (cols[i], NULL, 10)) ?
TRUE : FALSE)) : FALSE;
break;
case CAMEL_DB_COLUMN_SIZE:
- mir->size = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
+ mir->size = cols[i] ? g_ascii_strtoull (cols[i], NULL, 10) : 0;
break;
case CAMEL_DB_COLUMN_DSENT:
- mir->dsent = cols[i] ? strtol (cols[i], NULL, 10) : 0;
+ mir->dsent = cols[i] ? g_ascii_strtoll (cols[i], NULL, 10) : 0;
break;
case CAMEL_DB_COLUMN_DRECEIVED:
- mir->dreceived = cols[i] ? strtol (cols[i], NULL, 10) : 0;
+ mir->dreceived = cols[i] ? g_ascii_strtoll (cols[i], NULL, 10) : 0;
break;
case CAMEL_DB_COLUMN_SUBJECT:
- mir->subject = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->subject = cols[i];
break;
case CAMEL_DB_COLUMN_MAIL_FROM:
- mir->from = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->from = cols[i];
break;
case CAMEL_DB_COLUMN_MAIL_TO:
- mir->to = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->to = cols[i];
break;
case CAMEL_DB_COLUMN_MAIL_CC:
- mir->cc = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->cc = cols[i];
break;
case CAMEL_DB_COLUMN_MLIST:
- mir->mlist = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->mlist = cols[i];
break;
case CAMEL_DB_COLUMN_FOLLOWUP_FLAG:
- mir->followup_flag = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->followup_flag = cols[i];
break;
case CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON:
- mir->followup_completed_on = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->followup_completed_on = cols[i];
break;
case CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY:
- mir->followup_due_by = (gchar *) camel_pstring_strdup (cols[i]);
+ mir->followup_due_by = cols[i];
break;
case CAMEL_DB_COLUMN_PART:
- mir->part = g_strdup (cols[i]);
+ mir->part = cols[i];
break;
case CAMEL_DB_COLUMN_LABELS:
- mir->labels = g_strdup (cols[i]);
+ mir->labels = cols[i];
break;
case CAMEL_DB_COLUMN_USERTAGS:
- mir->usertags = g_strdup (cols[i]);
+ mir->usertags = cols[i];
break;
case CAMEL_DB_COLUMN_CINFO:
- mir->cinfo = g_strdup (cols[i]);
+ mir->cinfo = cols[i];
break;
case CAMEL_DB_COLUMN_BDATA:
- mir->bdata = g_strdup (cols[i]);
- break;
- case CAMEL_DB_COLUMN_BODYSTRUCTURE:
- /* Evolution itself doesn't yet use this, ignoring */
- /* mir->bodystructure = g_strdup (cols[i]); */
+ mir->bdata = cols[i];
break;
default:
g_warn_if_reached ();
@@ -2645,133 +1780,105 @@ camel_read_mir_callback (gpointer ref,
{
struct _db_pass_data *data = (struct _db_pass_data *) ref;
CamelFolderSummary *summary = data->summary;
- CamelMIRecord *mir;
+ CamelMIRecord mir;
CamelMessageInfo *info;
+ gchar *bdata_ptr;
gint ret = 0;
- mir = g_new0 (CamelMIRecord , 1);
- mir_from_cols (mir, summary, &data->columns_hash, ncol, cols, name);
+ memset (&mir, 0, sizeof (CamelMIRecord));
+
+ /* As mir_from_cols() only borrows data from cols, no need to free mir */
+ mir_from_cols (&mir, summary, &data->columns_hash, ncol, cols, name);
camel_folder_summary_lock (summary);
- if (!mir->uid || g_hash_table_lookup (summary->priv->loaded_infos, mir->uid)) {
+ if (!mir.uid || g_hash_table_lookup (summary->priv->loaded_infos, mir.uid)) {
/* Unlock and better return */
camel_folder_summary_unlock (summary);
- camel_db_camel_mir_free (mir);
return ret;
}
camel_folder_summary_unlock (summary);
- info = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_from_db (summary, mir);
-
- if (info) {
-
- if (summary->priv->build_content) {
- gchar *tmp;
- tmp = mir->cinfo;
- /* FIXME: this should be done differently, how i don't know */
- ((CamelMessageInfoBase *) info)->content = perform_content_info_load_from_db
(summary, mir);
- if (((CamelMessageInfoBase *) info)->content == NULL) {
- camel_message_info_unref (info);
- info = NULL;
- }
- mir->cinfo = tmp;
-
- if (!info) {
- camel_db_camel_mir_free (mir);
- return -1;
- }
- }
-
+ info = camel_message_info_new (summary);
+ bdata_ptr = mir.bdata;
+ if (camel_message_info_load (info, &mir, &bdata_ptr)) {
/* Just now we are reading from the DB, it can't be dirty. */
- ((CamelMessageInfoBase *) info)->dirty = FALSE;
- if (data->add)
- camel_folder_summary_add (summary, info);
- else
- camel_folder_summary_insert (summary, info, TRUE);
-
+ camel_message_info_set_dirty (info, FALSE);
+ if (data->add) {
+ camel_folder_summary_add (summary, info, FALSE);
+ g_clear_object (&info);
+ } else {
+ camel_folder_summary_lock (summary);
+ /* Summary always holds a ref for the loaded infos; this consumes it */
+ g_hash_table_insert (summary->priv->loaded_infos, (gchar *)
camel_message_info_get_uid (info), info);
+ camel_folder_summary_unlock (summary);
+ }
} else {
+ g_clear_object (&info);
g_warning ("Loading messageinfo from db failed");
ret = -1;
}
- camel_db_camel_mir_free (mir);
-
return ret;
}
-/* saves the content descriptions, recursively */
-static gboolean
-perform_content_info_save_to_db (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci,
- CamelMIRecord *record)
-{
- CamelMessageContentInfo *part;
- gchar *oldr;
-
- if (!CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_to_db (summary, ci, record))
- return FALSE;
-
- oldr = record->cinfo;
- record->cinfo = g_strdup_printf ("%s %d", oldr, my_list_size ((struct _node **) &ci->childs));
- g_free (oldr);
-
- part = ci->childs;
- while (part) {
- if (perform_content_info_save_to_db (summary, part, record) == -1)
- return FALSE;
- part = part->next;
- }
-
- return TRUE;
-}
-
static void
save_to_db_cb (gpointer key,
gpointer value,
gpointer data)
{
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) value;
- CamelFolderSummary *summary = (CamelFolderSummary *) mi->summary;
+ CamelMessageInfo *mi = value;
+ CamelFolderSummary *summary;
CamelStore *parent_store;
const gchar *full_name;
CamelDB *cdb;
CamelMIRecord *mir;
+ GString *bdata_str;
GError **error = data;
+ if (!camel_message_info_get_dirty (mi))
+ return;
+
+ summary = camel_message_info_ref_summary (mi);
+ if (!summary)
+ return;
+
full_name = camel_folder_get_full_name (summary->priv->folder);
parent_store = camel_folder_get_parent_store (summary->priv->folder);
- if (!parent_store)
+ if (!parent_store) {
+ g_clear_object (&summary);
return;
+ }
cdb = parent_store->cdb_w;
- if (!mi->dirty)
- return;
+ mir = g_new0 (CamelMIRecord, 1);
+ bdata_str = g_string_new (NULL);
- mir = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_to_db (summary, (CamelMessageInfo *) mi);
-
- if (mir && summary->priv->build_content) {
- if (!perform_content_info_save_to_db (summary, ((CamelMessageInfoBase *) mi)->content, mir)) {
- g_warning ("unable to save mir+cinfo for uid: %s\n", mir->uid);
- camel_db_camel_mir_free (mir);
- /* FIXME: Add exception here */
- return;
- }
+ if (!camel_message_info_save (mi, mir, bdata_str)) {
+ g_warning ("Failed to save message info: %s\n", camel_message_info_get_uid (mi));
+ g_string_free (bdata_str, TRUE);
+ camel_db_camel_mir_free (mir);
+ g_clear_object (&summary);
+ return;
}
- g_return_if_fail (mir != NULL);
+ g_warn_if_fail (mir->bdata == NULL);
+ mir->bdata = g_string_free (bdata_str, FALSE);
+ bdata_str = NULL;
if (camel_db_write_message_info_record (cdb, full_name, mir, error) != 0) {
camel_db_camel_mir_free (mir);
+ g_clear_object (&summary);
return;
}
/* Reset the dirty flag which decides if the changes are synced to the DB or not.
The FOLDER_FLAGGED should be used to check if the changes are synced to the server.
So, dont unset the FOLDER_FLAGGED flag */
- mi->dirty = FALSE;
+ camel_message_info_set_dirty (mi, FALSE);
camel_db_camel_mir_free (mir);
+ g_clear_object (&summary);
}
static gint
@@ -2808,23 +1915,6 @@ save_message_infos_to_db (CamelFolderSummary *summary,
return 0;
}
-static void
-msg_save_preview (const gchar *uid,
- gpointer value,
- CamelFolder *folder)
-{
- CamelStore *parent_store;
- const gchar *full_name;
-
- full_name = camel_folder_get_full_name (folder);
- parent_store = camel_folder_get_parent_store (folder);
-
- if (parent_store) {
- camel_db_write_preview_record (
- parent_store->cdb_w, full_name, uid, (gchar *) value, NULL);
- }
-}
-
/**
* camel_folder_summary_save_to_db:
*
@@ -2854,12 +1944,6 @@ camel_folder_summary_save_to_db (CamelFolderSummary *summary,
camel_folder_summary_lock (summary);
d (printf ("\ncamel_folder_summary_save_to_db called \n"));
- if (summary->priv->need_preview && g_hash_table_size (summary->priv->preview_updates)) {
- camel_db_begin_transaction (parent_store->cdb_w, NULL);
- g_hash_table_foreach (summary->priv->preview_updates, (GHFunc) msg_save_preview,
summary->priv->folder);
- g_hash_table_remove_all (summary->priv->preview_updates);
- camel_db_end_transaction (parent_store->cdb_w, NULL);
- }
summary->flags &= ~CAMEL_FOLDER_SUMMARY_DIRTY;
@@ -3020,35 +2104,51 @@ static gboolean
summary_assign_uid (CamelFolderSummary *summary,
CamelMessageInfo *info)
{
- const gchar *uid;
+ const gchar *info_uid;
+ gchar *new_uid;
CamelMessageInfo *mi;
- uid = camel_message_info_get_uid (info);
+ camel_message_info_set_abort_notifications (info, TRUE);
+ camel_message_info_property_lock (info);
+
+ info_uid = camel_message_info_get_uid (info);
+
+ if (!info_uid || !*info_uid) {
+ new_uid = camel_folder_summary_next_uid_string (summary);
- if (uid == NULL || uid[0] == 0) {
- camel_pstring_free (info->uid);
- uid = info->uid = (gchar *) camel_pstring_add (camel_folder_summary_next_uid_string
(summary), TRUE);
+ camel_message_info_set_uid (info, new_uid);
+ } else {
+ new_uid = g_strdup (info_uid);
}
camel_folder_summary_lock (summary);
- while ((mi = g_hash_table_lookup (summary->priv->loaded_infos, uid))) {
+ while ((mi = g_hash_table_lookup (summary->priv->loaded_infos, new_uid))) {
camel_folder_summary_unlock (summary);
- if (mi == info)
+ g_free (new_uid);
+
+ if (mi == info) {
+ camel_message_info_property_unlock (info);
return FALSE;
+ }
d (printf ("Trying to insert message with clashing uid (%s). new uid re-assigned",
camel_message_info_get_uid (info)));
- camel_pstring_free (info->uid);
- uid = info->uid = camel_pstring_add (camel_folder_summary_next_uid_string (summary), TRUE);
- camel_message_info_set_flags (info, CAMEL_MESSAGE_FOLDER_FLAGGED,
CAMEL_MESSAGE_FOLDER_FLAGGED);
+ new_uid = camel_folder_summary_next_uid_string (summary);
+ camel_message_info_set_uid (info, new_uid);
+ camel_message_info_set_folder_flagged (info, TRUE);
camel_folder_summary_lock (summary);
}
+ g_free (new_uid);
+
camel_folder_summary_unlock (summary);
+ camel_message_info_property_unlock (info);
+ camel_message_info_set_abort_notifications (info, FALSE);
+
return TRUE;
}
@@ -3056,36 +2156,47 @@ summary_assign_uid (CamelFolderSummary *summary,
* camel_folder_summary_add:
* @summary: a #CamelFolderSummary object
* @info: a #CamelMessageInfo
+ * @force_keep_uid: whether to keep set UID of the @info
*
- * Adds a new @info record to the summary. If @info->uid is %NULL,
+ * Adds a new @info record to the summary. If the @force_keep_uid is %FALSE,
* then a new uid is automatically re-assigned by calling
- * camel_folder_summary_next_uid_string().
+ * camel_folder_summary_next_uid_string(). It's an error to to use
+ * @force_keep_uid whe nthe @info has none set.
*
- * The @info record should have been generated by calling one of the
- * info_new_*() functions, as it will be free'd based on the summary
- * class. And MUST NOT be allocated directly using malloc.
+ * The @summary adds its own reference to @info, if needed.
**/
void
camel_folder_summary_add (CamelFolderSummary *summary,
- CamelMessageInfo *info)
+ CamelMessageInfo *info,
+ gboolean force_keep_uid)
{
- CamelMessageInfoBase *base_info;
-
g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary));
- if (info == NULL)
+ if (!info)
return;
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (info));
+
camel_folder_summary_lock (summary);
- if (!summary_assign_uid (summary, info)) {
+ if (!force_keep_uid && !summary_assign_uid (summary, info)) {
camel_folder_summary_unlock (summary);
return;
}
- base_info = (CamelMessageInfoBase *) info;
+ if (force_keep_uid) {
+ const gchar *uid;
+
+ uid = camel_message_info_get_uid (info);
+ if (!uid || !*uid) {
+ g_warning ("%s: Cannot add message info without UID, when disabled to assign new UID;
skipping it", G_STRFUNC);
+ camel_folder_summary_unlock (summary);
+ return;
+ }
+ }
+
folder_summary_update_counts_by_flags (summary, camel_message_info_get_flags (info),
UPDATE_COUNTS_ADD);
- base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
- base_info->dirty = TRUE;
+ camel_message_info_set_folder_flagged (info, TRUE);
+ camel_message_info_set_dirty (info, TRUE);
g_hash_table_insert (
summary->priv->uids,
@@ -3093,7 +2204,7 @@ camel_folder_summary_add (CamelFolderSummary *summary,
GUINT_TO_POINTER (camel_message_info_get_flags (info)));
/* Summary always holds a ref for the loaded infos */
- g_hash_table_insert (summary->priv->loaded_infos, (gpointer) camel_message_info_get_uid (info), info);
+ g_hash_table_insert (summary->priv->loaded_infos, (gpointer) camel_message_info_get_uid (info),
g_object_ref (info));
camel_folder_summary_touch (summary);
@@ -3101,56 +2212,18 @@ camel_folder_summary_add (CamelFolderSummary *summary,
}
/**
- * camel_folder_summary_insert:
- *
- * Since: 2.24
- **/
-void
-camel_folder_summary_insert (CamelFolderSummary *summary,
- CamelMessageInfo *info,
- gboolean load)
-{
- g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary));
-
- if (info == NULL)
- return;
-
- camel_folder_summary_lock (summary);
-
- if (!load) {
- CamelMessageInfoBase *base_info = (CamelMessageInfoBase *) info;
-
- folder_summary_update_counts_by_flags (summary, camel_message_info_get_flags (info),
UPDATE_COUNTS_ADD);
- base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
- base_info->dirty = TRUE;
-
- g_hash_table_insert (
- summary->priv->uids,
- (gpointer) camel_pstring_strdup (camel_message_info_get_uid (info)),
- GUINT_TO_POINTER (camel_message_info_get_flags (info)));
-
- camel_folder_summary_touch (summary);
- }
-
- /* Summary always holds a ref for the loaded infos */
- g_hash_table_insert (summary->priv->loaded_infos, (gchar *) camel_message_info_get_uid (info), info);
-
- camel_folder_summary_unlock (summary);
-}
-
-/**
* camel_folder_summary_info_new_from_header:
* @summary: a #CamelFolderSummary object
* @headers: rfc822 headers
*
* Create a new info record from a header.
*
- * Returns: the newly allocated record which must be unreferenced with
- * camel_message_info_unref()
+ * Returns: (transfer full): a newly created #CamelMessageInfo. Unref it
+ * with g_object_unref(), when done with it.
**/
CamelMessageInfo *
camel_folder_summary_info_new_from_header (CamelFolderSummary *summary,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
CamelFolderSummaryClass *class;
@@ -3180,8 +2253,8 @@ camel_folder_summary_info_new_from_header (CamelFolderSummary *summary,
* Once complete, the parser will be positioned at the end of
* the message.
*
- * Returns: the newly allocated record which must be unreferenced with
- * camel_message_info_unref()
+ * Returns: (transfer full): a newly created #CamelMessageInfo. Unref it
+ * with g_object_unref(), when done with it.
**/
CamelMessageInfo *
camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary,
@@ -3218,7 +2291,7 @@ camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary,
}
/* always scan the content info, even if we dont save it */
- ((CamelMessageInfoBase *) info)->content = summary_build_content_info (summary, info, mp);
+ summary_traverse_content_with_parser (summary, info, mp);
if (name && p->index) {
camel_index_write_name (p->index, name);
@@ -3229,7 +2302,7 @@ camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary,
g_rec_mutex_unlock (&summary->priv->filter_lock);
- ((CamelMessageInfoBase *) info)->size = camel_mime_parser_tell (mp) - start;
+ camel_message_info_set_size (info, camel_mime_parser_tell (mp) - start);
}
return info;
}
@@ -3238,23 +2311,21 @@ camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary,
* camel_folder_summary_info_new_from_message:
* @summary: a #CamelFolderSummary object
* @message: a #CamelMimeMessage object
- * @bodystructure: a bodystructure or NULL
*
* Create a summary item from a message.
*
- * Returns: the newly allocated record which must be unreferenced with
- * camel_message_info_unref()
+ * Returns: (transfer full): a newly created #CamelMessageInfo. Unref it
+ * with g_object_unref(), when done with it.
**/
CamelMessageInfo *
camel_folder_summary_info_new_from_message (CamelFolderSummary *summary,
- CamelMimeMessage *msg,
- const gchar *bodystructure)
+ CamelMimeMessage *msg)
{
CamelMessageInfo *info;
CamelFolderSummaryPrivate *p = summary->priv;
CamelIndexName *name = NULL;
- info = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_new_from_message (summary, msg,
bodystructure);
+ info = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_new_from_message (summary, msg);
/* assign a unique uid, this is slightly 'wrong' as we do not really
* know if we are going to store this in the summary, but we need it set for indexing */
@@ -3279,7 +2350,7 @@ camel_folder_summary_info_new_from_message (CamelFolderSummary *summary,
}
}
- ((CamelMessageInfoBase *) info)->content = summary_build_content_info_message (summary, info,
(CamelMimePart *) msg);
+ summary_traverse_content_with_part (summary, info, (CamelMimePart *) msg);
if (name) {
camel_index_write_name (p->index, name);
@@ -3294,28 +2365,6 @@ camel_folder_summary_info_new_from_message (CamelFolderSummary *summary,
}
/**
- * camel_folder_summary_content_info_free:
- * @summary: a #CamelFolderSummary object
- * @ci: a #CamelMessageContentInfo
- *
- * Free the content info @ci, and all associated memory.
- **/
-void
-camel_folder_summary_content_info_free (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci)
-{
- CamelMessageContentInfo *pw, *pn;
-
- pw = ci->childs;
- CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_free (summary, ci);
- while (pw) {
- pn = pw->next;
- camel_folder_summary_content_info_free (summary, pw);
- pw = pn;
- }
-}
-
-/**
* camel_folder_summary_touch:
* @summary: a #CamelFolderSummary object
*
@@ -3413,7 +2462,7 @@ camel_folder_summary_remove (CamelFolderSummary *summary,
g_return_val_if_fail (info != NULL, FALSE);
if (camel_folder_summary_remove_uid (summary, camel_message_info_get_uid (info))) {
- camel_message_info_unref (info);
+ g_clear_object (&info);
return TRUE;
}
@@ -3508,7 +2557,7 @@ camel_folder_summary_remove_uids (CamelFolderSummary *summary,
g_hash_table_remove (summary->priv->loaded_infos, uid_copy);
if (mi)
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
camel_pstring_free (uid_copy);
}
}
@@ -3527,36 +2576,6 @@ camel_folder_summary_remove_uids (CamelFolderSummary *summary,
return res;
}
-static struct _node *
-my_list_append (struct _node **list,
- struct _node *n)
-{
- struct _node *ln = *list;
- n->next = NULL;
-
- if (!ln) {
- *list = n;
- return n;
- }
-
- while (ln->next)
- ln = ln->next;
- ln->next = n;
- return n;
-}
-
-static gint
-my_list_size (struct _node **list)
-{
- gint len = 0;
- struct _node *ln = (struct _node *) list;
- while (ln->next) {
- ln = ln->next;
- len++;
- }
- return len;
-}
-
/* are these even useful for anything??? */
static CamelMessageInfo *
message_info_new_from_parser (CamelFolderSummary *summary,
@@ -3579,57 +2598,15 @@ message_info_new_from_parser (CamelFolderSummary *summary,
return mi;
}
-static CamelMessageContentInfo *
-content_info_new_from_parser (CamelFolderSummary *summary,
- CamelMimeParser *mp)
-{
- CamelMessageContentInfo *ci = NULL;
-
- switch (camel_mime_parser_state (mp)) {
- case CAMEL_MIME_PARSER_STATE_HEADER:
- case CAMEL_MIME_PARSER_STATE_MESSAGE:
- case CAMEL_MIME_PARSER_STATE_MULTIPART:
- ci = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_new_from_header (summary,
camel_mime_parser_headers_raw (mp));
- if (ci) {
- if (ci->type)
- camel_content_type_unref (ci->type);
- ci->type = camel_mime_parser_content_type (mp);
- camel_content_type_ref (ci->type);
- }
- break;
- default:
- g_error ("Invalid parser state");
- }
-
- return ci;
-}
-
static CamelMessageInfo *
message_info_new_from_message (CamelFolderSummary *summary,
- CamelMimeMessage *msg,
- const gchar *bodystructure)
-{
- CamelMessageInfo *mi;
-
- mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (summary)))->message_info_new_from_header
(summary, ((CamelMimePart *) msg)->headers);
- ((CamelMessageInfoBase *) mi)->bodystructure = g_strdup (bodystructure);
-
- return mi;
-}
-
-static CamelMessageContentInfo *
-content_info_new_from_message (CamelFolderSummary *summary,
- CamelMimePart *mp)
+ CamelMimeMessage *msg)
{
- CamelMessageContentInfo *ci;
-
- ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (summary)))->content_info_new_from_header
(summary, mp->headers);
-
- return ci;
+ return CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_new_from_header (summary,
((CamelMimePart *) msg)->headers);
}
static gchar *
-summary_format_address (struct _camel_header_raw *h,
+summary_format_address (CamelHeaderRaw *h,
const gchar *name,
const gchar *charset)
{
@@ -3656,7 +2633,7 @@ summary_format_address (struct _camel_header_raw *h,
}
static gchar *
-summary_format_string (struct _camel_header_raw *h,
+summary_format_string (CamelHeaderRaw *h,
const gchar *name,
const gchar *charset)
{
@@ -3675,35 +2652,15 @@ summary_format_string (struct _camel_header_raw *h,
return str;
}
-/**
- * camel_folder_summary_content_info_new:
- * @summary: a #CamelFolderSummary object
- *
- * Allocate a new #CamelMessageContentInfo, suitable for adding
- * to this summary.
- *
- * Returns: a newly allocated #CamelMessageContentInfo
- **/
-CamelMessageContentInfo *
-camel_folder_summary_content_info_new (CamelFolderSummary *summary)
-{
- CamelFolderSummaryClass *class;
-
- class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
- g_return_val_if_fail (class->content_info_size > 0, NULL);
-
- return g_slice_alloc0 (class->content_info_size);
-}
-
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *summary,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
const gchar *received, *date, *content, *charset = NULL;
GSList *refs, *irt, *scan;
gchar *subject, *from, *to, *cc, *mlist;
CamelContentType *ct = NULL;
- CamelMessageInfoBase *mi;
+ CamelMessageInfo *mi;
guint8 *digest;
gsize length;
gchar *msgid;
@@ -3712,7 +2669,9 @@ message_info_new_from_header (CamelFolderSummary *summary,
length = g_checksum_type_get_length (G_CHECKSUM_MD5);
digest = g_alloca (length);
- mi = (CamelMessageInfoBase *) camel_message_info_new (summary);
+ mi = camel_message_info_new (summary);
+
+ camel_message_info_set_abort_notifications (mi, TRUE);
if ((content = camel_header_raw_find (&h, "Content-Type", NULL))
&& (ct = camel_content_type_decode (content))
@@ -3731,53 +2690,62 @@ message_info_new_from_header (CamelFolderSummary *summary,
if (ct)
camel_content_type_unref (ct);
- mi->subject = camel_pstring_add (subject, TRUE);
- mi->from = camel_pstring_add (from, TRUE);
- mi->to = camel_pstring_add (to, TRUE);
- mi->cc = camel_pstring_add (cc, TRUE);
- mi->mlist = camel_pstring_add (mlist, TRUE);
+ camel_message_info_set_subject (mi, subject);
+ camel_message_info_set_from (mi, from);
+ camel_message_info_set_to (mi, to);
+ camel_message_info_set_cc (mi, cc);
+ camel_message_info_set_mlist (mi, mlist);
- mi->user_flags = NULL;
- mi->user_tags = NULL;
+ g_free (subject);
+ g_free (from);
+ g_free (to);
+ g_free (cc);
+ g_free (mlist);
if ((date = camel_header_raw_find (&h, "date", NULL)))
- mi->date_sent = camel_header_decode_date (date, NULL);
+ camel_message_info_set_date_sent (mi, camel_header_decode_date (date, NULL));
else
- mi->date_sent = 0;
+ camel_message_info_set_date_sent (mi, 0);
received = camel_header_raw_find (&h, "received", NULL);
if (received)
received = strrchr (received, ';');
if (received)
- mi->date_received = camel_header_decode_date (received + 1, NULL);
+ camel_message_info_set_date_received (mi, camel_header_decode_date (received + 1, NULL));
else
- mi->date_received = 0;
+ camel_message_info_set_date_received (mi, 0);
/* Fallback to Received date, when the Date header is missing */
- if (!mi->date_sent)
- mi->date_sent = mi->date_received;
+ if (!camel_message_info_get_date_sent (mi))
+ camel_message_info_set_date_sent (mi, camel_message_info_get_date_received (mi));
/* If neither Received is available, then use the current time. */
- if (!mi->date_sent)
- mi->date_sent = time (NULL);
+ if (!camel_message_info_get_date_sent (mi))
+ camel_message_info_set_date_sent (mi, (gint64) time (NULL));
msgid = camel_header_msgid_decode (camel_header_raw_find (&h, "message-id", NULL));
if (msgid) {
GChecksum *checksum;
+ CamelSummaryMessageID message_id;
checksum = g_checksum_new (G_CHECKSUM_MD5);
g_checksum_update (checksum, (guchar *) msgid, -1);
g_checksum_get_digest (checksum, digest, &length);
g_checksum_free (checksum);
- memcpy (mi->message_id.id.hash, digest, sizeof (mi->message_id.id.hash));
+ memcpy (message_id.id.hash, digest, sizeof (message_id.id.hash));
g_free (msgid);
+
+ camel_message_info_set_message_id (mi, message_id.id.id);
}
/* decode our references and in-reply-to headers */
refs = camel_header_references_decode (camel_header_raw_find (&h, "references", NULL));
irt = camel_header_references_decode (camel_header_raw_find (&h, "in-reply-to", NULL));
if (refs || irt) {
+ GArray *references;
+ CamelSummaryMessageID message_id;
+
if (irt) {
/* The References field is populated from the "References" and/or "In-Reply-To"
* headers. If both headers exist, take the first thing in the In-Reply-To header
@@ -3790,8 +2758,8 @@ message_info_new_from_header (CamelFolderSummary *summary,
}
count = g_slist_length (refs);
- mi->references = g_malloc (sizeof (*mi->references) + ((count - 1) * sizeof
(mi->references->references[0])));
- count = 0;
+ references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), count);
+
for (scan = refs; scan != NULL; scan = g_slist_next (scan)) {
GChecksum *checksum;
@@ -3800,84 +2768,18 @@ message_info_new_from_header (CamelFolderSummary *summary,
g_checksum_get_digest (checksum, digest, &length);
g_checksum_free (checksum);
- memcpy (mi->references->references[count].id.hash, digest, sizeof
(mi->message_id.id.hash));
- count++;
+ memcpy (message_id.id.hash, digest, sizeof (message_id.id.hash));
+
+ g_array_append_val (references, message_id.id.id);
}
- mi->references->size = count;
g_slist_free_full (refs, g_free);
- }
-
- return (CamelMessageInfo *) mi;
-}
-
-static void
-message_info_free (CamelFolderSummary *summary,
- CamelMessageInfo *info)
-{
- CamelFolderSummaryClass *class;
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
- if (mi->uid) {
- if (summary) {
- camel_folder_summary_lock (summary);
- if (g_hash_table_lookup (summary->priv->loaded_infos, mi->uid) == mi) {
- g_hash_table_remove (summary->priv->loaded_infos, mi->uid);
- }
- camel_folder_summary_unlock (summary);
- }
- camel_pstring_free (mi->uid);
+ camel_message_info_take_references (mi, references);
}
- camel_pstring_free (mi->subject);
- camel_pstring_free (mi->from);
- camel_pstring_free (mi->to);
- camel_pstring_free (mi->cc);
- camel_pstring_free (mi->mlist);
- g_free (mi->bodystructure);
- g_free (mi->references);
- g_free (mi->preview);
- camel_flag_list_free (&mi->user_flags);
- camel_tag_list_free (&mi->user_tags);
- if (mi->headers)
- camel_header_param_list_free (mi->headers);
-
- if (summary) {
- class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
- g_slice_free1 (class->message_info_size, mi);
- } else
- g_slice_free (CamelMessageInfoBase, mi);
-}
-static CamelMessageContentInfo *
-content_info_new_from_header (CamelFolderSummary *summary,
- struct _camel_header_raw *h)
-{
- CamelMessageContentInfo *ci;
- const gchar *charset;
-
- ci = camel_folder_summary_content_info_new (summary);
+ camel_message_info_set_abort_notifications (mi, FALSE);
- charset = camel_iconv_locale_charset ();
- ci->id = camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL));
- ci->description = camel_header_decode_string (camel_header_raw_find (&h, "content-description",
NULL), charset);
- ci->encoding = camel_content_transfer_encoding_decode (camel_header_raw_find (&h,
"content-transfer-encoding", NULL));
- ci->type = camel_content_type_decode (camel_header_raw_find (&h, "content-type", NULL));
-
- return ci;
-}
-
-static void
-content_info_free (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci)
-{
- CamelFolderSummaryClass *class;
-
- class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
-
- camel_content_type_unref (ci->type);
- g_free (ci->id);
- g_free (ci->description);
- g_free (ci->encoding);
- g_slice_free1 (class->content_info_size, ci);
+ return mi;
}
static gchar *
@@ -3893,30 +2795,25 @@ next_uid_string (CamelFolderSummary *summary)
*/
/* must have filter_lock before calling this function */
-static CamelMessageContentInfo *
-summary_build_content_info (CamelFolderSummary *summary,
- CamelMessageInfo *msginfo,
- CamelMimeParser *mp)
+static void
+summary_traverse_content_with_parser (CamelFolderSummary *summary,
+ CamelMessageInfo *msginfo,
+ CamelMimeParser *mp)
{
gint state;
gsize len;
gchar *buffer;
- CamelMessageContentInfo *info = NULL;
CamelContentType *ct;
gint enc_id = -1, chr_id = -1, html_id = -1, idx_id = -1;
CamelFolderSummaryPrivate *p = summary->priv;
CamelMimeFilter *mfc;
- CamelMessageContentInfo *part;
const gchar *calendar_header;
- d (printf ("building content info\n"));
+ d (printf ("traversing content\n"));
/* start of this part */
state = camel_mime_parser_step (mp, &buffer, &len);
- if (summary->priv->build_content)
- info = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_new_from_parser (summary, mp);
-
switch (state) {
case CAMEL_MIME_PARSER_STATE_HEADER:
/* check content type for indexing, then read body */
@@ -4032,11 +2929,7 @@ summary_build_content_info (CamelFolderSummary *summary,
while (camel_mime_parser_step (mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
camel_mime_parser_unstep (mp);
- part = summary_build_content_info (summary, msginfo, mp);
- if (part) {
- part->parent = info;
- my_list_append ((struct _node **) &info->childs, (struct _node *) part);
- }
+ summary_traverse_content_with_parser (summary, msginfo, mp);
}
break;
case CAMEL_MIME_PARSER_STATE_MESSAGE:
@@ -4044,11 +2937,7 @@ summary_build_content_info (CamelFolderSummary *summary,
/* update attachments flag as we go */
camel_message_info_set_flags (msginfo, CAMEL_MESSAGE_ATTACHMENTS, CAMEL_MESSAGE_ATTACHMENTS);
- part = summary_build_content_info (summary, msginfo, mp);
- if (part) {
- part->parent = info;
- my_list_append ((struct _node **) &info->childs, (struct _node *) part);
- }
+ summary_traverse_content_with_parser (summary, msginfo, mp);
state = camel_mime_parser_step (mp, &buffer, &len);
if (state != CAMEL_MIME_PARSER_STATE_MESSAGE_END) {
g_error ("Bad parser state: Expecing MESSAGE_END or MESSAGE_EOF, got: %d", state);
@@ -4057,33 +2946,27 @@ summary_build_content_info (CamelFolderSummary *summary,
break;
}
- d (printf ("finished building content info\n"));
-
- return info;
+ d (printf ("finished traversion content info\n"));
}
/* build the content-info, from a message */
/* this needs the filter lock since it uses filters to perform indexing */
-static CamelMessageContentInfo *
-summary_build_content_info_message (CamelFolderSummary *summary,
+static void
+summary_traverse_content_with_part (CamelFolderSummary *summary,
CamelMessageInfo *msginfo,
CamelMimePart *object)
{
CamelDataWrapper *containee;
gint parts, i;
CamelFolderSummaryPrivate *p = summary->priv;
- CamelMessageContentInfo *info = NULL, *child;
CamelContentType *ct;
- const struct _camel_header_raw *header;
+ const CamelHeaderRaw *header;
gboolean is_calendar = FALSE, is_note = FALSE;
- if (summary->priv->build_content)
- info = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->content_info_new_from_message (summary,
object);
-
containee = camel_medium_get_content (CAMEL_MEDIUM (object));
if (containee == NULL)
- return info;
+ return;
/* TODO: I find it odd that get_part and get_content do not
* add a reference, probably need fixing for multithreading */
@@ -4139,20 +3022,12 @@ summary_build_content_info_message (CamelFolderSummary *summary,
for (i = 0; i < parts; i++) {
CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (containee), i);
- g_return_val_if_fail (part, info);
- child = summary_build_content_info_message (summary, msginfo, part);
- if (child) {
- child->parent = info;
- my_list_append ((struct _node **) &info->childs, (struct _node *) child);
- }
+ g_return_if_fail (part);
+ summary_traverse_content_with_part (summary, msginfo, part);
}
} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
/* for messages we only look at its contents */
- child = summary_build_content_info_message (summary, msginfo, (CamelMimePart *) containee);
- if (child) {
- child->parent = info;
- my_list_append ((struct _node **) &info->childs, (struct _node *) child);
- }
+ summary_traverse_content_with_part (summary, msginfo, (CamelMimePart *) containee);
} else if (p->filter_stream
&& camel_content_type_is (ct, "text", "*")) {
gint html_id = -1, idx_id = -1;
@@ -4181,327 +3056,6 @@ summary_build_content_info_message (CamelFolderSummary *summary,
camel_stream_filter_remove (
CAMEL_STREAM_FILTER (p->filter_stream), html_id);
}
-
- return info;
-}
-
-/**
- * camel_flag_get:
- * @list: the address of a #CamelFlag list
- * @name: name of the flag to get
- *
- * Find the state of the flag @name in @list.
- *
- * Returns: the state of the flag (%TRUE or %FALSE)
- **/
-gboolean
-camel_flag_get (CamelFlag **list,
- const gchar *name)
-{
- CamelFlag *flag;
- flag = *list;
- while (flag) {
- if (!strcmp (flag->name, name))
- return TRUE;
- flag = flag->next;
- }
- return FALSE;
-}
-
-/**
- * camel_flag_set:
- * @list: the address of a #CamelFlag list
- * @name: name of the flag to set or change
- * @value: the value to set on the flag
- *
- * Set the state of a flag @name in the list @list to @value.
- *
- * Returns: %TRUE if the value of the flag has been changed or %FALSE
- * otherwise
- **/
-gboolean
-camel_flag_set (CamelFlag **list,
- const gchar *name,
- gboolean value)
-{
- CamelFlag *flag, *tmp;
- gsize tmp_len = 0;
-
- if (!name)
- return TRUE;
-
- /* this 'trick' works because flag->next is the first element */
- flag = (CamelFlag *) list;
- while (flag->next) {
- tmp = flag->next;
- if (!strcmp (flag->next->name, name)) {
- if (!value) {
- flag->next = tmp->next;
- g_free (tmp);
- }
- return !value;
- }
- flag = tmp;
- }
-
- if (value) {
- tmp_len = sizeof (*tmp) + strlen (name);
- tmp = g_malloc (tmp_len);
- g_strlcpy (tmp->name, name, strlen (name) + 1);
- tmp->next = NULL;
- flag->next = tmp;
- }
- return value;
-}
-
-/**
- * camel_flag_list_size:
- * @list: the address of a #CamelFlag list
- *
- * Get the length of the flag list.
- *
- * Returns: the number of flags in the list
- **/
-gint
-camel_flag_list_size (CamelFlag **list)
-{
- gint count = 0;
- CamelFlag *flag;
-
- flag = *list;
- while (flag) {
- count++;
- flag = flag->next;
- }
- return count;
-}
-
-/**
- * camel_flag_list_free:
- * @list: the address of a #CamelFlag list
- *
- * Free the memory associated with the flag list @list.
- **/
-void
-camel_flag_list_free (CamelFlag **list)
-{
- CamelFlag *flag, *tmp;
- flag = *list;
- while (flag) {
- tmp = flag->next;
- g_free (flag);
- flag = tmp;
- }
- *list = NULL;
-}
-
-/**
- * camel_flag_list_copy:
- * @to: the address of the #CamelFlag list to copy to
- * @from: the address of the #CamelFlag list to copy from
- *
- * Copy a flag list.
- *
- * Returns: %TRUE if @to is changed or %FALSE otherwise
- **/
-gboolean
-camel_flag_list_copy (CamelFlag **to,
- CamelFlag **from)
-{
- CamelFlag *flag, *tmp;
- gboolean changed = FALSE;
-
- if (*to == NULL && from == NULL)
- return FALSE;
-
- /* Remove any now-missing flags */
- flag = (CamelFlag *) to;
- while (flag->next) {
- tmp = flag->next;
- if (!camel_flag_get (from, tmp->name)) {
- if (*tmp->name)
- changed = TRUE;
- flag->next = tmp->next;
- g_free (tmp);
- } else {
- flag = tmp;
- }
- }
-
- /* Add any new non-empty flags */
- flag = *from;
- while (flag) {
- if (*flag->name)
- changed |= camel_flag_set (to, flag->name, TRUE);
- flag = flag->next;
- }
-
- return changed;
-}
-
-/**
- * camel_tag_get:
- * @list: the address of a #CamelTag list
- * @name: name of the tag to get
- *
- * Find the flag @name in @list and get the value.
- *
- * Returns: the value of the flag or %NULL if unset
- **/
-const gchar *
-camel_tag_get (CamelTag **list,
- const gchar *name)
-{
- CamelTag *tag;
-
- tag = *list;
- while (tag) {
- if (!strcmp (tag->name, name))
- return (const gchar *) tag->value;
- tag = tag->next;
- }
- return NULL;
-}
-
-/**
- * camel_tag_set:
- * @list: the address of a #CamelTag list
- * @name: name of the tag to set
- * @value: value to set on the tag
- *
- * Set the tag @name in the tag list @list to @value.
- *
- * Returns: %TRUE if the value on the tag changed or %FALSE otherwise
- **/
-gboolean
-camel_tag_set (CamelTag **list,
- const gchar *name,
- const gchar *value)
-{
- CamelTag *tag, *tmp;
-
- /* this 'trick' works because tag->next is the first element */
- tag = (CamelTag *) list;
- while (tag->next) {
- tmp = tag->next;
- if (!strcmp (tmp->name, name)) {
- if (value == NULL) { /* clear it? */
- tag->next = tmp->next;
- g_free (tmp->value);
- g_free (tmp);
- return TRUE;
- } else if (strcmp (tmp->value, value)) { /* has it changed? */
- g_free (tmp->value);
- tmp->value = g_strdup (value);
- return TRUE;
- }
- return FALSE;
- }
- tag = tmp;
- }
-
- if (value) {
- tmp = g_malloc (sizeof (*tmp) + strlen (name));
- g_strlcpy (tmp->name, name, strlen (name) + 1);
- tmp->value = g_strdup (value);
- tmp->next = NULL;
- tag->next = tmp;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * camel_tag_list_size:
- * @list: the address of a #CamelTag list
- *
- * Get the number of tags present in the tag list @list.
- *
- * Returns: the number of tags
- **/
-gint
-camel_tag_list_size (CamelTag **list)
-{
- gint count = 0;
- CamelTag *tag;
-
- tag = *list;
- while (tag) {
- count++;
- tag = tag->next;
- }
- return count;
-}
-
-static void
-rem_tag (gchar *key,
- gchar *value,
- CamelTag **to)
-{
- camel_tag_set (to, key, NULL);
-}
-
-/**
- * camel_tag_list_copy:
- * @to: the address of the #CamelTag list to copy to
- * @from: the address of the #CamelTag list to copy from
- *
- * Copy a tag list.
- *
- * Returns: %TRUE if @to is changed or %FALSE otherwise
- **/
-gboolean
-camel_tag_list_copy (CamelTag **to,
- CamelTag **from)
-{
- gint changed = FALSE;
- CamelTag *tag;
- GHashTable *left;
-
- if (*to == NULL && from == NULL)
- return FALSE;
-
- left = g_hash_table_new (g_str_hash, g_str_equal);
- tag = *to;
- while (tag) {
- g_hash_table_insert (left, tag->name, tag);
- tag = tag->next;
- }
-
- tag = *from;
- while (tag) {
- changed |= camel_tag_set (to, tag->name, tag->value);
- g_hash_table_remove (left, tag->name);
- tag = tag->next;
- }
-
- if (g_hash_table_size (left) > 0) {
- g_hash_table_foreach (left, (GHFunc) rem_tag, to);
- changed = TRUE;
- }
- g_hash_table_destroy (left);
-
- return changed;
-}
-
-/**
- * camel_tag_list_free:
- * @list: the address of a #CamelTag list
- *
- * Free the tag list @list.
- **/
-void
-camel_tag_list_free (CamelTag **list)
-{
- CamelTag *tag, *tmp;
- tag = *list;
- while (tag) {
- tmp = tag->next;
- g_free (tag->value);
- g_free (tag);
- tag = tmp;
- }
- *list = NULL;
}
static struct flag_names_t {
@@ -4559,59 +3113,6 @@ camel_system_flag_get (CamelMessageFlags flags,
}
/**
- * camel_message_info_new:
- * @summary: (nullable): a #CamelFolderSummary object or %NULL
- *
- * Create a new #CamelMessageInfo.
- *
- * Returns: (transfer full) (type CamelMessageInfo): a new #CamelMessageInfo
- **/
-gpointer
-camel_message_info_new (CamelFolderSummary *summary)
-{
- CamelFolderSummaryClass *class;
- CamelMessageInfo *info;
- gsize message_info_size;
-
- if (summary != NULL) {
- class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
- g_return_val_if_fail (class->message_info_size > 0, NULL);
- message_info_size = class->message_info_size;
- } else {
- message_info_size = sizeof (CamelMessageInfoBase);
- }
-
- info = g_slice_alloc0 (message_info_size);
- info->refcount = 1;
- info->summary = summary;
-
- /* We assume that mi is always dirty unless freshly read or just saved*/
- ((CamelMessageInfoBase *) info)->dirty = TRUE;
-
- return info;
-}
-
-/**
- * camel_message_info_ref:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Reference an info.
- * Returns: (transfer full) (type CamelMessageInfo):
- **/
-gpointer
-camel_message_info_ref (gpointer o)
-{
- CamelMessageInfo *mi = o;
-
- g_return_val_if_fail (mi != NULL, NULL);
- g_return_val_if_fail (mi->refcount > 0, NULL);
-
- g_atomic_int_inc (&mi->refcount);
-
- return o;
-}
-
-/**
* camel_message_info_new_from_header:
* @summary: a #CamelFolderSummary object or %NULL
* @header: raw header
@@ -4623,623 +3124,15 @@ camel_message_info_ref (gpointer o)
**/
CamelMessageInfo *
camel_message_info_new_from_header (CamelFolderSummary *summary,
- struct _camel_header_raw *header)
+ CamelHeaderRaw *header)
{
if (summary != NULL)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->
- message_info_new_from_header (summary, header);
+ return CAMEL_FOLDER_SUMMARY_GET_CLASS (summary)->message_info_new_from_header (summary,
header);
else
return message_info_new_from_header (NULL, header);
}
/**
- * camel_message_info_unref:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Unref's and potentially frees a #CamelMessageInfo and its contents.
- **/
-void
-camel_message_info_unref (gpointer o)
-{
- CamelMessageInfo *mi = o;
-
- g_return_if_fail (mi != NULL);
- g_return_if_fail (mi->refcount > 0);
-
- if (g_atomic_int_dec_and_test (&mi->refcount)) {
- if (mi->summary != NULL) {
- CamelFolderSummaryClass *class;
-
- /* FIXME This is kinda busted, should really
- * be handled by message_info_free(). */
- if (mi->summary->priv->build_content
- && ((CamelMessageInfoBase *) mi)->content) {
- camel_folder_summary_content_info_free (
- mi->summary,
- ((CamelMessageInfoBase *) mi)->content);
- ((CamelMessageInfoBase *) mi)->content = NULL;
- }
-
- class = CAMEL_FOLDER_SUMMARY_GET_CLASS (mi->summary);
- g_return_if_fail (class->message_info_free != NULL);
-
- class->message_info_free (mi->summary, mi);
- } else {
- message_info_free (NULL, mi);
- }
- }
-}
-
-/**
- * camel_message_info_clone:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Duplicate a #CamelMessageInfo.
- *
- * Returns: (transfer full) (type CamelMessageInfo): the duplicated #CamelMessageInfo
- **/
-gpointer
-camel_message_info_clone (gconstpointer o)
-{
- const CamelMessageInfo *mi = o;
-
- if (mi->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (mi->summary)->message_info_clone (mi->summary, mi);
- else
- return message_info_clone (NULL, mi);
-}
-
-/**
- * camel_message_info_get_ptr:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- * @id: info to get
- *
- * Generic accessor method for getting pointer data.
- *
- * Returns: (transfer none): the pointer data
- *
- * Since: 3.22
- **/
-gconstpointer
-camel_message_info_get_ptr (gconstpointer info,
- gint id)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, NULL);
-
- if (nfo->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (nfo->summary)->info_ptr (nfo, id);
- else
- return info_ptr (nfo, id);
-}
-
-/**
- * camel_message_info_get_uint32:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- * @id: info to get
- *
- * Generic accessor method for getting 32bit unsigned integer data.
- *
- * Returns: the guint32 data
- *
- * Since: 3.22
- **/
-guint32
-camel_message_info_get_uint32 (gconstpointer info,
- gint id)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, 0);
-
- if (nfo->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (nfo->summary)->info_uint32 (nfo, id);
- else
- return info_uint32 (nfo, id);
-}
-
-/**
- * camel_message_info_get_time:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- * @id: info to get
- *
- * Generic accessor method for getting time_t data.
- *
- * Returns: the time_t data
- *
- * Since: 3.22
- **/
-time_t
-camel_message_info_get_time (gconstpointer info,
- gint id)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, (time_t) 0);
-
- if (nfo->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (nfo->summary)->info_time (nfo, id);
- else
- return info_time (nfo, id);
-}
-
-/**
- * camel_message_info_get_uid:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the uid of the #CamelMessageInfo
- *
- * Returns: the uid
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_uid (gconstpointer info)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, NULL);
-
- return nfo->uid;
-}
-
-/**
- * camel_message_info_get_subject:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the subject of the #CamelMessageInfo
- *
- * Returns: the subject
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_subject (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_SUBJECT);
-}
-
-/**
- * camel_message_info_get_preview:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the preview of the #CamelMessageInfo
- *
- * Returns: the preview
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_preview (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_PREVIEW);
-}
-
-/**
- * camel_message_info_get_from:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the from field of the #CamelMessageInfo
- *
- * Returns: the from field
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_from (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_FROM);
-}
-
-/**
- * camel_message_info_get_to:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the to field of the #CamelMessageInfo
- *
- * Returns: the to field
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_to (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_TO);
-}
-
-/**
- * camel_message_info_get_cc:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the cc field of the #CamelMessageInfo
- *
- * Returns: the cc field
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_cc (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_CC);
-}
-
-/**
- * camel_message_info_get_mlist:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the mlist of the #CamelMessageInfo
- *
- * Returns: the mlist
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_mlist (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_MLIST);
-}
-
-/**
- * camel_message_info_get_flags:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the flags of the #CamelMessageInfo
- *
- * Returns: the flags
- *
- * Since: 3.22
- **/
-guint32
-camel_message_info_get_flags (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, 0);
-
- return camel_message_info_get_uint32 (info, CAMEL_MESSAGE_INFO_FLAGS);
-}
-
-/**
- * camel_message_info_get_size:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the size of the #CamelMessageInfo
- *
- * Returns: the size
- *
- * Since: 3.22
- **/
-guint32
-camel_message_info_get_size (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, 0);
-
- return camel_message_info_get_uint32 (info, CAMEL_MESSAGE_INFO_SIZE);
-}
-
-/**
- * camel_message_info_get_date_sent:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the sent date of the #CamelMessageInfo
- *
- * Returns: the sent date
- *
- * Since: 3.22
- **/
-time_t
-camel_message_info_get_date_sent (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, (time_t) 0);
-
- return camel_message_info_get_time (info, CAMEL_MESSAGE_INFO_DATE_SENT);
-}
-
-/**
- * camel_message_info_get_date_received:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the received date of the #CamelMessageInfo
- *
- * Returns: the received date
- *
- * Since: 3.22
- **/
-time_t
-camel_message_info_get_date_received (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, (time_t) 0);
-
- return camel_message_info_get_time (info, CAMEL_MESSAGE_INFO_DATE_RECEIVED);
-}
-
-/**
- * camel_message_info_get_user_flag:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- * @id: user flag to get
- *
- * Get the state of a user flag named @id.
- *
- * Returns: the state of the user flag
- *
- * Since: 3.22
- **/
-gboolean
-camel_message_info_get_user_flag (gconstpointer info,
- const gchar *id)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, FALSE);
-
- if (nfo->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (nfo->summary)->info_user_flag (nfo, id);
- else
- return info_user_flag (nfo, id);
-}
-
-/**
- * camel_message_info_get_user_tag:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- * @id: user tag to get
- *
- * Get the value of a user tag named @id.
- *
- * Returns: the value of the user tag
- *
- * Since: 3.22
- **/
-const gchar *
-camel_message_info_get_user_tag (gconstpointer info,
- const gchar *id)
-{
- const CamelMessageInfo *nfo = info;
-
- g_return_val_if_fail (info != NULL, NULL);
-
- if (nfo->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (nfo->summary)->info_user_tag (nfo, id);
- else
- return info_user_tag (nfo, id);
-}
-
-/**
- * camel_message_info_get_message_id:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelSummaryMessageID of the #CamelMessageInfo
- *
- * Returns: the id of the message
- *
- * Since: 3.22
- **/
-const CamelSummaryMessageID *
-camel_message_info_get_message_id (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_MESSAGE_ID);
-}
-
-/**
- * camel_message_info_get_references:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelSummaryReferences of the #CamelMessageInfo
- *
- * Returns: the references of the message
- *
- * Since: 3.22
- **/
-const CamelSummaryReferences *
-camel_message_info_get_references (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_REFERENCES);
-}
-
-/**
- * camel_message_info_get_user_flags:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelFlag of the #CamelMessageInfo
- *
- * Returns: the flags of the message
- *
- * Since: 3.22
- **/
-const CamelFlag *
-camel_message_info_get_user_flags (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_USER_FLAGS);
-}
-
-/**
- * camel_message_info_get_user_tags:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelTag of the #CamelMessageInfo
- *
- * Returns: the tags of the message
- *
- * Since: 3.22
- **/
-const CamelTag *
-camel_message_info_get_user_tags (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_USER_TAGS);
-}
-
-/**
- * camel_message_info_get_headers:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelHeaderParam of the #CamelMessageInfo
- *
- * Returns: the headers of the message
- *
- * Since: 3.22
- **/
-const CamelHeaderParam *
-camel_message_info_get_headers (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_HEADERS);
-}
-
-/**
- * camel_message_info_get_content:
- * @info: (type CamelMessageInfo): a #CamelMessageInfo
- *
- * Get the #CamelMessageContentInfo of the #CamelMessageInfo
- *
- * Returns: the content of the message
- *
- * Since: 3.22
- **/
-const CamelMessageContentInfo *
-camel_message_info_get_content (gconstpointer info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return camel_message_info_get_ptr (info, CAMEL_MESSAGE_INFO_CONTENT);
-}
-
-/**
- * camel_message_info_set_flags:
- * @info: a #CamelMessageInfo
- * @flags: mask of flags to change
- * @set: state the flags should be changed to
- *
- * Change the state of the system flags on the #CamelMessageInfo
- *
- * Returns: %TRUE if any of the flags changed or %FALSE otherwise
- **/
-gboolean
-camel_message_info_set_flags (CamelMessageInfo *info,
- CamelMessageFlags flags,
- guint32 set)
-{
- if (info->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (info->summary)->info_set_flags (info, flags, set);
- else
- return info_set_flags (info, flags, set);
-}
-
-/**
- * camel_message_info_set_user_flag:
- * @info: a #CamelMessageInfo
- * @id: name of the user flag to set
- * @state: state to set the flag to
- *
- * Set the state of a user flag on a #CamelMessageInfo.
- *
- * Returns: %TRUE if the state changed or %FALSE otherwise
- **/
-gboolean
-camel_message_info_set_user_flag (CamelMessageInfo *info,
- const gchar *id,
- gboolean state)
-{
- if (info->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (info->summary)->info_set_user_flag (info, id, state);
- else
- return info_set_user_flag (info, id, state);
-}
-
-/**
- * camel_message_info_set_user_tag:
- * @info: a #CamelMessageInfo
- * @id: name of the user tag to set
- * @val: value to set
- *
- * Set the value of a user tag on a #CamelMessageInfo.
- *
- * Returns: %TRUE if the value changed or %FALSE otherwise
- **/
-gboolean
-camel_message_info_set_user_tag (CamelMessageInfo *info,
- const gchar *id,
- const gchar *val)
-{
- if (info->summary)
- return CAMEL_FOLDER_SUMMARY_GET_CLASS (info->summary)->info_set_user_tag (info, id, val);
- else
- return info_set_user_tag (info, id, val);
-}
-
-void
-camel_content_info_dump (CamelMessageContentInfo *ci,
- gint depth)
-{
- gchar *p;
-
- p = alloca (depth * 4 + 1);
- memset (p, ' ', depth * 4);
- p[depth * 4] = 0;
-
- if (ci == NULL) {
- printf ("%s<empty>\n", p);
- return;
- }
-
- if (ci->type)
- printf (
- "%scontent-type: %s/%s\n",
- p, ci->type->type ? ci->type->type : "(null)",
- ci->type->subtype ? ci->type->subtype : "(null)");
- else
- printf ("%scontent-type: <unset>\n", p);
- printf (
- "%scontent-transfer-encoding: %s\n",
- p, ci->encoding ? ci->encoding : "(null)");
- printf (
- "%scontent-description: %s\n",
- p, ci->description ? ci->description : "(null)");
- printf ("%ssize: %lu\n", p, (gulong) ci->size);
- ci = ci->childs;
- while (ci) {
- camel_content_info_dump (ci, depth + 1);
- ci = ci->next;
- }
-}
-
-void
-camel_message_info_dump (CamelMessageInfo *info)
-{
- if (info == NULL) {
- printf ("No message?\n");
- return;
- }
-
- printf ("Subject: %s\n", camel_message_info_get_subject (info));
- printf ("To: %s\n", camel_message_info_get_to (info));
- printf ("Cc: %s\n", camel_message_info_get_cc (info));
- printf ("mailing list: %s\n", camel_message_info_get_mlist (info));
- printf ("From: %s\n", camel_message_info_get_from (info));
- printf ("UID: %s\n", camel_message_info_get_uid (info));
- printf ("Flags: %04x\n", camel_message_info_get_flags (info));
- camel_content_info_dump (((CamelMessageInfoBase *) info)->content, 0);
-}
-
-/**
* camel_folder_summary_lock:
* @summary: a #CamelFolderSummary
*
@@ -5270,47 +3163,3 @@ camel_folder_summary_unlock (CamelFolderSummary *summary)
g_rec_mutex_unlock (&summary->priv->summary_lock);
}
-
-gint
-bdata_extract_digit (/* const */ gchar **part)
-{
- if (!part || !*part || !**part)
- return 0;
-
- if (**part == ' ')
- *part += 1;
-
- if (!**part)
- return 0;
-
- return strtoul (*part, part, 10);
-}
-
-/* expecting "digit-value", where digit is length of the value */
-gchar *
-bdata_extract_string (/* const */ gchar **part)
-{
- gint len, has_len;
- gchar *val;
-
- len = bdata_extract_digit (part);
-
- /* might be a '-' sign */
- if (part && *part && **part)
- *part += 1;
-
- if (len <= 0 || !part || !*part || !**part)
- return g_strdup ("");
-
- if (!**part)
- return g_strdup ("");
-
- has_len = strlen (*part);
- if (has_len < len)
- len = has_len;
-
- val = g_strndup (*part, len);
- *part += len;
-
- return val;
-}
diff --git a/src/camel/camel-folder-summary.h b/src/camel/camel-folder-summary.h
index d6dfff0..6bf2dde 100644
--- a/src/camel/camel-folder-summary.h
+++ b/src/camel/camel-folder-summary.h
@@ -28,7 +28,7 @@
#include <time.h>
#include <camel/camel-index.h>
-#include <camel/camel-memchunk.h>
+#include <camel/camel-message-info.h>
#include <camel/camel-mime-message.h>
#include <camel/camel-mime-parser.h>
@@ -60,156 +60,6 @@ typedef struct _CamelFolderSummary CamelFolderSummary;
typedef struct _CamelFolderSummaryClass CamelFolderSummaryClass;
typedef struct _CamelFolderSummaryPrivate CamelFolderSummaryPrivate;
-typedef struct _CamelMessageInfo CamelMessageInfo;
-typedef struct _CamelMessageInfoBase CamelMessageInfoBase;
-
-typedef struct _CamelMessageContentInfo CamelMessageContentInfo;
-
-/* A tree of message content info structures
- * describe the content structure of the message (if it has any) */
-struct _CamelMessageContentInfo {
- CamelMessageContentInfo *next;
-
- CamelMessageContentInfo *childs;
- CamelMessageContentInfo *parent;
-
- CamelContentType *type;
- gchar *id;
- gchar *description;
- gchar *encoding; /* this should be an enum?? */
- guint32 size;
-};
-
-/* system flag bits */
-typedef enum _CamelMessageFlags {
- CAMEL_MESSAGE_ANSWERED = 1 << 0,
- CAMEL_MESSAGE_DELETED = 1 << 1,
- CAMEL_MESSAGE_DRAFT = 1 << 2,
- CAMEL_MESSAGE_FLAGGED = 1 << 3,
- CAMEL_MESSAGE_SEEN = 1 << 4,
-
- /* these aren't really system flag bits, but are convenience flags */
- CAMEL_MESSAGE_ATTACHMENTS = 1 << 5,
- CAMEL_MESSAGE_ANSWERED_ALL = 1 << 6,
- CAMEL_MESSAGE_JUNK = 1 << 7,
- CAMEL_MESSAGE_SECURE = 1 << 8,
- CAMEL_MESSAGE_NOTJUNK = 1 << 9,
- CAMEL_MESSAGE_FORWARDED = 1 << 10,
-
- /* following flags are for the folder, and are not really permanent flags */
- CAMEL_MESSAGE_FOLDER_FLAGGED = 1 << 16, /* for use by the folder implementation */
- /* flags after 1 << 16 are used by camel providers,
- * if adding non permanent flags, add them to the end */
-
- CAMEL_MESSAGE_JUNK_LEARN = 1 << 30, /* used when setting CAMEL_MESSAGE_JUNK flag
- * to say that we request junk plugin
- * to learn that message as junk/non junk */
- CAMEL_MESSAGE_USER = 1 << 31 /* supports user flags */
-} CamelMessageFlags;
-
-/* Changes to system flags will NOT trigger a folder changed event */
-#define CAMEL_MESSAGE_SYSTEM_MASK (0xffff << 16)
-
-typedef struct _CamelFlag {
- struct _CamelFlag *next;
- gchar name[1]; /* name allocated as part of the structure */
-} CamelFlag;
-
-typedef struct _CamelTag {
- struct _CamelTag *next;
- gchar *value;
- gchar name[1]; /* name allocated as part of the structure */
-} CamelTag;
-
-/* a summary messageid is a 64 bit identifier (partial md5 hash) */
-typedef struct _CamelSummaryMessageID {
- union {
- guint64 id;
- guchar hash[8];
- struct {
- guint32 hi;
- guint32 lo;
- } part;
- } id;
-} CamelSummaryMessageID;
-
-/* summary references is a fixed size array of references */
-typedef struct _CamelSummaryReferences {
- gint size;
- CamelSummaryMessageID references[1];
-} CamelSummaryReferences;
-
-/* accessor id's */
-enum {
- CAMEL_MESSAGE_INFO_SUBJECT,
- CAMEL_MESSAGE_INFO_FROM,
- CAMEL_MESSAGE_INFO_TO,
- CAMEL_MESSAGE_INFO_CC,
- CAMEL_MESSAGE_INFO_MLIST,
-
- CAMEL_MESSAGE_INFO_FLAGS,
- CAMEL_MESSAGE_INFO_SIZE,
-
- CAMEL_MESSAGE_INFO_DATE_SENT,
- CAMEL_MESSAGE_INFO_DATE_RECEIVED,
-
- CAMEL_MESSAGE_INFO_MESSAGE_ID,
- CAMEL_MESSAGE_INFO_REFERENCES,
- CAMEL_MESSAGE_INFO_USER_FLAGS,
- CAMEL_MESSAGE_INFO_USER_TAGS,
-
- CAMEL_MESSAGE_INFO_HEADERS,
- CAMEL_MESSAGE_INFO_PREVIEW,
- CAMEL_MESSAGE_INFO_CONTENT,
- CAMEL_MESSAGE_INFO_LAST
-};
-
-/* information about a given message, use accessors */
-struct _CamelMessageInfo {
- CamelFolderSummary *summary;
-
- volatile gint refcount;
- const gchar *uid;
- /*FIXME: Make it work with the CAMEL_MESSADE_DB_DIRTY flag instead of another 4 bytes*/
- guint dirty : 1;
-};
-
-/* For classes wishing to do the provided i/o, or for anonymous users,
- * they must subclass or use this messageinfo structure */
-/* Otherwise they can do their own thing entirely */
-struct _CamelMessageInfoBase {
- CamelFolderSummary *summary;
-
- volatile gint refcount;
- const gchar *uid;
- /*FIXME: Make it work with the CAMEL_MESSADE_DB_DIRTY flag instead of another 4 bytes*/
- guint dirty : 1;
-
- const gchar *subject;
- const gchar *from;
- const gchar *to;
- const gchar *cc;
- const gchar *mlist;
-
- CamelMessageFlags flags;
- guint32 size;
-
- time_t date_sent;
- time_t date_received;
-
- CamelSummaryMessageID message_id;
- CamelSummaryReferences *references;/* from parent to root */
-
- struct _CamelFlag *user_flags;
- struct _CamelTag *user_tags;
-
- /* tree of content description - NULL if it is not available */
- CamelMessageContentInfo *content;
- struct _camel_header_param *headers;
- gchar *preview;
- gchar *bodystructure;
-};
-
/**
* CamelFolderSummaryFlags:
* @CAMEL_FOLDER_SUMMARY_DIRTY:
@@ -245,9 +95,7 @@ struct _CamelFIRecord;
struct _CamelFolderSummaryClass {
GObjectClass parent_class;
- /* sizes of memory objects */
- gsize message_info_size;
- gsize content_info_size;
+ GType message_info_type;
/* Load/Save folder summary from DB*/
gboolean (*summary_header_from_db)
@@ -257,28 +105,12 @@ struct _CamelFolderSummaryClass {
(*summary_header_to_db)
(CamelFolderSummary *summary,
GError **error);
- CamelMessageInfo *
- (*message_info_from_db)
- (CamelFolderSummary *summary,
- struct _CamelMIRecord *mir);
- struct _CamelMIRecord *
- (*message_info_to_db)
- (CamelFolderSummary *summary,
- CamelMessageInfo *info);
- CamelMessageContentInfo *
- (*content_info_from_db)
- (CamelFolderSummary *summary,
- struct _CamelMIRecord *mir);
- gboolean (*content_info_to_db)
- (CamelFolderSummary *summary,
- CamelMessageContentInfo *info,
- struct _CamelMIRecord *mir);
- /* create/save/load an individual message info */
+ /* create an individual message info */
CamelMessageInfo *
(*message_info_new_from_header)
(CamelFolderSummary *summary,
- struct _camel_header_raw *header);
+ CamelHeaderRaw *header);
CamelMessageInfo *
(*message_info_new_from_parser)
(CamelFolderSummary *summary,
@@ -286,32 +118,8 @@ struct _CamelFolderSummaryClass {
CamelMessageInfo *
(*message_info_new_from_message)
(CamelFolderSummary *summary,
- CamelMimeMessage *message,
- const gchar *bodystructure);
- void (*message_info_free)
- (CamelFolderSummary *summary,
- CamelMessageInfo *ci);
- CamelMessageInfo *
- (*message_info_clone)
- (CamelFolderSummary *summary,
- const CamelMessageInfo *info);
+ CamelMimeMessage *message);
- /* save/load individual content info's */
- CamelMessageContentInfo *
- (*content_info_new_from_header)
- (CamelFolderSummary *summary,
- struct _camel_header_raw *header);
- CamelMessageContentInfo *
- (*content_info_new_from_parser)
- (CamelFolderSummary *summary,
- CamelMimeParser *parser);
- CamelMessageContentInfo *
- (*content_info_new_from_message)
- (CamelFolderSummary *summary,
- CamelMimePart *mime_part);
- void (*content_info_free)
- (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci);
CamelMessageInfo *
(*message_info_from_uid)
(CamelFolderSummary *summary,
@@ -321,34 +129,8 @@ struct _CamelFolderSummaryClass {
gchar * (*next_uid_string)
(CamelFolderSummary *summary);
- /* virtual accessors on messageinfo's */
- gconstpointer (*info_ptr) (const CamelMessageInfo *info,
- gint id);
- guint32 (*info_uint32) (const CamelMessageInfo *info,
- gint id);
- time_t (*info_time) (const CamelMessageInfo *info,
- gint id);
-
- gboolean (*info_user_flag)
- (const CamelMessageInfo *info,
- const gchar *id);
- const gchar * (*info_user_tag)
- (const CamelMessageInfo *info,
- const gchar *id);
-
- /* set accessors for the modifyable bits */
- gboolean (*info_set_user_flag)
- (CamelMessageInfo *info,
- const gchar *id,
- gboolean state);
- gboolean (*info_set_user_tag)
- (CamelMessageInfo *info,
- const gchar *id,
- const gchar *val);
- gboolean (*info_set_flags)
- (CamelMessageInfo *info,
- guint32 mask,
- guint32 set);
+ /* Padding for future expansion */
+ gpointer reserved[20];
};
GType camel_folder_summary_get_type (void);
@@ -374,16 +156,6 @@ guint32 camel_folder_summary_get_visible_count
void camel_folder_summary_set_index (CamelFolderSummary *summary,
CamelIndex *index);
CamelIndex * camel_folder_summary_get_index (CamelFolderSummary *summary);
-void camel_folder_summary_set_build_content
- (CamelFolderSummary *summary,
- gboolean state);
-gboolean camel_folder_summary_get_build_content
- (CamelFolderSummary *summary);
-void camel_folder_summary_set_need_preview
- (CamelFolderSummary *summary,
- gboolean preview);
-gboolean camel_folder_summary_get_need_preview
- (CamelFolderSummary *summary);
guint32 camel_folder_summary_next_uid (CamelFolderSummary *summary);
void camel_folder_summary_set_next_uid
(CamelFolderSummary *summary,
@@ -417,7 +189,7 @@ void camel_folder_summary_touch (CamelFolderSummary *summary);
CamelMessageInfo *
camel_folder_summary_info_new_from_header
(CamelFolderSummary *summary,
- struct _camel_header_raw *headers);
+ CamelHeaderRaw *headers);
CamelMessageInfo *
camel_folder_summary_info_new_from_parser
(CamelFolderSummary *summary,
@@ -425,28 +197,12 @@ CamelMessageInfo *
CamelMessageInfo *
camel_folder_summary_info_new_from_message
(CamelFolderSummary *summary,
- CamelMimeMessage *message,
- const gchar *bodystructure);
-
-CamelMessageContentInfo *
- camel_folder_summary_content_info_new
- (CamelFolderSummary *summary);
-void camel_folder_summary_content_info_free
- (CamelFolderSummary *summary,
- CamelMessageContentInfo *ci);
-
-void camel_folder_summary_add_preview
- (CamelFolderSummary *summary,
- CamelMessageInfo *info);
+ CamelMimeMessage *message);
/* add a new raw summary item */
void camel_folder_summary_add (CamelFolderSummary *summary,
- CamelMessageInfo *info);
-
-/* insert mi to summary */
-void camel_folder_summary_insert (CamelFolderSummary *summary,
CamelMessageInfo *info,
- gboolean load);
+ gboolean force_keep_uid);
gboolean camel_folder_summary_remove (CamelFolderSummary *summary,
CamelMessageInfo *info);
@@ -499,134 +255,15 @@ void camel_folder_summary_prepare_fetch_all
void camel_folder_summary_lock (CamelFolderSummary *summary);
void camel_folder_summary_unlock (CamelFolderSummary *summary);
-/* message flag operations */
-gboolean camel_flag_get (CamelFlag **list,
- const gchar *name);
-gboolean camel_flag_set (CamelFlag **list,
- const gchar *name,
- gboolean value);
-gboolean camel_flag_list_copy (CamelFlag **to,
- CamelFlag **from);
-gint camel_flag_list_size (CamelFlag **list);
-void camel_flag_list_free (CamelFlag **list);
-
CamelMessageFlags
camel_system_flag (const gchar *name);
gboolean camel_system_flag_get (CamelMessageFlags flags,
const gchar *name);
-/* message tag operations */
-const gchar * camel_tag_get (CamelTag **list,
- const gchar *name);
-gboolean camel_tag_set (CamelTag **list,
- const gchar *name,
- const gchar *value);
-gboolean camel_tag_list_copy (CamelTag **to,
- CamelTag **from);
-gint camel_tag_list_size (CamelTag **list);
-void camel_tag_list_free (CamelTag **list);
-
-/* Summary may be null */
-/* Use anonymous pointers to avoid tons of cast crap */
-GType camel_message_info_get_type (void) G_GNUC_CONST;
-gpointer camel_message_info_new (CamelFolderSummary *summary);
-gpointer camel_message_info_ref (gpointer info);
CamelMessageInfo *
camel_message_info_new_from_header
(CamelFolderSummary *summary,
- struct _camel_header_raw *header);
-void camel_message_info_unref (gpointer info);
-gpointer camel_message_info_clone (gconstpointer info);
-
-/* These will be fully removed soon, left only for a backward compatibility */
-#define camel_message_info_ptr camel_message_info_get_ptr
-#define camel_message_info_uint32 camel_message_info_get_uint32
-#define camel_message_info_time camel_message_info_get_time
-#define camel_message_info_uid camel_message_info_get_uid
-#define camel_message_info_subject camel_message_info_get_subject
-#define camel_message_info_preview camel_message_info_get_preview
-#define camel_message_info_from camel_message_info_get_from
-#define camel_message_info_to camel_message_info_get_to
-#define camel_message_info_cc camel_message_info_get_cc
-#define camel_message_info_mlist camel_message_info_get_mlist
-#define camel_message_info_flags camel_message_info_get_flags
-#define camel_message_info_size camel_message_info_get_size
-#define camel_message_info_date_sent camel_message_info_get_date_sent
-#define camel_message_info_date_received camel_message_info_get_date_received
-#define camel_message_info_message_id camel_message_info_get_message_id
-#define camel_message_info_references camel_message_info_get_references
-#define camel_message_info_user_flags camel_message_info_get_user_flags
-#define camel_message_info_user_tags camel_message_info_get_user_tags
-#define camel_message_info_headers camel_message_info_get_headers
-#define camel_message_info_content camel_message_info_get_content
-#define camel_message_info_user_flag camel_message_info_get_user_flag
-#define camel_message_info_user_tag camel_message_info_get_user_tag
-
-/* accessors */
-gconstpointer camel_message_info_get_ptr (gconstpointer info,
- gint id);
-guint32 camel_message_info_get_uint32 (gconstpointer info,
- gint id);
-time_t camel_message_info_get_time (gconstpointer info,
- gint id);
-
-const gchar * camel_message_info_get_uid (gconstpointer info);
-const gchar * camel_message_info_get_subject (gconstpointer info);
-const gchar * camel_message_info_get_preview (gconstpointer info);
-const gchar * camel_message_info_get_from (gconstpointer info);
-const gchar * camel_message_info_get_to (gconstpointer info);
-
-const gchar * camel_message_info_get_cc (gconstpointer info);
-const gchar * camel_message_info_get_mlist (gconstpointer info);
-guint32 camel_message_info_get_flags (gconstpointer info);
-guint32 camel_message_info_get_size (gconstpointer info);
-
-time_t camel_message_info_get_date_sent
- (gconstpointer info);
-time_t camel_message_info_get_date_received
- (gconstpointer info);
-
-const CamelSummaryMessageID *
- camel_message_info_get_message_id
- (gconstpointer info);
-const CamelSummaryReferences *
- camel_message_info_get_references
- (gconstpointer info);
-const CamelFlag *
- camel_message_info_get_user_flags
- (gconstpointer info);
-const CamelTag *
- camel_message_info_get_user_tags
- (gconstpointer info);
-const CamelHeaderParam *
- camel_message_info_get_headers (gconstpointer info);
-const CamelMessageContentInfo *
- camel_message_info_get_content (gconstpointer info);
-gboolean camel_message_info_get_user_flag(gconstpointer info,
- const gchar *id);
-const gchar * camel_message_info_get_user_tag (gconstpointer info,
- const gchar *id);
-
-gboolean camel_message_info_set_flags (CamelMessageInfo *info,
- CamelMessageFlags flags,
- guint32 set);
-gboolean camel_message_info_set_user_flag
- (CamelMessageInfo *info,
- const gchar *id,
- gboolean state);
-gboolean camel_message_info_set_user_tag (CamelMessageInfo *info,
- const gchar *id,
- const gchar *val);
-
-/* debugging functions */
-void camel_content_info_dump (CamelMessageContentInfo *ci,
- gint depth);
-void camel_message_info_dump (CamelMessageInfo *info);
-
-/* utility functions for bdata string decomposition */
-gint bdata_extract_digit (gchar **part);
-gchar * bdata_extract_string (gchar **part);
-
+ CamelHeaderRaw *header);
G_END_DECLS
#endif /* CAMEL_FOLDER_SUMMARY_H */
diff --git a/src/camel/camel-folder-thread.c b/src/camel/camel-folder-thread.c
index 277ccea..b3183f5 100644
--- a/src/camel/camel-folder-thread.c
+++ b/src/camel/camel-folder-thread.c
@@ -372,12 +372,16 @@ dump_tree_rec (struct _tree_info *info,
g_hash_table_insert (info->visited, c, c);
}
if (c->message) {
+ CamelSummaryMessageID message_id;
+
+ message_id.id.id = camel_message_info_get_message_id (c->message);
+
printf (
"%s %p Subject: %s <%08x%08x>\n",
p, (gpointer) c,
camel_message_info_get_subject (c->message),
- camel_message_info_get_message_id (c->message)->id.part.hi,
- camel_message_info_get_message_id (c->message)->id.part.lo);
+ message_id.id.part.hi,
+ message_id.id.part.lo);
count += 1;
} else {
printf ("%s %p <empty>\n", p, (gpointer) c);
@@ -462,18 +466,18 @@ sort_thread (CamelFolderThreadNode **cp)
}
static guint
-id_hash (gpointer key)
+id_hash (gconstpointer key)
{
- CamelSummaryMessageID *id = (CamelSummaryMessageID *) key;
+ const CamelSummaryMessageID *id = key;
return id->id.part.lo;
}
-static gint
-id_equal (gpointer a,
- gpointer b)
+static gboolean
+id_equal (gconstpointer a,
+ gconstpointer b)
{
- return ((CamelSummaryMessageID *) a)->id.id == ((CamelSummaryMessageID *) b)->id.id;
+ return ((const CamelSummaryMessageID *) a)->id.id == ((const CamelSummaryMessageID *) b)->id.id;
}
/* perform actual threading */
@@ -491,15 +495,20 @@ thread_summary (CamelFolderThread *thread,
gettimeofday (&start, NULL);
#endif
- id_table = g_hash_table_new ((GHashFunc) id_hash, (GCompareFunc) id_equal);
+ id_table = g_hash_table_new_full (id_hash, id_equal, g_free, NULL);
no_id_table = g_hash_table_new (NULL, NULL);
for (i = 0; i < summary->len; i++) {
CamelMessageInfo *mi = summary->pdata[i];
- const CamelSummaryMessageID *mid = camel_message_info_get_message_id (mi);
- const CamelSummaryReferences *references = camel_message_info_get_references (mi);
+ CamelSummaryMessageID *message_id_copy, message_id;
+ const GArray *references;
+
+ camel_message_info_property_lock (mi);
- if (mid != NULL && mid->id.id) {
- c = g_hash_table_lookup (id_table, mid);
+ message_id.id.id = camel_message_info_get_message_id (mi);
+ references = camel_message_info_get_references (mi);
+
+ if (message_id.id.id) {
+ c = g_hash_table_lookup (id_table, &message_id);
/* check for duplicate messages */
if (c && c->order) {
/* if duplicate, just make out it is a no-id message, but try and insert it
@@ -508,9 +517,11 @@ thread_summary (CamelFolderThread *thread,
c = camel_memchunk_alloc0 (thread->node_chunks);
g_hash_table_insert (no_id_table, (gpointer) mi, c);
} else if (!c) {
- d (printf ("doing : %08x%08x (%s)\n", mid->id.part.hi, mid->id.part.lo,
camel_message_info_get_subject (mi)));
+ d (printf ("doing : %08x%08x (%s)\n", message_id.id.part.hi,
message_id.id.part.lo, camel_message_info_get_subject (mi)));
c = camel_memchunk_alloc0 (thread->node_chunks);
- g_hash_table_insert (id_table, (gpointer) mid, c);
+ message_id_copy = g_new0 (CamelSummaryMessageID, 1);
+ message_id_copy->id.id = message_id.id.id;
+ g_hash_table_insert (id_table, message_id_copy, c);
}
} else {
d (printf ("doing : (no message id)\n"));
@@ -522,21 +533,26 @@ thread_summary (CamelFolderThread *thread,
c->order = i + 1;
child = c;
if (references) {
- gint j;
+ guint jj;
d (printf ("%s (%s) references:\n", G_STRLOC, G_STRFUNC); )
- for (j = 0; j < references->size; j++) {
+
+ for (jj = 0; jj < references->len; jj++) {
gboolean found = FALSE;
+ message_id.id.id = g_array_index (references, guint64, jj);
+
/* should never be empty, but just incase */
- if (references->references[j].id.id == 0)
+ if (!message_id.id.id)
continue;
- c = g_hash_table_lookup (id_table, &references->references[j]);
+ c = g_hash_table_lookup (id_table, &message_id);
if (c == NULL) {
d (printf ("%s (%s) not found\n", G_STRLOC, G_STRFUNC));
c = camel_memchunk_alloc0 (thread->node_chunks);
- g_hash_table_insert (id_table, (gpointer) &references->references[j],
c);
+ message_id_copy = g_new0 (CamelSummaryMessageID, 1);
+ message_id_copy->id.id = message_id.id.id;
+ g_hash_table_insert (id_table, message_id_copy, c);
} else
found = TRUE;
if (c != child) {
@@ -550,6 +566,8 @@ thread_summary (CamelFolderThread *thread,
child = c;
}
}
+
+ camel_message_info_property_unlock (mi);
}
d (printf ("\n\n"));
@@ -713,7 +731,7 @@ add_present_rec (CamelFolderThread *thread,
g_hash_table_remove (have, uid);
g_ptr_array_add (summary, info);
} else {
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
if (node->child)
@@ -782,7 +800,7 @@ camel_folder_thread_messages_unref (CamelFolderThread *thread)
gint i;
for (i = 0; i < thread->summary->len; i++)
- camel_message_info_unref (thread->summary->pdata[i]);
+ g_clear_object (&thread->summary->pdata[i]);
g_ptr_array_free (thread->summary, TRUE);
g_object_unref (thread->folder);
}
diff --git a/src/camel/camel-folder.c b/src/camel/camel-folder.c
index 2b08478..b15ae5b 100644
--- a/src/camel/camel-folder.c
+++ b/src/camel/camel-folder.c
@@ -135,7 +135,7 @@ async_context_free (AsyncContext *async_context)
g_object_unref (async_context->message);
if (async_context->info != NULL)
- camel_message_info_unref (async_context->info);
+ g_clear_object (&async_context->info);
if (async_context->destination != NULL)
g_object_unref (async_context->destination);
@@ -299,7 +299,7 @@ folder_filter (CamelSession *session,
continue;
camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK_LEARN, 0);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
@@ -310,7 +310,7 @@ folder_filter (CamelSession *session,
continue;
camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK_LEARN, 0);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
@@ -444,7 +444,7 @@ folder_filter (CamelSession *session,
data->driver, NULL, info, uid, data->folder,
store_uid, store_uid, cancellable, error);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_operation_pop_message (cancellable);
@@ -493,8 +493,8 @@ folder_transfer_message_to (CamelFolder *source,
/* if its deleted we poke the flags, so we need to copy the messageinfo */
if ((source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
&& (minfo = camel_folder_get_message_info (source, uid))) {
- info = camel_message_info_clone (minfo);
- camel_message_info_unref (minfo);
+ info = camel_message_info_clone (minfo, NULL);
+ g_clear_object (&minfo);
} else
info = camel_message_info_new_from_header (NULL, ((CamelMimePart *) msg)->headers);
@@ -517,7 +517,7 @@ folder_transfer_message_to (CamelFolder *source,
source, uid, CAMEL_MESSAGE_DELETED |
CAMEL_MESSAGE_SEEN, ~0);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
static gboolean
@@ -706,18 +706,18 @@ folder_get_message_count (CamelFolder *folder)
return camel_folder_summary_count (folder->summary);
}
-static CamelMessageFlags
+static guint32
folder_get_permanent_flags (CamelFolder *folder)
{
return folder->permanent_flags;
}
-static CamelMessageFlags
+static guint32
folder_get_message_flags (CamelFolder *folder,
const gchar *uid)
{
CamelMessageInfo *info;
- CamelMessageFlags flags;
+ guint32 flags;
g_return_val_if_fail (folder->summary != NULL, 0);
@@ -726,7 +726,7 @@ folder_get_message_flags (CamelFolder *folder,
return 0;
flags = camel_message_info_get_flags (info);
- camel_message_info_unref (info);
+ g_clear_object (&info);
return flags;
}
@@ -734,8 +734,8 @@ folder_get_message_flags (CamelFolder *folder,
static gboolean
folder_set_message_flags (CamelFolder *folder,
const gchar *uid,
- CamelMessageFlags flags,
- CamelMessageFlags set)
+ guint32 mask,
+ guint32 set)
{
CamelMessageInfo *info;
gint res;
@@ -746,8 +746,8 @@ folder_set_message_flags (CamelFolder *folder,
if (info == NULL)
return FALSE;
- res = camel_message_info_set_flags (info, flags, set);
- camel_message_info_unref (info);
+ res = camel_message_info_set_flags (info, mask, set);
+ g_clear_object (&info);
return res;
}
@@ -767,7 +767,7 @@ folder_get_message_user_flag (CamelFolder *folder,
return FALSE;
ret = camel_message_info_get_user_flag (info, name);
- camel_message_info_unref (info);
+ g_clear_object (&info);
return ret;
}
@@ -787,7 +787,7 @@ folder_set_message_user_flag (CamelFolder *folder,
return;
camel_message_info_set_user_flag (info, name, value);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
static const gchar *
@@ -805,7 +805,7 @@ folder_get_message_user_tag (CamelFolder *folder,
return NULL;
ret = camel_message_info_get_user_tag (info, name);
- camel_message_info_unref (info);
+ g_clear_object (&info);
return ret;
}
@@ -825,7 +825,7 @@ folder_set_message_user_tag (CamelFolder *folder,
return;
camel_message_info_set_user_tag (info, name, value);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
static GPtrArray *
@@ -1113,7 +1113,7 @@ folder_changed (CamelFolder *folder,
junk_filter = camel_session_get_junk_filter (session);
if (junk_filter != NULL && info->uid_changed->len) {
- CamelMessageFlags flags;
+ guint32 flags;
for (i = 0; i < info->uid_changed->len; i++) {
flags = camel_folder_summary_get_info_flags (folder->summary,
info->uid_changed->pdata[i]);
@@ -1704,7 +1704,7 @@ camel_folder_get_deleted_message_count (CamelFolder *folder)
* stored on a message between sessions. If it includes
* #CAMEL_FLAG_USER, then user-defined flags will be remembered.
**/
-CamelMessageFlags
+guint32
camel_folder_get_permanent_flags (CamelFolder *folder)
{
CamelFolderClass *class;
@@ -1727,7 +1727,7 @@ camel_folder_get_permanent_flags (CamelFolder *folder)
* Returns: the #CamelMessageFlags that are set on the indicated
* message.
**/
-CamelMessageFlags
+guint32
camel_folder_get_message_flags (CamelFolder *folder,
const gchar *uid)
{
@@ -1746,10 +1746,10 @@ camel_folder_get_message_flags (CamelFolder *folder,
* camel_folder_set_message_flags:
* @folder: a #CamelFolder
* @uid: the UID of a message in @folder
- * @flags: a set of #CamelMessageFlag values to set
- * @set: the mask of values in @flags to use.
+ * @mask: a mask of #CamelMessageFlag bit-or values to use
+ * @set: the flags to ser, also bit-or of #CamelMessageFlag
*
- * Sets those flags specified by @flags to the values specified by @set
+ * Sets those flags specified by @mask to the values specified by @set
* on the indicated message. (This may or may not persist after the
* folder or store is closed. See camel_folder_get_permanent_flags())
*
@@ -1764,8 +1764,8 @@ camel_folder_get_message_flags (CamelFolder *folder,
gboolean
camel_folder_set_message_flags (CamelFolder *folder,
const gchar *uid,
- CamelMessageFlags flags,
- CamelMessageFlags set)
+ guint32 mask,
+ guint32 set)
{
CamelFolderClass *class;
@@ -1775,12 +1775,7 @@ camel_folder_set_message_flags (CamelFolder *folder,
class = CAMEL_FOLDER_GET_CLASS (folder);
g_return_val_if_fail (class->set_message_flags != NULL, FALSE);
- if ((flags & (CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_JUNK_LEARN)) == CAMEL_MESSAGE_JUNK) {
- flags |= CAMEL_MESSAGE_JUNK_LEARN;
- set &= ~CAMEL_MESSAGE_JUNK_LEARN;
- }
-
- return class->set_message_flags (folder, uid, flags, set);
+ return class->set_message_flags (folder, uid, mask, set);
}
/**
@@ -1910,11 +1905,11 @@ camel_folder_set_message_user_tag (CamelFolder *folder,
* @folder: a #CamelFolder
* @uid: the uid of a message
*
- * Retrieve the #CamelMessageInfo for the specified @uid. This return
- * must be freed using camel_message_info_unref().
+ * Retrieve the #CamelMessageInfo for the specified @uid.
*
- * Returns: the summary information for the indicated message, or %NULL
- * if the uid does not exist
+ * Returns: (transfer full): The summary information for the indicated message, or %NULL
+ * if the uid does not exist. Free the returned object with g_object_unref(),
+ * when done with it.
**/
CamelMessageInfo *
camel_folder_get_message_info (CamelFolder *folder,
@@ -2807,7 +2802,7 @@ camel_folder_append_message (CamelFolder *folder,
async_context = g_slice_new0 (AsyncContext);
async_context->message = g_object_ref (message);
- async_context->info = camel_message_info_ref (info);
+ async_context->info = g_object_ref (info);
task = g_task_new (folder, cancellable, callback, user_data);
g_task_set_source_tag (task, camel_folder_append_message);
diff --git a/src/camel/camel-folder.h b/src/camel/camel-folder.h
index df2cdbb..70d7898 100644
--- a/src/camel/camel-folder.h
+++ b/src/camel/camel-folder.h
@@ -125,7 +125,7 @@ struct _CamelFolder {
CamelFolderSummary *summary;
CamelFolderFlags folder_flags;
- CamelMessageFlags permanent_flags;
+ guint32 permanent_flags; /* bit-or of CamelMessageFlags */
/* Future ABI expansion */
gpointer later[4];
@@ -136,15 +136,13 @@ struct _CamelFolderClass {
/* Non-Blocking Methods */
gint (*get_message_count) (CamelFolder *folder);
- CamelMessageFlags
- (*get_permanent_flags) (CamelFolder *folder);
- CamelMessageFlags
- (*get_message_flags) (CamelFolder *folder,
+ guint32 (*get_permanent_flags) (CamelFolder *folder);
+ guint32 (*get_message_flags) (CamelFolder *folder,
const gchar *uid);
gboolean (*set_message_flags) (CamelFolder *folder,
const gchar *uid,
- CamelMessageFlags flags,
- CamelMessageFlags set);
+ guint32 mask,
+ guint32 set);
gboolean (*get_message_user_flag)(CamelFolder *folder,
const gchar *uid,
const gchar *name);
@@ -283,17 +281,15 @@ const gchar * camel_folder_get_description (CamelFolder *folder);
gchar * camel_folder_dup_description (CamelFolder *folder);
void camel_folder_set_description (CamelFolder *folder,
const gchar *description);
-CamelMessageFlags
- camel_folder_get_permanent_flags
+guint32 camel_folder_get_permanent_flags
(CamelFolder *folder);
#ifndef CAMEL_DISABLE_DEPRECATED
-CamelMessageFlags
- camel_folder_get_message_flags (CamelFolder *folder,
+guint32 camel_folder_get_message_flags (CamelFolder *folder,
const gchar *uid);
gboolean camel_folder_set_message_flags (CamelFolder *folder,
const gchar *uid,
- CamelMessageFlags flags,
- CamelMessageFlags set);
+ guint32 mask,
+ guint32 set);
gboolean camel_folder_get_message_user_flag
(CamelFolder *folder,
const gchar *uid,
diff --git a/src/camel/camel-index.h b/src/camel/camel-index.h
index 5bec6cf..8ed26bd 100644
--- a/src/camel/camel-index.h
+++ b/src/camel/camel-index.h
@@ -94,7 +94,7 @@ typedef struct _CamelIndexCursor CamelIndexCursor;
typedef struct _CamelIndexCursorClass CamelIndexCursorClass;
typedef struct _CamelIndexCursorPrivate CamelIndexCursorPrivate;
-typedef gchar * (*CamelIndexNorm)(CamelIndex *index, const gchar *word, gpointer data);
+typedef gchar * (*CamelIndexNorm)(CamelIndex *index, const gchar *word, gpointer user_data);
/* ********************************************************************** */
diff --git a/src/camel/camel-message-info-base.c b/src/camel/camel-message-info-base.c
new file mode 100644
index 0000000..ce8315e
--- /dev/null
+++ b/src/camel/camel-message-info-base.c
@@ -0,0 +1,877 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "camel-folder-summary.h"
+#include "camel-message-info.h"
+
+#include "camel-message-info-base.h"
+
+struct _CamelMessageInfoBasePrivate {
+ guint32 flags; /* bit-or of CamelMessageFlags */
+ CamelNamedFlags *user_flags;
+ CamelNameValueArray *user_tags;
+ gchar *subject;
+ gchar *from;
+ gchar *to;
+ gchar *cc;
+ gchar *mlist;
+ guint32 size;
+ gint64 date_sent; /* aka time_t */
+ gint64 date_received; /* aka time_t */
+ guint64 message_id;
+ GArray *references; /* guint64, aka CamelSummaryMessageID */
+ CamelNameValueArray *headers;
+};
+
+G_DEFINE_TYPE (CamelMessageInfoBase, camel_message_info_base, CAMEL_TYPE_MESSAGE_INFO)
+
+static guint32
+message_info_base_get_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ guint32 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), 0);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->flags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_flags (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set)
+{
+ CamelMessageInfoBase *bmi;
+ guint32 old_flags;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ old_flags = bmi->priv->flags;
+ bmi->priv->flags = (old_flags & ~mask) | (set & mask);
+ changed = old_flags != bmi->priv->flags;
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static gboolean
+message_info_base_get_user_flag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ if (bmi->priv->user_flags)
+ result = camel_named_flags_contains (bmi->priv->user_flags, name);
+ else
+ result = FALSE;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_user_flag (CamelMessageInfo *mi,
+ const gchar *name,
+ gboolean state)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ if (!bmi->priv->user_flags)
+ bmi->priv->user_flags = camel_named_flags_new ();
+
+ if (state)
+ changed = camel_named_flags_insert (bmi->priv->user_flags, name);
+ else
+ changed = camel_named_flags_remove (bmi->priv->user_flags, name);
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const CamelNamedFlags *
+message_info_base_get_user_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->user_flags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static CamelNamedFlags *
+message_info_base_dup_user_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ if (bmi->priv->user_flags)
+ result = camel_named_flags_copy (bmi->priv->user_flags);
+ else
+ result = NULL;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_take_user_flags (CamelMessageInfo *mi,
+ CamelNamedFlags *user_flags)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !camel_named_flags_equal (bmi->priv->user_flags, user_flags);
+
+ if (changed) {
+ camel_named_flags_free (bmi->priv->user_flags);
+ bmi->priv->user_flags = user_flags;
+ } else {
+ camel_named_flags_free (user_flags);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_user_tag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ if (bmi->priv->user_tags)
+ result = camel_name_value_array_get_named (bmi->priv->user_tags, TRUE, name);
+ else
+ result = NULL;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_user_tag (CamelMessageInfo *mi,
+ const gchar *name,
+ const gchar *value)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ if (!bmi->priv->user_tags)
+ bmi->priv->user_tags = camel_name_value_array_new ();
+
+ if (value)
+ changed = camel_name_value_array_set_named (bmi->priv->user_tags, TRUE, name, value);
+ else
+ changed = camel_name_value_array_remove_named (bmi->priv->user_tags, TRUE, name, FALSE);
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const CamelNameValueArray *
+message_info_base_get_user_tags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->user_tags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static CamelNameValueArray *
+message_info_base_dup_user_tags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = camel_name_value_array_copy (bmi->priv->user_tags);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_take_user_tags (CamelMessageInfo *mi,
+ CamelNameValueArray *user_tags)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !camel_name_value_array_equal (bmi->priv->user_tags, user_tags, TRUE);
+
+ if (changed) {
+ camel_name_value_array_free (bmi->priv->user_tags);
+ bmi->priv->user_tags = user_tags;
+ } else {
+ camel_name_value_array_free (user_tags);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_subject (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->subject;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_subject (CamelMessageInfo *mi,
+ const gchar *subject)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (bmi->priv->subject, subject) != 0;
+
+ if (changed) {
+ g_free (bmi->priv->subject);
+ bmi->priv->subject = g_strdup (subject);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_from (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->from;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_from (CamelMessageInfo *mi,
+ const gchar *from)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (bmi->priv->from, from) != 0;
+
+ if (changed) {
+ g_free (bmi->priv->from);
+ bmi->priv->from = g_strdup (from);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_to (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->to;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_to (CamelMessageInfo *mi,
+ const gchar *to)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (bmi->priv->to, to) != 0;
+
+ if (changed) {
+ g_free (bmi->priv->to);
+ bmi->priv->to = g_strdup (to);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_cc (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->cc;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_cc (CamelMessageInfo *mi,
+ const gchar *cc)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (bmi->priv->cc, cc) != 0;
+
+ if (changed) {
+ g_free (bmi->priv->cc);
+ bmi->priv->cc = g_strdup (cc);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const gchar *
+message_info_base_get_mlist (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->mlist;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_mlist (CamelMessageInfo *mi,
+ const gchar *mlist)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (bmi->priv->mlist, mlist) != 0;
+
+ if (changed) {
+ g_free (bmi->priv->mlist);
+ bmi->priv->mlist = g_strdup (mlist);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static guint32
+message_info_base_get_size (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ guint32 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), 0);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->size;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_size (CamelMessageInfo *mi,
+ guint32 size)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = bmi->priv->size != size;
+
+ if (changed)
+ bmi->priv->size = size;
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static gint64
+message_info_base_get_date_sent (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ gint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), 0);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->date_sent;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_date_sent (CamelMessageInfo *mi,
+ gint64 date_sent)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = bmi->priv->date_sent != date_sent;
+
+ if (changed)
+ bmi->priv->date_sent = date_sent;
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static gint64
+message_info_base_get_date_received (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ gint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), 0);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->date_received;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_date_received (CamelMessageInfo *mi,
+ gint64 date_received)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = bmi->priv->date_received != date_received;
+
+ if (changed)
+ bmi->priv->date_received = date_received;
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static guint64
+message_info_base_get_message_id (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ guint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), 0);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->message_id;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_set_message_id (CamelMessageInfo *mi,
+ guint64 message_id)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = bmi->priv->message_id != message_id;
+
+ if (changed)
+ bmi->priv->message_id = message_id;
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const GArray *
+message_info_base_get_references (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const GArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->references;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_references_equal (const GArray *references_a,
+ const GArray *references_b)
+{
+ guint ii, len;
+
+ if (references_a == references_b)
+ return TRUE;
+
+ if (!references_a || !references_b)
+ return FALSE;
+
+ len = references_a->len;
+ if (len != references_b->len)
+ return FALSE;
+
+ /* They can be still the same, only having the items on different indexes,
+ but that's too expensive to compare precisely. */
+ for (ii = 0; ii < len; ii++) {
+ if (g_array_index (references_a, guint64, ii) != g_array_index (references_b, guint64, ii))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+message_info_base_take_references (CamelMessageInfo *mi,
+ GArray *references)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !message_info_base_references_equal (bmi->priv->references, references);
+
+ if (changed) {
+ if (bmi->priv->references)
+ g_array_unref (bmi->priv->references);
+ bmi->priv->references = references;
+ } else if (references) {
+ g_array_unref (references);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static const CamelNameValueArray *
+message_info_base_get_headers (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoBase *bmi;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+ result = bmi->priv->headers;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+static gboolean
+message_info_base_take_headers (CamelMessageInfo *mi,
+ CamelNameValueArray *headers)
+{
+ CamelMessageInfoBase *bmi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO_BASE (mi), FALSE);
+
+ bmi = CAMEL_MESSAGE_INFO_BASE (mi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !camel_name_value_array_equal (bmi->priv->headers, headers, TRUE);
+
+ if (changed) {
+ camel_name_value_array_free (bmi->priv->headers);
+ bmi->priv->headers = headers;
+ } else {
+ camel_name_value_array_free (headers);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ return changed;
+}
+
+static void
+message_info_base_dispose (GObject *object)
+{
+ CamelMessageInfoBase *bmi = CAMEL_MESSAGE_INFO_BASE (object);
+
+ camel_named_flags_free (bmi->priv->user_flags);
+ bmi->priv->user_flags = NULL;
+
+ camel_name_value_array_free (bmi->priv->user_tags);
+ bmi->priv->user_tags = NULL;
+
+ #define free_ptr(x) G_STMT_START { g_free (x); x = NULL; } G_STMT_END
+
+ free_ptr (bmi->priv->subject);
+ free_ptr (bmi->priv->from);
+ free_ptr (bmi->priv->to);
+ free_ptr (bmi->priv->cc);
+ free_ptr (bmi->priv->mlist);
+
+ #undef free_ptr
+
+ if (bmi->priv->references) {
+ g_array_unref (bmi->priv->references);
+ bmi->priv->references = NULL;
+ }
+
+ camel_name_value_array_free (bmi->priv->headers);
+ bmi->priv->headers = NULL;
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_message_info_base_parent_class)->dispose (object);
+}
+
+static void
+camel_message_info_base_class_init (CamelMessageInfoBaseClass *class)
+{
+ CamelMessageInfoClass *mi_class;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelMessageInfoBasePrivate));
+
+ mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
+ mi_class->get_flags = message_info_base_get_flags;
+ mi_class->set_flags = message_info_base_set_flags;
+ mi_class->get_user_flag = message_info_base_get_user_flag;
+ mi_class->set_user_flag = message_info_base_set_user_flag;
+ mi_class->get_user_flags = message_info_base_get_user_flags;
+ mi_class->dup_user_flags = message_info_base_dup_user_flags;
+ mi_class->take_user_flags = message_info_base_take_user_flags;
+ mi_class->get_user_tag = message_info_base_get_user_tag;
+ mi_class->set_user_tag = message_info_base_set_user_tag;
+ mi_class->get_user_tags = message_info_base_get_user_tags;
+ mi_class->dup_user_tags = message_info_base_dup_user_tags;
+ mi_class->take_user_tags = message_info_base_take_user_tags;
+ mi_class->get_subject = message_info_base_get_subject;
+ mi_class->set_subject = message_info_base_set_subject;
+ mi_class->get_from = message_info_base_get_from;
+ mi_class->set_from = message_info_base_set_from;
+ mi_class->get_to = message_info_base_get_to;
+ mi_class->set_to = message_info_base_set_to;
+ mi_class->get_cc = message_info_base_get_cc;
+ mi_class->set_cc = message_info_base_set_cc;
+ mi_class->get_mlist = message_info_base_get_mlist;
+ mi_class->set_mlist = message_info_base_set_mlist;
+ mi_class->get_size = message_info_base_get_size;
+ mi_class->set_size = message_info_base_set_size;
+ mi_class->get_date_sent = message_info_base_get_date_sent;
+ mi_class->set_date_sent = message_info_base_set_date_sent;
+ mi_class->get_date_received = message_info_base_get_date_received;
+ mi_class->set_date_received = message_info_base_set_date_received;
+ mi_class->get_message_id = message_info_base_get_message_id;
+ mi_class->set_message_id = message_info_base_set_message_id;
+ mi_class->get_references = message_info_base_get_references;
+ mi_class->take_references = message_info_base_take_references;
+ mi_class->get_headers = message_info_base_get_headers;
+ mi_class->take_headers = message_info_base_take_headers;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = message_info_base_dispose;
+}
+
+static void
+camel_message_info_base_init (CamelMessageInfoBase *bmi)
+{
+ bmi->priv = G_TYPE_INSTANCE_GET_PRIVATE (bmi, CAMEL_TYPE_MESSAGE_INFO_BASE,
CamelMessageInfoBasePrivate);
+}
diff --git a/src/camel/camel-message-info-base.h b/src/camel/camel-message-info-base.h
new file mode 100644
index 0000000..70b8a0e
--- /dev/null
+++ b/src/camel/camel-message-info-base.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_MESSAGE_INFO_BASE_H
+#define CAMEL_MESSAGE_INFO_BASE_H
+
+#include <glib-object.h>
+
+#include <camel/camel-message-info.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_MESSAGE_INFO_BASE \
+ (camel_message_info_base_get_type ())
+#define CAMEL_MESSAGE_INFO_BASE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO_BASE, CamelMessageInfoBase))
+#define CAMEL_MESSAGE_INFO_BASE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_MESSAGE_INFO_BASE, CamelMessageInfoBaseClass))
+#define CAMEL_IS_MESSAGE_INFO_BASE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO_BASE))
+#define CAMEL_IS_MESSAGE_INFO_BASE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_MESSAGE_INFO_BASE))
+#define CAMEL_MESSAGE_INFO_BASE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO_BASE, CamelMessageInfoBaseClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelMessageInfoBase CamelMessageInfoBase;
+typedef struct _CamelMessageInfoBaseClass CamelMessageInfoBaseClass;
+typedef struct _CamelMessageInfoBasePrivate CamelMessageInfoBasePrivate;
+
+struct _CamelMessageInfoBase {
+ CamelMessageInfo parent;
+ CamelMessageInfoBasePrivate *priv;
+};
+
+struct _CamelMessageInfoBaseClass {
+ CamelMessageInfoClass parent_class;
+};
+
+GType camel_message_info_base_get_type (void);
+
+G_END_DECLS
+
+#endif /* CAMEL_MESSAGE_INFO_BASE_H */
diff --git a/src/camel/camel-message-info.c b/src/camel/camel-message-info.c
new file mode 100644
index 0000000..c4d4152
--- /dev/null
+++ b/src/camel/camel-message-info.c
@@ -0,0 +1,2979 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "camel-db.h"
+#include "camel-folder.h"
+#include "camel-folder-summary.h"
+#include "camel-message-info-base.h"
+#include "camel-string-utils.h"
+
+#include "camel-message-info.h"
+
+struct _CamelMessageInfoPrivate {
+ GRecMutex property_lock;
+
+ GWeakRef summary; /* CamelFolderSummary * */
+ gboolean dirty; /* whether requires save to local disk/summary */
+ const gchar *uid; /* allocated in the string pool */
+ gboolean abort_notifications;
+ gboolean thaw_notify_folder;
+ gboolean thaw_notify_folder_with_counts;
+ guint freeze_notifications;
+ guint folder_flagged_stamp;
+};
+
+enum {
+ PROP_0,
+ PROP_SUMMARY,
+ PROP_DIRTY,
+ PROP_FOLDER_FLAGGED,
+ PROP_FOLDER_FLAGGED_STAMP,
+ PROP_ABORT_NOTIFICATIONS,
+ PROP_UID,
+ PROP_FLAGS,
+ PROP_USER_FLAGS,
+ PROP_USER_TAGS,
+ PROP_SUBJECT,
+ PROP_FROM,
+ PROP_TO,
+ PROP_CC,
+ PROP_MLIST,
+ PROP_SIZE,
+ PROP_DATE_SENT,
+ PROP_DATE_RECEIVED,
+ PROP_MESSAGE_ID,
+ PROP_REFERENCES,
+ PROP_HEADERS
+};
+
+G_DEFINE_ABSTRACT_TYPE (CamelMessageInfo, camel_message_info, G_TYPE_OBJECT)
+
+static CamelMessageInfo *
+message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfo *result;
+ const gchar *uid;
+ const GArray *references;
+ const CamelNameValueArray *headers;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+ if (assign_summary)
+ g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (assign_summary), NULL);
+
+ /* Make sure the 'mi' doesn't change while copying the values. */
+ camel_message_info_property_lock (mi);
+
+ if (!assign_summary) {
+ CamelFolderSummary *mi_summary;
+
+ mi_summary = camel_message_info_ref_summary (mi);
+ result = camel_message_info_new (mi_summary);
+ g_clear_object (&mi_summary);
+ } else {
+ result = camel_message_info_new (assign_summary);
+ }
+
+ g_object_freeze_notify (G_OBJECT (result));
+ camel_message_info_set_abort_notifications (result, TRUE);
+
+ uid = camel_message_info_pooldup_uid (mi);
+ camel_message_info_set_uid (result, uid);
+ camel_pstring_free (uid);
+
+ camel_message_info_take_user_flags (result, camel_message_info_dup_user_flags (mi));
+ camel_message_info_take_user_tags (result, camel_message_info_dup_user_tags (mi));
+ camel_message_info_set_subject (result, camel_message_info_get_subject (mi));
+ camel_message_info_set_from (result, camel_message_info_get_from (mi));
+ camel_message_info_set_to (result, camel_message_info_get_to (mi));
+ camel_message_info_set_cc (result, camel_message_info_get_cc (mi));
+ camel_message_info_set_mlist (result, camel_message_info_get_mlist (mi));
+ camel_message_info_set_size (result, camel_message_info_get_size (mi));
+ camel_message_info_set_date_sent (result, camel_message_info_get_date_sent (mi));
+ camel_message_info_set_date_received (result, camel_message_info_get_date_received (mi));
+ camel_message_info_set_message_id (result, camel_message_info_get_message_id (mi));
+
+ references = camel_message_info_get_references (mi);
+ if (references && references->len) {
+ GArray *copy;
+ guint ii;
+
+ copy = g_array_sized_new (FALSE, FALSE, references->len, sizeof (guint64));
+
+ for (ii = 0; ii < references->len; ii++) {
+ g_array_append_val (copy, g_array_index (references, guint64, ii));
+ }
+
+ camel_message_info_take_references (result, copy);
+ }
+
+ headers = camel_message_info_get_headers (mi);
+ if (headers) {
+ camel_message_info_take_headers (result,
+ camel_name_value_array_copy (headers));
+ }
+
+ /* Set flags as the last, to not overwrite 'folder-flagged' flag by
+ the "changes" when copying fields. */
+ camel_message_info_set_flags (result, ~0, camel_message_info_get_flags (mi));
+
+ camel_message_info_property_unlock (mi);
+
+ /* Also ensure 'dirty' flag, thus it can be eventually saved. */
+ camel_message_info_set_dirty (result, TRUE);
+
+ camel_message_info_set_abort_notifications (result, FALSE);
+ g_object_thaw_notify (G_OBJECT (result));
+
+ return result;
+}
+
+static gboolean
+message_info_load (CamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ gint ii, count;
+ gchar *part, *label;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ camel_message_info_set_uid (mi, record->uid);
+ camel_message_info_set_flags (mi, ~0, record->flags);
+ camel_message_info_set_size (mi, record->size);
+ camel_message_info_set_date_sent (mi, record->dsent);
+ camel_message_info_set_date_received (mi, record->dreceived);
+
+ camel_message_info_set_subject (mi, record->subject);
+ camel_message_info_set_from (mi, record->from);
+ camel_message_info_set_to (mi, record->to);
+ camel_message_info_set_cc (mi, record->cc);
+ camel_message_info_set_mlist (mi, record->mlist);
+
+ /* Extract Message id & References */
+ part = record->part;
+ if (part) {
+ CamelSummaryMessageID message_id;
+
+ message_id.id.part.hi = camel_util_bdata_get_number (&part, 0);
+ message_id.id.part.lo = camel_util_bdata_get_number (&part, 0);
+
+ camel_message_info_set_message_id (mi, message_id.id.id);
+
+ count = camel_util_bdata_get_number (&part, 0);
+
+ if (count > 0) {
+ GArray *references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), count);
+
+ for (ii = 0; ii < count; ii++) {
+ message_id.id.part.hi = camel_util_bdata_get_number (&part, 0);
+ message_id.id.part.lo = camel_util_bdata_get_number (&part, 0);
+
+ g_array_append_val (references, message_id.id.id);
+ }
+
+ camel_message_info_take_references (mi, references);
+ }
+ }
+
+ /* Extract User flags/labels */
+ part = record->labels;
+ if (part) {
+ CamelNamedFlags *user_flags;
+
+ user_flags = camel_named_flags_new ();
+
+ label = part;
+ for (ii = 0; part[ii]; ii++) {
+ if (part[ii] == ' ') {
+ part[ii] = 0;
+ if (label && *label)
+ camel_named_flags_insert (user_flags, label);
+ label = &(part[ii + 1]);
+ part[ii] = ' ';
+ }
+ }
+ if (label && *label)
+ camel_named_flags_insert (user_flags, label);
+
+ camel_message_info_take_user_flags (mi, user_flags);
+ }
+
+ /* Extract User tags */
+ part = record->usertags;
+ if (part) {
+ CamelNameValueArray *user_tags;
+
+ count = camel_util_bdata_get_number (&part, 0);
+
+ user_tags = camel_name_value_array_new_sized (count);
+
+ for (ii = 0; ii < count; ii++) {
+ gchar *name, *value;
+
+ name = camel_util_bdata_get_string (&part, NULL);
+ value = camel_util_bdata_get_string (&part, NULL);
+
+ if (name)
+ camel_name_value_array_set_named (user_tags, TRUE, name, value ? value : "");
+
+ g_free (name);
+ g_free (value);
+ }
+
+ camel_message_info_take_user_tags (mi, user_tags);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+message_info_save (const CamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ GString *tmp;
+ CamelSummaryMessageID message_id;
+ const CamelNamedFlags *user_flags;
+ const CamelNameValueArray *user_tags;
+ const GArray *references;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ record->uid = (gchar *) camel_pstring_strdup (camel_message_info_get_uid (mi));
+ record->flags = camel_message_info_get_flags (mi);
+
+ record->read = ((record->flags & (CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_JUNK)))
? 1 : 0;
+ record->deleted = (record->flags & CAMEL_MESSAGE_DELETED) != 0 ? 1 : 0;
+ record->replied = (record->flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 1 : 0;
+ record->important = (record->flags & CAMEL_MESSAGE_FLAGGED) != 0 ? 1 : 0;
+ record->junk = (record->flags & CAMEL_MESSAGE_JUNK) != 0 ? 1 : 0;
+ record->dirty = (record->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 ? 1 : 0;
+ record->attachment = (record->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0 ? 1 : 0;
+
+ record->size = camel_message_info_get_size (mi);
+ record->dsent = camel_message_info_get_date_sent (mi);
+ record->dreceived = camel_message_info_get_date_received (mi);
+
+ record->subject = g_strdup (camel_message_info_get_subject (mi));
+ record->from = g_strdup (camel_message_info_get_from (mi));
+ record->to = g_strdup (camel_message_info_get_to (mi));
+ record->cc = g_strdup (camel_message_info_get_cc (mi));
+ record->mlist = g_strdup (camel_message_info_get_mlist (mi));
+
+ record->followup_flag = g_strdup (camel_message_info_get_user_tag (mi, "follow-up"));
+ record->followup_completed_on = g_strdup (camel_message_info_get_user_tag (mi, "completed-on"));
+ record->followup_due_by = g_strdup (camel_message_info_get_user_tag (mi, "due-by"));
+
+ tmp = g_string_new (NULL);
+ message_id.id.id = camel_message_info_get_message_id (mi);
+ g_string_append_printf (tmp, "%lu %lu ", (gulong) message_id.id.part.hi, (gulong)
message_id.id.part.lo);
+ references = camel_message_info_get_references (mi);
+ if (references) {
+ guint ii;
+
+ g_string_append_printf (tmp, "%lu", (gulong) references->len);
+ for (ii = 0; ii < references->len; ii++) {
+ message_id.id.id = g_array_index (references, guint64, ii);
+
+ g_string_append_printf (tmp, " %lu %lu", (gulong) message_id.id.part.hi, (gulong)
message_id.id.part.lo);
+ }
+ } else {
+ g_string_append (tmp, "0");
+ }
+ record->part = g_string_free (tmp, FALSE);
+
+ tmp = g_string_new (NULL);
+ user_flags = camel_message_info_get_user_flags (mi);
+ if (user_flags) {
+ guint ii, count;
+
+ count = camel_named_flags_get_length (user_flags);
+ for (ii = 0; ii < count; ii++) {
+ const gchar *name = camel_named_flags_get (user_flags, ii);
+
+ if (name && *name) {
+ if (tmp->len)
+ g_string_append (tmp, " ");
+ g_string_append (tmp, name);
+ }
+ }
+ }
+ record->labels = g_string_free (tmp, FALSE);
+
+ tmp = g_string_new (NULL);
+ user_tags = camel_message_info_get_user_tags (mi);
+ if (user_tags) {
+ guint ii, count;
+
+ count = camel_name_value_array_get_length (user_tags);
+ g_string_append_printf (tmp, "%lu", (gulong) count);
+
+ for (ii = 0; ii < count; ii++) {
+ const gchar *name = NULL, *value = NULL;
+
+ if (camel_name_value_array_get (user_tags, ii, &name, &value)) {
+ if (!name)
+ name = "";
+ if (!value)
+ value = "";
+
+ g_string_append_printf (tmp, " %lu-%s %lu-%s", (gulong) strlen (name), name,
(gulong) strlen (value), value);
+ }
+ }
+ } else {
+ g_string_append (tmp, "0");
+ }
+ record->usertags = g_string_free (tmp, FALSE);
+
+ return TRUE;
+}
+
+static void
+message_info_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_SUMMARY:
+ g_weak_ref_set (&mi->priv->summary, g_value_get_object (value));
+ return;
+
+ case PROP_DIRTY:
+ camel_message_info_set_dirty (mi, g_value_get_boolean (value));
+ return;
+
+ case PROP_FOLDER_FLAGGED:
+ camel_message_info_set_folder_flagged (mi, g_value_get_boolean (value));
+ return;
+
+ case PROP_ABORT_NOTIFICATIONS:
+ camel_message_info_set_abort_notifications (mi, g_value_get_boolean (value));
+ return;
+
+ case PROP_UID:
+ camel_message_info_set_uid (mi, g_value_get_string (value));
+ return;
+
+ case PROP_FLAGS:
+ camel_message_info_set_flags (mi, ~0, g_value_get_uint (value));
+ return;
+
+ case PROP_USER_FLAGS:
+ camel_message_info_take_user_flags (mi, g_value_dup_boxed (value));
+ return;
+
+ case PROP_USER_TAGS:
+ camel_message_info_take_user_tags (mi, g_value_dup_boxed (value));
+ return;
+
+ case PROP_SUBJECT:
+ camel_message_info_set_subject (mi, g_value_get_string (value));
+ return;
+
+ case PROP_FROM:
+ camel_message_info_set_from (mi, g_value_get_string (value));
+ return;
+
+ case PROP_TO:
+ camel_message_info_set_to (mi, g_value_get_string (value));
+ return;
+
+ case PROP_CC:
+ camel_message_info_set_cc (mi, g_value_get_string (value));
+ return;
+
+ case PROP_MLIST:
+ camel_message_info_set_mlist (mi, g_value_get_string (value));
+ return;
+
+ case PROP_SIZE:
+ camel_message_info_set_size (mi, g_value_get_uint (value));
+ return;
+
+ case PROP_DATE_SENT:
+ camel_message_info_set_date_sent (mi, g_value_get_int64 (value));
+ return;
+
+ case PROP_DATE_RECEIVED:
+ camel_message_info_set_date_received (mi, g_value_get_int64 (value));
+ return;
+
+ case PROP_MESSAGE_ID:
+ camel_message_info_set_message_id (mi, g_value_get_uint64 (value));
+ return;
+
+ case PROP_REFERENCES:
+ camel_message_info_take_references (mi, g_value_dup_boxed (value));
+ return;
+
+ case PROP_HEADERS:
+ camel_message_info_take_headers (mi, g_value_dup_boxed (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+message_info_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_SUMMARY:
+ g_value_take_object (value, camel_message_info_ref_summary (mi));
+ return;
+
+ case PROP_DIRTY:
+ g_value_set_boolean (value, camel_message_info_get_dirty (mi));
+ return;
+
+ case PROP_FOLDER_FLAGGED:
+ g_value_set_boolean (value, camel_message_info_get_folder_flagged (mi));
+ return;
+
+ case PROP_FOLDER_FLAGGED_STAMP:
+ g_value_set_uint (value, camel_message_info_get_folder_flagged_stamp (mi));
+ return;
+
+ case PROP_ABORT_NOTIFICATIONS:
+ g_value_set_boolean (value, camel_message_info_get_abort_notifications (mi));
+ return;
+
+ case PROP_UID:
+ g_value_set_string (value, camel_message_info_get_uid (mi));
+ return;
+
+ case PROP_FLAGS:
+ g_value_set_uint (value, camel_message_info_get_flags (mi));
+ return;
+
+ case PROP_USER_FLAGS:
+ g_value_take_boxed (value, camel_message_info_dup_user_flags (mi));
+ return;
+
+ case PROP_USER_TAGS:
+ g_value_take_boxed (value, camel_message_info_dup_user_tags (mi));
+ return;
+
+ case PROP_SUBJECT:
+ g_value_set_string (value, camel_message_info_get_subject (mi));
+ return;
+
+ case PROP_FROM:
+ g_value_set_string (value, camel_message_info_get_from (mi));
+ return;
+
+ case PROP_TO:
+ g_value_set_string (value, camel_message_info_get_to (mi));
+ return;
+
+ case PROP_CC:
+ g_value_set_string (value, camel_message_info_get_cc (mi));
+ return;
+
+ case PROP_MLIST:
+ g_value_set_string (value, camel_message_info_get_mlist (mi));
+ return;
+
+ case PROP_SIZE:
+ g_value_set_uint (value, camel_message_info_get_size (mi));
+ return;
+
+ case PROP_DATE_SENT:
+ g_value_set_int64 (value, camel_message_info_get_date_sent (mi));
+ return;
+
+ case PROP_DATE_RECEIVED:
+ g_value_set_int64 (value, camel_message_info_get_date_received (mi));
+ return;
+
+ case PROP_MESSAGE_ID:
+ g_value_set_uint64 (value, camel_message_info_get_message_id (mi));
+ return;
+
+ case PROP_REFERENCES:
+ g_value_take_boxed (value, camel_message_info_dup_references (mi));
+ return;
+
+ case PROP_HEADERS:
+ g_value_take_boxed (value, camel_message_info_dup_headers (mi));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+message_info_dispose (GObject *object)
+{
+ CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
+
+ g_weak_ref_set (&mi->priv->summary, NULL);
+ camel_pstring_free (mi->priv->uid);
+ mi->priv->uid = NULL;
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_message_info_parent_class)->dispose (object);
+}
+
+static void
+message_info_finalize (GObject *object)
+{
+ CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
+
+ g_weak_ref_clear (&mi->priv->summary);
+ g_rec_mutex_clear (&mi->priv->property_lock);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_message_info_parent_class)->finalize (object);
+}
+
+static void
+camel_message_info_class_init (CamelMessageInfoClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelMessageInfoPrivate));
+
+ class->clone = message_info_clone;
+ class->load = message_info_load;
+ class->save = message_info_save;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = message_info_set_property;
+ object_class->get_property = message_info_get_property;
+ object_class->dispose = message_info_dispose;
+ object_class->finalize = message_info_finalize;
+
+ /**
+ * CamelMessageInfo:summary
+ *
+ * The #CamelFolderSummary to which the message info belongs, or %NULL.
+ * It can be set only during construction of the object.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SUMMARY,
+ g_param_spec_object (
+ "summary",
+ "Summary",
+ NULL,
+ CAMEL_TYPE_FOLDER_SUMMARY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * CamelMessageInfo:uid
+ *
+ * A unique ID of the message in its folder.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_UID,
+ g_param_spec_string (
+ "uid",
+ "UID",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:dirty
+ *
+ * Flag, whether the info is changed and requires save to disk.
+ * Compare with CamelMessageInfo:folder-flagged
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DIRTY,
+ g_param_spec_boolean (
+ "dirty",
+ "Dirty",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:folder-flagged
+ *
+ * Flag, whether the info is changed and requires save to
+ * the destination store/server. This is different from
+ * the CamelMessageInfo:dirty, which takes care of the local
+ * information only.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FOLDER_FLAGGED,
+ g_param_spec_boolean (
+ "folder-flagged",
+ "Folder Flagged",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:folder-flagged-stamp
+ *
+ * The 'folder-flagged-stamp' is a stamp of the 'folder-flagged' flag. This stamp
+ * changes whenever anything would mark the @mi 'folder-flagged', regardless the @mi
+ * being already 'folder-flagged'. It can be used to recognize changes
+ * on the 'folder-flagged' flag during the time.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FOLDER_FLAGGED_STAMP,
+ g_param_spec_uint (
+ "folder-flagged-stamp",
+ "Folder Flagged Stamp",
+ NULL,
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE));
+
+ /**
+ * CamelMessageInfo:abort-notifications
+ *
+ * Flag, whether the info is currently aborting notifications. It is used to avoid
+ * unnecessary 'folder-flagged' and 'dirty' flags changes and also to avoid
+ * associated folder's "changed" signal.
+ *f
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_ABORT_NOTIFICATIONS,
+ g_param_spec_boolean (
+ "abort-notifications",
+ "Abort Notifications",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:flags
+ *
+ * Bit-or of #CamelMessageFlags.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FLAGS,
+ g_param_spec_uint (
+ "flags",
+ "Flags",
+ NULL,
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:user-flags
+ *
+ * User flags for the associated message. Can be %NULL.
+ * Unlike user-tags, which can contain various values, the user-flags
+ * can only be set or not.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_USER_FLAGS,
+ g_param_spec_boxed (
+ "user-flags",
+ "User Flags",
+ NULL,
+ CAMEL_TYPE_NAMED_FLAGS,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:user-tags
+ *
+ * User tags for the associated message. Can be %NULL.
+ * Unlike user-flags, which can be set or not, the user-tags
+ * can contain various values.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_USER_TAGS,
+ g_param_spec_boxed (
+ "user-tags",
+ "User tags",
+ NULL,
+ CAMEL_TYPE_NAME_VALUE_ARRAY,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:subject
+ *
+ * Subject of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SUBJECT,
+ g_param_spec_string (
+ "subject",
+ "Subject",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:from
+ *
+ * From address of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FROM,
+ g_param_spec_string (
+ "from",
+ "From",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:to
+ *
+ * To address of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_TO,
+ g_param_spec_string (
+ "to",
+ "To",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:cc
+ *
+ * CC address of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_CC,
+ g_param_spec_string (
+ "cc",
+ "CC",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:mlist
+ *
+ * Mailing list address of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_MLIST,
+ g_param_spec_string (
+ "mlist",
+ "mlist",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:size
+ *
+ * Size of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SIZE,
+ g_param_spec_uint (
+ "size",
+ "Size",
+ NULL,
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:date-sent
+ *
+ * Sent Date of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DATE_SENT,
+ g_param_spec_int64 (
+ "date-sent",
+ "Date Sent",
+ NULL,
+ G_MININT64, G_MAXINT64, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:date-received
+ *
+ * Received date of the associated message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DATE_RECEIVED,
+ g_param_spec_int64 (
+ "date-received",
+ "Date Received",
+ NULL,
+ G_MININT64, G_MAXINT64, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:message-id
+ *
+ * Encoded Message-ID of the associated message as a guint64 number,
+ * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_MESSAGE_ID,
+ g_param_spec_uint64 (
+ "message-id",
+ "Message ID",
+ NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:references
+ *
+ * Encoded In-Reply-To and References headers of the associated message
+ * as an array of guint64 numbers, partial MD5 sums. Each value can be
+ * cast to #CamelSummaryMessageID.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_REFERENCES,
+ g_param_spec_boxed (
+ "references",
+ "References",
+ NULL,
+ G_TYPE_ARRAY,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelMessageInfo:headers
+ *
+ * Headers of the associated message. Can be %NULL.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_HEADERS,
+ g_param_spec_boxed (
+ "headers",
+ "Headers",
+ NULL,
+ CAMEL_TYPE_NAME_VALUE_ARRAY,
+ G_PARAM_READWRITE));
+}
+
+static void
+camel_message_info_init (CamelMessageInfo *mi)
+{
+ mi->priv = G_TYPE_INSTANCE_GET_PRIVATE (mi, CAMEL_TYPE_MESSAGE_INFO, CamelMessageInfoPrivate);
+
+ g_rec_mutex_init (&mi->priv->property_lock);
+ g_weak_ref_init (&mi->priv->summary, NULL);
+}
+
+/**
+ * camel_message_info_new:
+ * @summary: (nullable): parent #CamelFolderSummary object, or %NULL
+ *
+ * Create a new #CamelMessageInfo object, optionally for given @summary.
+ *
+ * Returns: (transfer full): a new #CamelMessageInfo object
+ *
+ * Since: 3.24
+ **/
+CamelMessageInfo *
+camel_message_info_new (CamelFolderSummary *summary)
+{
+ GType type = CAMEL_TYPE_MESSAGE_INFO_BASE;
+
+ if (summary) {
+ CamelFolderSummaryClass *klass;
+
+ g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL);
+
+ klass = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
+ g_return_val_if_fail (klass != NULL, NULL);
+
+ type = klass->message_info_type;
+ }
+
+ return g_object_new (type, "summary", summary, NULL);
+}
+
+/**
+ * camel_message_info_clone:
+ * @mi: a #CamelMessageInfo to clone
+ * @assign_summary: (nullable): parent #CamelFolderSummary object, or %NULL, to set on the clone
+ *
+ * Clones the @mi as a new #CamelMessageInfo and eventually assigns
+ * a new #CamelFolderSummary to it. If it's not set, then the same
+ * summary as the one with @mi is used.
+ *
+ * Returns: (transfer full): a new #CamelMessageInfo object, clone of the @mi
+ *
+ * Since: 3.24
+ **/
+CamelMessageInfo *
+camel_message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfoClass *klass;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+ if (assign_summary)
+ g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (assign_summary), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->clone != NULL, NULL);
+
+ return klass->clone (mi, assign_summary);
+}
+
+/**
+ * camel_message_info_load:
+ * @mi: a #CamelMessageInfo to load
+ * @record: a #CamelMIRecord to load the @mi from
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ *
+ * Load content of @mi from the data stored in @record. The @bdata_ptr points
+ * to the current position of the record->bdata, where the read can continue.
+ * Use helper functions camel_util_bdata_get_number() and camel_util_bdata_get_string()
+ * to read data from it and also move forward the *bdata_ptr.
+ *
+ * After successful load of the @mi, the 'dirty' flag is unset.
+ *
+ * Returns: Whether the load was successful.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_load (CamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ CamelMessageInfoClass *klass;
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->load != NULL, FALSE);
+
+ g_object_freeze_notify (G_OBJECT (mi));
+ camel_message_info_property_lock (mi);
+ camel_message_info_set_abort_notifications (mi, TRUE);
+
+ success = klass->load (mi, record, bdata_ptr);
+
+ if (success)
+ camel_message_info_set_dirty (mi, FALSE);
+
+ camel_message_info_set_abort_notifications (mi, FALSE);
+ camel_message_info_property_unlock (mi);
+ g_object_thaw_notify (G_OBJECT (mi));
+
+ return success;
+}
+
+/**
+ * camel_message_info_save:
+ * @mi: a #CamelMessageInfo
+ * @record: a #CamelMIRecord to populate
+ * @bdata_str: a #GString with a string to save as backend specific data (bdata)
+ *
+ * Save the @mi content to the message info record @record. It can populate all
+ * but the record->bdata value, which is set fro mthe @bdata_str. Use helper functions
+ * camel_util_bdata_put_number() and camel_util_bdata_put_string() to put data into the @bdata_str.
+ *
+ * Returns: Whether the save succeeded.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_save (const CamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ CamelMessageInfoClass *klass;
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->save != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+
+ success = klass->save (mi, record, bdata_str);
+
+ camel_message_info_property_unlock (mi);
+
+ return success;
+}
+
+/**
+ * camel_message_info_ref_summary:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer full): Referenced #CamelFolderSummary to which the @mi belongs, or %NULL,
+ * if there is none. Use g_object_unref() for non-NULL returned values when done with it.
+ *
+ * Since: 3.24
+ **/
+CamelFolderSummary *
+camel_message_info_ref_summary (const CamelMessageInfo *mi)
+{
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ return g_weak_ref_get (&mi->priv->summary);
+}
+
+/**
+ * camel_message_info_property_lock:
+ * @mi: a #CamelMessageInfo
+ *
+ * Acquires a property lock, which is used to ensure thread safety
+ * when properties are changing. Release the lock with
+ * camel_message_info_property_unlock().
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_property_lock (const CamelMessageInfo *mi)
+{
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ g_rec_mutex_lock (&mi->priv->property_lock);
+}
+
+/**
+ * camel_message_info_property_unlock:
+ * @mi: a #CamelMessageInfo
+ *
+ * Releases a property lock, previously acquired with
+ * camel_message_info_property_lock().
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_property_unlock (const CamelMessageInfo *mi)
+{
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ g_rec_mutex_unlock (&mi->priv->property_lock);
+}
+
+static void
+camel_message_info_update_summary_and_folder (CamelMessageInfo *mi,
+ gboolean update_counts)
+{
+ CamelFolderSummary *summary;
+
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ camel_message_info_property_lock (mi);
+ if (camel_message_info_get_notifications_frozen (mi)) {
+ mi->priv->thaw_notify_folder = TRUE;
+ mi->priv->thaw_notify_folder_with_counts |= update_counts;
+ camel_message_info_property_unlock (mi);
+
+ return;
+ }
+ camel_message_info_property_unlock (mi);
+
+ summary = camel_message_info_ref_summary (mi);
+ if (summary) {
+ CamelFolder *folder;
+ const gchar *uid;
+
+ uid = camel_message_info_pooldup_uid (mi);
+
+ /* This is for cases when a new message info had been created,
+ but not added into the summary yet. */
+ if (uid && camel_folder_summary_check_uid (summary, uid) &&
+ camel_folder_summary_peek_loaded (summary, uid) == mi) {
+ if (update_counts) {
+ camel_folder_summary_lock (summary);
+ g_object_freeze_notify (G_OBJECT (summary));
+
+ camel_folder_summary_replace_flags (summary, mi);
+
+ g_object_thaw_notify (G_OBJECT (summary));
+ camel_folder_summary_unlock (summary);
+ }
+
+ folder = camel_folder_summary_get_folder (summary);
+ if (folder) {
+ CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
+
+ camel_folder_change_info_change_uid (changes, uid);
+ camel_folder_changed (folder, changes);
+ camel_folder_change_info_free (changes);
+ }
+ }
+
+ g_clear_object (&summary);
+ camel_pstring_free (uid);
+ }
+}
+
+/**
+ * camel_message_info_get_dirty:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Whether the @mi is dirty, which means that it had been
+ * changed and a save to the local summary is required.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_get_dirty (const CamelMessageInfo *mi)
+{
+ gboolean result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ camel_message_info_property_lock (mi);
+ result = mi->priv->dirty;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_dirty:
+ * @mi: a #CamelMessageInfo
+ * @dirty: a dirty state to set
+ *
+ * Marks the @mi as dirty, which means a save to the local summary
+ * is required. In case the @dirty is %TRUE and the @mi is not aborting notifications,
+ * the 'dirty-stamp' changes too.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_set_dirty (const CamelMessageInfo *mi,
+ gboolean dirty)
+{
+ gboolean changed, abort_notifications;
+
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ camel_message_info_property_lock (mi);
+
+ changed = (!mi->priv->dirty) != (!dirty);
+ if (changed)
+ mi->priv->dirty = dirty;
+ abort_notifications = mi->priv->abort_notifications;
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "dirty");
+
+ if (dirty) {
+ CamelFolderSummary *summary;
+
+ summary = camel_message_info_ref_summary (mi);
+ if (summary)
+ camel_folder_summary_touch (summary);
+
+ g_clear_object (&summary);
+ }
+ }
+}
+
+/**
+ * camel_message_info_get_folder_flagged:
+ * @mi: a #CamelMessageInfo
+ *
+ * The folder flagged flag is used to mark the message infor as being changed
+ * and this change should be propagated to the remote store (server). This is
+ * different from the 'dirty' flag, which is set for local changes only. It
+ * can happen that the 'folder-flagged' flag is set, but the 'dirty' flag not.
+ *
+ * This is only a convenient wrapper around CAMEL_MESSAGE_FOLDER_FLAGGED flag,
+ * for better readiness of the code.
+ *
+ * Returns: Whether requires save of the local changes into the remote store.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_get_folder_flagged (const CamelMessageInfo *mi)
+{
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ return (camel_message_info_get_flags (mi) & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
+}
+
+/**
+ * camel_message_info_set_folder_flagged:
+ * @mi: a #CamelMessageInfo
+ * folder_flagged: a value to set to
+ *
+ * Changes the folder-flagged flag to the @folder_flagged value. See
+ * camel_message_info_get_folder_flagged() for more information about
+ * the use of this flag.
+ *
+ * This is only a convenient wrapper around CAMEL_MESSAGE_FOLDER_FLAGGED flag,
+ * for better readiness of the code.
+ *
+ * Returns: Whether the flag had been changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_folder_flagged (CamelMessageInfo *mi,
+ gboolean folder_flagged)
+{
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ /* g_object_notify (G_OBJECT (mi), "folder-flagged");
+ is called as part of the set_flags function */
+
+ return camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_FLAGGED,
+ folder_flagged ? CAMEL_MESSAGE_FOLDER_FLAGGED : 0);
+}
+
+/**
+ * camel_message_info_get_folder_flagged_stamp:
+ * @mi: a #CamelMessageInfo
+ *
+ * The 'folder-flagged-stamp' is a stamp of the 'folder-flagged' flag. This stamp
+ * changes whenever anything would mark the @mi as 'folder-flagged', regardless
+ * the @mi being already 'folder-flagged'. It can be used to recognize changes
+ * on the 'folder-flagged' flag during the time.
+ *
+ * Returns: Stamp of the 'folder-flagged' flag.
+ *
+ * Since: 3.24
+ **/
+guint
+camel_message_info_get_folder_flagged_stamp (const CamelMessageInfo *mi)
+{
+ guint result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), ~0);
+
+ camel_message_info_property_lock (mi);
+ result = mi->priv->folder_flagged_stamp;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_get_abort_notifications:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Whether the @mi is aborting notifications, which means
+ * that it will not influence 'dirty' and 'folder-flagged' flags
+ * in the set/take functions, neither it will emit any GObject::notify
+ * signals on change, nor associated folder's "changed" signal.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_get_abort_notifications (const CamelMessageInfo *mi)
+{
+ gboolean result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ camel_message_info_property_lock (mi);
+ result = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_abort_notifications:
+ * @mi: a #CamelMessageInfo
+ * @abort_notifications: a state to set
+ *
+ * Marks the @mi to abort any notifications, which means that it
+ * will not influence 'dirty' and 'folder-flagged' flags in
+ * the set/take functions, neither it will emit any GObject::notify
+ * signals on change, nor associated folder's "changed" signal.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_set_abort_notifications (CamelMessageInfo *mi,
+ gboolean abort_notifications)
+{
+ gboolean changed;
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ camel_message_info_property_lock (mi);
+ changed = (!mi->priv->abort_notifications) != (!abort_notifications);
+ if (changed)
+ mi->priv->abort_notifications = abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed)
+ g_object_notify (G_OBJECT (mi), "abort-notifications");
+}
+
+/**
+ * camel_message_info_freeze_notifications:
+ * @mi: a #CamelMessageInfo
+ *
+ * Freezes all the notifications until the camel_message_info_thaw_notifications() is called.
+ * This function can be called multiple times, where the last thaw will do the notifications.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_freeze_notifications (CamelMessageInfo *mi)
+{
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ camel_message_info_property_lock (mi);
+ mi->priv->freeze_notifications++;
+ if (mi->priv->freeze_notifications == 1) {
+ mi->priv->thaw_notify_folder = FALSE;
+ mi->priv->thaw_notify_folder_with_counts = FALSE;
+ g_object_freeze_notify (G_OBJECT (mi));
+ }
+ camel_message_info_property_unlock (mi);
+}
+
+/**
+ * camel_message_info_thaw_notifications:
+ * @mi: a #CamelMessageInfo
+ *
+ * Reverses the call of the camel_message_info_freeze_notifications().
+ * If this is the last freeze, then the associated folder is also notified
+ * about the change, if any happened during the freeze.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_thaw_notifications (CamelMessageInfo *mi)
+{
+ g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
+
+ camel_message_info_property_lock (mi);
+ if (!mi->priv->freeze_notifications) {
+ camel_message_info_property_unlock (mi);
+
+ g_warn_if_reached ();
+ return;
+ }
+
+ mi->priv->freeze_notifications--;
+ if (!mi->priv->freeze_notifications) {
+ gboolean notify_folder, notify_folder_with_counts;
+
+ notify_folder = mi->priv->thaw_notify_folder;
+ notify_folder_with_counts = mi->priv->thaw_notify_folder_with_counts;
+
+ camel_message_info_property_unlock (mi);
+
+ g_object_thaw_notify (G_OBJECT (mi));
+
+ if (notify_folder)
+ camel_message_info_update_summary_and_folder (mi, notify_folder_with_counts);
+ } else {
+ camel_message_info_property_unlock (mi);
+ }
+}
+
+/**
+ * camel_message_info_get_notifications_frozen:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Whether the notifications are frozen.
+ *
+ * See: camel_message_info_freeze_notifications()
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_get_notifications_frozen (const CamelMessageInfo *mi)
+{
+ gboolean result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ camel_message_info_property_lock (mi);
+ result = mi->priv->freeze_notifications > 0;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_get_uid:
+ * @mi: a #CamelMessageInfo
+ *
+ * Get the UID of the #mi.
+ *
+ * Returns: (transfer none): The UID of the @mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_uid (const CamelMessageInfo *mi)
+{
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ camel_message_info_property_lock (mi);
+ result = mi->priv->uid;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_pooldup_uid:
+ * @mi: a #CamelMessageInfo
+ *
+ * Get the UID of the #mi, duplicated on the Camel's string pool.
+ * This is good for thread safety, though the UID should not change once set.
+ *
+ * Returns: A newly references string in the string pool, the #mi UID.
+ * Free it with camel_pstring_free() when no longer needed.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_pooldup_uid (const CamelMessageInfo *mi)
+{
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ camel_message_info_property_lock (mi);
+ result = camel_pstring_strdup (mi->priv->uid);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_uid:
+ * @mi: a #CamelMessageInfo
+ * @uid: a UID to set
+ *
+ * Changes UID of the @mi to @uid. If it changes, the 'dirty' flag
+ * of the @mi is set too, unless the @mi is aborting notifications. This change
+ * does not influence the 'folder-flagged' flag.
+ *
+ * Returns: Whether the UID changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_uid (CamelMessageInfo *mi,
+ const gchar *uid)
+{
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = mi->priv->uid != uid && g_strcmp0 (mi->priv->uid, uid) != 0;
+ if (changed) {
+ camel_pstring_free (mi->priv->uid);
+ mi->priv->uid = camel_pstring_strdup (uid);
+ }
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "uid");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_flags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Bit-or of #CamelMessageFlags set on the @mi.
+ *
+ * Since: 3.24
+ **/
+guint32
+camel_message_info_get_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ guint32 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, 0);
+ g_return_val_if_fail (klass->get_flags != NULL, 0);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_flags (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_flags:
+ * @mi: a #CamelMessageInfo
+ * @mask: mask of flags to change
+ * @set: state the flags should be changed to
+ *
+ * Change the state of the flags on the @mi. Both @mask and @set are bit-or
+ * of #CamelMessageFlags.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary. In case
+ * the CAMEL_MESSAGE_FOLDER_FLAGGED flag would be set and the @mi is
+ * not aborting notifications, the 'folder-flagged-stamp' changes too.
+ *
+ * Returns: Whether the flags changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_flags (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_flags != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+
+ changed = klass->set_flags (mi, mask, set);
+ abort_notifications = mi->priv->abort_notifications;
+
+ if (!abort_notifications &&
+ (mask & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 &&
+ (set & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0)
+ mi->priv->folder_flagged_stamp++;
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "flags");
+ camel_message_info_set_dirty (mi, TRUE);
+
+ /* Only if the folder-flagged was not part of the change */
+ if (!(mask & CAMEL_MESSAGE_FOLDER_FLAGGED))
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ else
+ g_object_notify (G_OBJECT (mi), "folder-flagged");
+
+ camel_message_info_update_summary_and_folder (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_user_flag:
+ * @mi: a #CamelMessageInfo
+ * @name: user flag name
+ *
+ * Returns: Whther the user flag named @name is set.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_get_user_flag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ CamelMessageInfoClass *klass;
+ gboolean result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->get_user_flag != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_user_flag (mi, name);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_user_flag:
+ * @mi: a #CamelMessageInfo
+ * @name: user flag name
+ * @state: state to set for the flag
+ *
+ * Change @state of the flag named @name. Unlike user tags, user flags
+ * can only be set or unset, while the user tags can contain certain values.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
+ *
+ * Returns: Whether the message info changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_user_flag (CamelMessageInfo *mi,
+ const gchar *name,
+ gboolean state)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_user_flag != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_user_flag (mi, name, state);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "user-flags");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+
+ camel_message_info_update_summary_and_folder (mi, FALSE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_user_flags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none) (nullable): A #CamelNamedFlags with all the currently set
+ * user flags on the @mi. Do not modify it.
+ *
+ * Since: 3.24
+ **/
+const CamelNamedFlags *
+camel_message_info_get_user_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_user_flags != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_user_flags (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_dup_user_flags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer full): A newly allocated #CamelNamedFlags with all the currently set
+ * user flags on the @mi. Free the returned structure with camel_named_flags_free()
+ * when no londer needed.
+ *
+ * Since: 3.24
+ **/
+CamelNamedFlags *
+camel_message_info_dup_user_flags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->dup_user_flags != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->dup_user_flags (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_take_user_flags:
+ * @mi: a #CamelMessageInfo
+ * @user_flags: (transfer full) (nullable): user flags to set
+ *
+ * Takes all the @user_flags, which replaces any current user flags on the @mi.
+ * The passed-in @user_flags is consumed by the @mi, which becomes an owner
+ * of it. The caller should not change @user_flags afterwards.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
+ *
+ * Note that it's not safe to use the @user_flags after the call to this function,
+ * because it can be freed due to no change.
+ *
+ * Returns: Whether the message info changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_take_user_flags (CamelMessageInfo *mi,
+ CamelNamedFlags *user_flags)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->take_user_flags != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->take_user_flags (mi, user_flags);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "user-flags");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+
+ camel_message_info_update_summary_and_folder (mi, FALSE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_user_tag:
+ * @mi: a #CamelMessageInfo
+ * @name: user tag name
+ *
+ * Returns: (transfer none) (nullable): Value of the user tag, or %NULL when
+ * it is not set.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_user_tag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_user_tag != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_user_tag (mi, name);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_dup_user_tag:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer full) (nullable): Value of the user tag as newly allocated
+ * string, or %NULL when it is not set. Free it with g_free() when no longer needed.
+ *
+ * Since: 3.24
+ **/
+gchar *
+camel_message_info_dup_user_tag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = g_strdup (camel_message_info_get_user_tag (mi, name));
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_user_tag:
+ * @mi: a #CamelMessageInfo
+ * @name: user tag name
+ * @value: (nullable): user tag value, or %NULL to remove the user tag
+ *
+ * Set user tag @name to @value, or remove it, if @value is %NULL.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
+ *
+ * Returns: Whether the @mi changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_user_tag (CamelMessageInfo *mi,
+ const gchar *name,
+ const gchar *value)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_user_tag != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_user_tag (mi, name, value);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "user-tags");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+
+ camel_message_info_update_summary_and_folder (mi, FALSE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_user_tags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none) (nullable): a #CamelNameValueArray containing all set
+ * user tags of the @mi. Do not modify it.
+ *
+ * Since: 3.24
+ **/
+const CamelNameValueArray *
+camel_message_info_get_user_tags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_user_tags != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_user_tags (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_dup_user_tags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer full) (nullable): a newly allocated #CamelNameValueArray containing all set
+ * user tags of the @mi. Free it with camel_name_value_array_free() when no longer needed.
+ *
+ * Since: 3.24
+ **/
+CamelNameValueArray *
+camel_message_info_dup_user_tags (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->dup_user_tags != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->dup_user_tags (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_take_user_tags:
+ * @mi: a #CamelMessageInfo
+ * @user_tags: (transfer full) (nullable): user tags to set
+ *
+ * Takes all the @user_tags, which replaces any current user tags on the @mi.
+ * The passed-in @user_tags is consumed by the @mi, which becomes an owner
+ * of it. The caller should not change @user_tags afterwards.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
+ *
+ * Note that it's not safe to use the @user_tags after the call to this function,
+ * because it can be freed due to no change.
+ *
+ * Returns: Whether the @mi changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_take_user_tags (CamelMessageInfo *mi,
+ CamelNameValueArray *user_tags)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->take_user_tags != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->take_user_tags (mi, user_tags);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "user-tags");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+
+ camel_message_info_update_summary_and_folder (mi, FALSE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_subject:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none): Subject of the #mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_subject (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_subject != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_subject (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_subject:
+ * @mi: a #CamelMessageInfo
+ * @subject: (nullable): a Subject to set
+ *
+ * Sets Subject from the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_subject (CamelMessageInfo *mi,
+ const gchar *subject)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_subject != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_subject (mi, subject);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "subject");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_from:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none): From address of the @mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_from (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_from != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_from (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_from:
+ * @mi: a #CamelMessageInfo
+ * @from: (nullable): a From to set
+ *
+ * Sets From from the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_from (CamelMessageInfo *mi,
+ const gchar *from)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_from != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_from (mi, from);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "from");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_to:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none): To address of the @mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_to (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_to != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_to (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_to:
+ * @mi: a #CamelMessageInfo
+ * @to: (nullable): a To to set
+ *
+ * Sets To from the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_to (CamelMessageInfo *mi,
+ const gchar *to)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_to != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_to (mi, to);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "to");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_cc:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none): CC address of the @mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_cc (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_cc != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_cc (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_cc:
+ * @mi: a #CamelMessageInfo
+ * @cc: (nullable): a CC to set
+ *
+ * Sets CC from the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_cc (CamelMessageInfo *mi,
+ const gchar *cc)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_cc != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_cc (mi, cc);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "cc");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_mlist:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none): Mailing list address of the @mi.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_message_info_get_mlist (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_mlist != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_mlist (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_mlist:
+ * @mi: a #CamelMessageInfo
+ * @mlist: (nullable): a message list address to set
+ *
+ * Sets mesage list address from the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_mlist (CamelMessageInfo *mi,
+ const gchar *mlist)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_mlist != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_mlist (mi, mlist);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "mlist");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_size:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Size of the associated message.
+ *
+ * Since: 3.24
+ **/
+guint32
+camel_message_info_get_size (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ guint32 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, 0);
+ g_return_val_if_fail (klass->get_size != NULL, 0);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_size (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_size:
+ * @mi: a #CamelMessageInfo
+ * @size: a size to set
+ *
+ * Sets size of the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_size (CamelMessageInfo *mi,
+ guint32 size)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_size != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_size (mi, size);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "size");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_date_sent:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: time_t of the Date header of the message, encoded as gint64.
+ *
+ * Since: 3.24
+ **/
+gint64
+camel_message_info_get_date_sent (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ gint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, 0);
+ g_return_val_if_fail (klass->get_date_sent != NULL, 0);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_date_sent (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_date_sent:
+ * @mi: a #CamelMessageInfo
+ * @date_sent: a sent date to set
+ *
+ * Sets sent date (the Date header) of the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_date_sent (CamelMessageInfo *mi,
+ gint64 date_sent)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_date_sent != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_date_sent (mi, date_sent);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "date-sent");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_date_received:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: time_t of the Received header of the message, encoded as gint64.
+ *
+ * Since: 3.24
+ **/
+gint64
+camel_message_info_get_date_received (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ gint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, 0);
+ g_return_val_if_fail (klass->get_date_received != NULL, 0);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_date_received (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_date_received:
+ * @mi: a #CamelMessageInfo
+ * @date_received: a received date to set
+ *
+ * Sets received date (the Received header) of the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_date_received (CamelMessageInfo *mi,
+ gint64 date_received)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_date_received != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_date_received (mi, date_received);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "date-received");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_message_id:
+ * @mi: a #CamelMessageInfo
+ *
+ * Encoded Message-ID of the associated message as a guint64 number,
+ * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
+ *
+ * Returns: Partial MD5 hash of the Message-ID header of the associated message.
+ *
+ * Since: 3.24
+ **/
+guint64
+camel_message_info_get_message_id (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ guint64 result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, 0);
+ g_return_val_if_fail (klass->get_message_id != NULL, 0);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_message_id (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_set_message_id:
+ * @mi: a #CamelMessageInfo
+ * @message_id: a message id to set
+ *
+ * Sets encoded Message-ID of the associated message as a guint64 number,
+ * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_set_message_id (CamelMessageInfo *mi,
+ guint64 message_id)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_message_id != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->set_message_id (mi, message_id);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "message-id");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_references:
+ * @mi: a #CamelMessageInfo
+ *
+ * Gets encoded In-Reply-To and References headers of the associated
+ * message as an array of guint64 numbers, partial MD5 sums. Each value
+ * can be cast to #CamelSummaryMessageID.
+ *
+ * Returns: (transfer none) (nullable): A #GArray of guint64 encoded
+ * Message-ID-s; or %NULL when none are available.
+ *
+ * Since: 3.24
+ **/
+const GArray *
+camel_message_info_get_references (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const GArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_references != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_references (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_dup_references:
+ * @mi: a #CamelMessageInfo
+ *
+ * Duplicates encoded In-Reply-To and References headers of the associated
+ * message as an array of guint64 numbers, partial MD5 sums. Each value
+ * can be cast to #CamelSummaryMessageID.
+ *
+ * Returns: (transfer full) (nullable): A #GArray of guint64 encoded
+ * Message-ID-s; or %NULL when none are available. Free returned array
+ * with g_array_unref() when no longer needed.
+ *
+ * Since: 3.24
+ **/
+GArray *
+camel_message_info_dup_references (const CamelMessageInfo *mi)
+{
+ const GArray *arr;
+ GArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ camel_message_info_property_lock (mi);
+ arr = camel_message_info_get_references (mi);
+ if (arr) {
+ guint ii;
+
+ result = g_array_sized_new (FALSE, FALSE, sizeof (guint64), arr->len);
+ for (ii = 0; ii < arr->len; ii++) {
+ g_array_append_val (result, g_array_index (arr, guint64, ii));
+ }
+ } else {
+ result = NULL;
+ }
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_take_references:
+ * @mi: a #CamelMessageInfo
+ * @references: (transfer full) (nullable): a references to set
+ *
+ * Takes encoded In-Reply-To and References headers of the associated message
+ * as an array of guint64 numbers, partial MD5 sums. Each value can be
+ * cast to #CamelSummaryMessageID.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Note that it's not safe to use the @references after the call to this function,
+ * because it can be freed due to no change.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_take_references (CamelMessageInfo *mi,
+ GArray *references)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->take_references != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->take_references (mi, references);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "references");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_get_headers:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none) (nullable): All the message headers of the associated
+ * message, or %NULL, when none are available.
+ *
+ * Since: 3.24
+ **/
+const CamelNameValueArray *
+camel_message_info_get_headers (const CamelMessageInfo *mi)
+{
+ CamelMessageInfoClass *klass;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_headers != NULL, NULL);
+
+ camel_message_info_property_lock (mi);
+ result = klass->get_headers (mi);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_dup_headers:
+ * @mi: a #CamelMessageInfo
+ *
+ * Duplicates array of headers for the @mi.
+ *
+ * Returns: (transfer full) (nullable): All the message headers of the associated
+ * message, or %NULL, when none are available. Free returned array with
+ * camel_name_value_array_free() when no longer needed.
+ *
+ * Since: 3.24
+ **/
+CamelNameValueArray *
+camel_message_info_dup_headers (const CamelMessageInfo *mi)
+{
+ const CamelNameValueArray *arr;
+ CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ camel_message_info_property_lock (mi);
+ arr = camel_message_info_get_headers (mi);
+ if (arr) {
+ result = camel_name_value_array_copy (arr);
+ } else {
+ result = NULL;
+ }
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * camel_message_info_take_headers:
+ * @mi: a #CamelMessageInfo
+ * @headers: (transfer full) (nullable): headers to set, as #CamelNameValueArray, or %NULL
+ *
+ * Takes headers of the associated message.
+ *
+ * This property is considered static, in a meaning that it should
+ * not change during the life-time of the @mi, the same as it doesn't
+ * change in the associated message.
+ *
+ * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
+ * set automatically, unless the @mi is aborting notifications. There is not emitted
+ * folder's "changed" signal for this @mi.
+ *
+ * Note that it's not safe to use the @headers after the call to this function,
+ * because it can be freed due to no change.
+ *
+ * Returns: Whether the value changed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_take_headers (CamelMessageInfo *mi,
+ CamelNameValueArray *headers)
+{
+ CamelMessageInfoClass *klass;
+ gboolean changed, abort_notifications;
+
+ g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->take_headers != NULL, FALSE);
+
+ camel_message_info_property_lock (mi);
+ changed = klass->take_headers (mi, headers);
+ abort_notifications = mi->priv->abort_notifications;
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !abort_notifications) {
+ g_object_notify (G_OBJECT (mi), "headers");
+ camel_message_info_set_dirty (mi, TRUE);
+ camel_message_info_set_folder_flagged (mi, TRUE);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_message_info_dump:
+ * @mi: a #CamelMessageInfo
+ *
+ * Dumps the mesasge info @mi to stdout. This is meand for debugging
+ * purposes only.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_dump (CamelMessageInfo *mi)
+{
+ if (!mi) {
+ printf ("No message info\n");
+ return;
+ }
+
+ camel_message_info_property_lock (mi);
+
+ printf ("Message info %s:\n", G_OBJECT_TYPE_NAME (mi));
+ printf (" UID: %s\n", camel_message_info_get_uid (mi));
+ printf (" Flags: %04x\n", camel_message_info_get_flags (mi));
+ printf (" From: %s\n", camel_message_info_get_from (mi));
+ printf (" To: %s\n", camel_message_info_get_to (mi));
+ printf (" Cc: %s\n", camel_message_info_get_cc (mi));
+ printf (" Mailing list: %s\n", camel_message_info_get_mlist (mi));
+ printf (" Subject: %s\n", camel_message_info_get_subject (mi));
+
+ camel_message_info_property_unlock (mi);
+}
diff --git a/src/camel/camel-message-info.h b/src/camel/camel-message-info.h
new file mode 100644
index 0000000..7b355cb
--- /dev/null
+++ b/src/camel/camel-message-info.h
@@ -0,0 +1,328 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_MESSAGE_INFO_H
+#define CAMEL_MESSAGE_INFO_H
+
+#include <glib-object.h>
+
+#include <camel/camel-named-flags.h>
+#include <camel/camel-name-value-array.h>
+#include <camel/camel-utils.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_MESSAGE_INFO \
+ (camel_message_info_get_type ())
+#define CAMEL_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO, CamelMessageInfo))
+#define CAMEL_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_MESSAGE_INFO, CamelMessageInfoClass))
+#define CAMEL_IS_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO))
+#define CAMEL_IS_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_MESSAGE_INFO))
+#define CAMEL_MESSAGE_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_MESSAGE_INFO, CamelMessageInfoClass))
+
+G_BEGIN_DECLS
+
+/* Forward declarations */
+struct _CamelFolderSummary;
+struct _CamelMIRecord;
+
+/* A summary messageid is a 64 bit identifier (partial md5 hash) */
+typedef struct _CamelSummaryMessageID {
+ union {
+ guint64 id;
+ guchar hash[8];
+ struct {
+ guint32 hi;
+ guint32 lo;
+ } part;
+ } id;
+} CamelSummaryMessageID;
+
+/* system flag bits */
+typedef enum _CamelMessageFlags {
+ CAMEL_MESSAGE_ANSWERED = 1 << 0,
+ CAMEL_MESSAGE_DELETED = 1 << 1,
+ CAMEL_MESSAGE_DRAFT = 1 << 2,
+ CAMEL_MESSAGE_FLAGGED = 1 << 3,
+ CAMEL_MESSAGE_SEEN = 1 << 4,
+
+ /* these aren't really system flag bits, but are convenience flags */
+ CAMEL_MESSAGE_ATTACHMENTS = 1 << 5,
+ CAMEL_MESSAGE_ANSWERED_ALL = 1 << 6,
+ CAMEL_MESSAGE_JUNK = 1 << 7,
+ CAMEL_MESSAGE_SECURE = 1 << 8,
+ CAMEL_MESSAGE_NOTJUNK = 1 << 9,
+ CAMEL_MESSAGE_FORWARDED = 1 << 10,
+
+ /* following flags are for the folder, and are not really permanent flags */
+ CAMEL_MESSAGE_FOLDER_FLAGGED = 1 << 16, /* for use by the folder implementation */
+ /* flags after 1 << 16 are used by camel providers,
+ * if adding non permanent flags, add them to the end */
+
+ CAMEL_MESSAGE_JUNK_LEARN = 1 << 30, /* used when setting CAMEL_MESSAGE_JUNK flag
+ * to say that we request junk plugin
+ * to learn that message as junk/non junk */
+ CAMEL_MESSAGE_USER = 1 << 31 /* supports user flags */
+} CamelMessageFlags;
+
+/* Changes to system flags will NOT trigger a folder changed event */
+#define CAMEL_MESSAGE_SYSTEM_MASK (0xffff << 16)
+
+typedef struct _CamelMessageInfo CamelMessageInfo;
+typedef struct _CamelMessageInfoClass CamelMessageInfoClass;
+typedef struct _CamelMessageInfoPrivate CamelMessageInfoPrivate;
+
+struct _CamelMessageInfo {
+ GObject parent;
+ CamelMessageInfoPrivate *priv;
+};
+
+struct _CamelMessageInfoClass {
+ GObjectClass parent_class;
+
+ CamelMessageInfo * (* clone) (const CamelMessageInfo *mi,
+ struct _CamelFolderSummary *assign_summary);
+ gboolean (* load) (CamelMessageInfo *mi,
+ const struct _CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr);
+ gboolean (* save) (const CamelMessageInfo *mi,
+ struct _CamelMIRecord *record,
+ GString *bdata_str);
+ guint32 (* get_flags) (const CamelMessageInfo *mi);
+ gboolean (* set_flags) (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set);
+ gboolean (* get_user_flag)
+ (const CamelMessageInfo *mi,
+ const gchar *name);
+ gboolean (* set_user_flag)
+ (CamelMessageInfo *mi,
+ const gchar *name,
+ gboolean state);
+ const CamelNamedFlags * (* get_user_flags)
+ (const CamelMessageInfo *mi);
+ CamelNamedFlags * (* dup_user_flags)
+ (const CamelMessageInfo *mi);
+ gboolean (* take_user_flags)
+ (CamelMessageInfo *mi,
+ CamelNamedFlags *user_flags);
+ const gchar * (* get_user_tag)(const CamelMessageInfo *mi,
+ const gchar *name);
+ gboolean (* set_user_tag)(CamelMessageInfo *mi,
+ const gchar *name,
+ const gchar *value);
+ const CamelNameValueArray *
+ (* get_user_tags)
+ (const CamelMessageInfo *mi);
+ CamelNameValueArray * (* dup_user_tags)
+ (const CamelMessageInfo *mi);
+ gboolean (* take_user_tags)
+ (CamelMessageInfo *mi,
+ CamelNameValueArray *user_tags);
+ const gchar * (* get_subject) (const CamelMessageInfo *mi);
+ gboolean (* set_subject) (CamelMessageInfo *mi,
+ const gchar *subject);
+ const gchar * (* get_from) (const CamelMessageInfo *mi);
+ gboolean (* set_from) (CamelMessageInfo *mi,
+ const gchar *from);
+ const gchar * (* get_to) (const CamelMessageInfo *mi);
+ gboolean (* set_to) (CamelMessageInfo *mi,
+ const gchar *to);
+ const gchar * (* get_cc) (const CamelMessageInfo *mi);
+ gboolean (* set_cc) (CamelMessageInfo *mi,
+ const gchar *cc);
+ const gchar * (* get_mlist) (const CamelMessageInfo *mi);
+ gboolean (* set_mlist) (CamelMessageInfo *mi,
+ const gchar *mlist);
+ guint32 (* get_size) (const CamelMessageInfo *mi);
+ gboolean (* set_size) (CamelMessageInfo *mi,
+ guint32 size);
+ gint64 (* get_date_sent)
+ (const CamelMessageInfo *mi);
+ gboolean (* set_date_sent)
+ (CamelMessageInfo *mi,
+ gint64 date_sent);
+ gint64 (* get_date_received)
+ (const CamelMessageInfo *mi);
+ gboolean (* set_date_received)
+ (CamelMessageInfo *mi,
+ gint64 date_received);
+ guint64 (* get_message_id)
+ (const CamelMessageInfo *mi);
+ gboolean (* set_message_id)
+ (CamelMessageInfo *mi,
+ guint64 message_id);
+ const GArray * (* get_references)
+ (const CamelMessageInfo *mi);
+ gboolean (* take_references)
+ (CamelMessageInfo *mi,
+ GArray *references);
+ const CamelNameValueArray *
+ (* get_headers) (const CamelMessageInfo *mi);
+ gboolean (* take_headers)(CamelMessageInfo *mi,
+ CamelNameValueArray *headers);
+
+ /* Padding for future expansion */
+ gpointer reserved[20];
+};
+
+GType camel_message_info_get_type (void);
+CamelMessageInfo *
+ camel_message_info_new (struct _CamelFolderSummary *summary);
+CamelMessageInfo *
+ camel_message_info_clone (const CamelMessageInfo *mi,
+ struct _CamelFolderSummary *assign_summary);
+gboolean camel_message_info_load (CamelMessageInfo *mi,
+ const struct _CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr);
+gboolean camel_message_info_save (const CamelMessageInfo *mi,
+ struct _CamelMIRecord *record,
+ GString *bdata_str);
+struct _CamelFolderSummary *
+ camel_message_info_ref_summary (const CamelMessageInfo *mi);
+void camel_message_info_property_lock
+ (const CamelMessageInfo *mi);
+void camel_message_info_property_unlock
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_get_dirty (const CamelMessageInfo *mi);
+void camel_message_info_set_dirty (const CamelMessageInfo *mi,
+ gboolean dirty);
+gboolean camel_message_info_get_folder_flagged
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_folder_flagged
+ (CamelMessageInfo *mi,
+ gboolean folder_flagged);
+guint camel_message_info_get_folder_flagged_stamp
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_get_abort_notifications
+ (const CamelMessageInfo *mi);
+void camel_message_info_set_abort_notifications
+ (CamelMessageInfo *mi,
+ gboolean abort_notifications);
+void camel_message_info_freeze_notifications
+ (CamelMessageInfo *mi);
+void camel_message_info_thaw_notifications
+ (CamelMessageInfo *mi);
+gboolean camel_message_info_get_notifications_frozen
+ (const CamelMessageInfo *mi);
+const gchar * camel_message_info_get_uid (const CamelMessageInfo *mi);
+const gchar * camel_message_info_pooldup_uid (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_uid (CamelMessageInfo *mi,
+ const gchar *uid);
+guint32 camel_message_info_get_flags (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_flags (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set);
+gboolean camel_message_info_get_user_flag
+ (const CamelMessageInfo *mi,
+ const gchar *name);
+gboolean camel_message_info_set_user_flag
+ (CamelMessageInfo *mi,
+ const gchar *name,
+ gboolean state);
+const CamelNamedFlags *
+ camel_message_info_get_user_flags
+ (const CamelMessageInfo *mi);
+CamelNamedFlags *
+ camel_message_info_dup_user_flags
+ (const CamelMessageInfo *mi);
+gboolean
+ camel_message_info_take_user_flags
+ (CamelMessageInfo *mi,
+ CamelNamedFlags *user_flags);
+const gchar * camel_message_info_get_user_tag (const CamelMessageInfo *mi,
+ const gchar *name);
+gchar * camel_message_info_dup_user_tag (const CamelMessageInfo *mi,
+ const gchar *name);
+gboolean camel_message_info_set_user_tag (CamelMessageInfo *mi,
+ const gchar *name,
+ const gchar *value);
+const CamelNameValueArray *
+ camel_message_info_get_user_tags
+ (const CamelMessageInfo *mi);
+CamelNameValueArray *
+ camel_message_info_dup_user_tags
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_take_user_tags
+ (CamelMessageInfo *mi,
+ CamelNameValueArray *user_tags);
+const gchar * camel_message_info_get_subject (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_subject (CamelMessageInfo *mi,
+ const gchar *subject);
+const gchar * camel_message_info_get_from (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_from (CamelMessageInfo *mi,
+ const gchar *from);
+const gchar * camel_message_info_get_to (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_to (CamelMessageInfo *mi,
+ const gchar *to);
+const gchar * camel_message_info_get_cc (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_cc (CamelMessageInfo *mi,
+ const gchar *cc);
+const gchar * camel_message_info_get_mlist (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_mlist (CamelMessageInfo *mi,
+ const gchar *mlist);
+guint32 camel_message_info_get_size (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_size (CamelMessageInfo *mi,
+ guint32 size);
+gint64 camel_message_info_get_date_sent
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_date_sent
+ (CamelMessageInfo *mi,
+ gint64 date_sent);
+gint64 camel_message_info_get_date_received
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_date_received
+ (CamelMessageInfo *mi,
+ gint64 date_received);
+guint64 camel_message_info_get_message_id
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_set_message_id
+ (CamelMessageInfo *mi,
+ guint64 message_id);
+const GArray * camel_message_info_get_references
+ (const CamelMessageInfo *mi);
+GArray * camel_message_info_dup_references
+ (const CamelMessageInfo *mi);
+gboolean camel_message_info_take_references
+ (CamelMessageInfo *mi,
+ GArray *references);
+const CamelNameValueArray *
+ camel_message_info_get_headers (const CamelMessageInfo *mi);
+CamelNameValueArray *
+ camel_message_info_dup_headers (const CamelMessageInfo *mi);
+gboolean camel_message_info_take_headers (CamelMessageInfo *mi,
+ CamelNameValueArray *headers);
+
+/* Debugging functions */
+void camel_message_info_dump (CamelMessageInfo *mi);
+
+G_END_DECLS
+
+#endif /* CAMEL_MESSAGE_INFO_H */
diff --git a/src/camel/camel-mime-filter-yenc.c b/src/camel/camel-mime-filter-yenc.c
index ba87c9e..8f75192 100644
--- a/src/camel/camel-mime-filter-yenc.c
+++ b/src/camel/camel-mime-filter-yenc.c
@@ -380,12 +380,12 @@ static const gint yenc_crc_table[256] = {
/**
* camel_ydecode_step:
- * @in: input buffer
+ * @in: (type guchar) (array length=inlen): input buffer
* @inlen: input buffer length
- * @out: output buffer
- * @state: ydecode state
- * @pcrc: part crc state
- * @crc: crc state
+ * @out: (out) (array): output buffer
+ * @state: (out): ydecode state
+ * @pcrc: (out): part crc state
+ * @crc: (out): crc state
*
* Performs a 'decode step' on a chunk of yEncoded data of length
* @inlen pointed to by @in and writes to @out. Assumes the =ybegin
@@ -463,12 +463,12 @@ camel_ydecode_step (const guchar *in,
/**
* camel_yencode_step:
- * @in: input buffer
+ * @in: (type guchar) (array length=inlen): input buffer
* @inlen: input buffer length
- * @out: output buffer
- * @state: yencode state
- * @pcrc: part crc state
- * @crc: crc state
+ * @out: (array) (out): output buffer
+ * @state: (out): yencode state
+ * @pcrc: (out): part crc state
+ * @crc: (out): crc state
*
* Performs an yEncode 'encode step' on a chunk of raw data of length
* @inlen pointed to by @in and writes to @out.
@@ -532,12 +532,12 @@ camel_yencode_step (const guchar *in,
/**
* camel_yencode_close:
- * @in: input buffer
+ * @in: (type guchar) (array length=inlen): input buffer
* @inlen: input buffer length
- * @out: output buffer
- * @state: yencode state
- * @pcrc: part crc state
- * @crc: crc state
+ * @out: (array) (out): output buffer
+ * @state: (out): yencode state
+ * @pcrc: (out): part crc state
+ * @crc: (out): crc state
*
* Call this function when finished encoding data with
* camel_yencode_step() to flush off the remaining state.
diff --git a/src/camel/camel-mime-message.c b/src/camel/camel-mime-message.c
index d41b030..c7ea3a0 100644
--- a/src/camel/camel-mime-message.c
+++ b/src/camel/camel-mime-message.c
@@ -1217,7 +1217,7 @@ static const gchar tz_days[][4] = {
gchar *
camel_mime_message_build_mbox_from (CamelMimeMessage *message)
{
- struct _camel_header_raw *header = ((CamelMimePart *) message)->headers;
+ CamelHeaderRaw *header = ((CamelMimePart *) message)->headers;
GString *out = g_string_new ("From ");
gchar *ret;
const gchar *tmp;
diff --git a/src/camel/camel-mime-parser.c b/src/camel/camel-mime-parser.c
index dccf063..51fefcd 100644
--- a/src/camel/camel-mime-parser.c
+++ b/src/camel/camel-mime-parser.c
@@ -116,7 +116,7 @@ struct _header_scan_stack {
#ifdef MEMPOOL
CamelMemPool *pool; /* memory pool to keep track of headers/etc at this level */
#endif
- struct _camel_header_raw *headers; /* headers for this part */
+ CamelHeaderRaw *headers; /* headers for this part */
CamelContentType *content_type;
@@ -335,7 +335,7 @@ camel_mime_parser_header (CamelMimeParser *m,
*
* Since: 2.22
**/
-struct _camel_header_raw *
+CamelHeaderRaw *
camel_mime_parser_headers_raw (CamelMimeParser *m)
{
struct _header_scan_state *s = _PRIVATE (m);
@@ -1180,7 +1180,7 @@ header_append_mempool (struct _header_scan_state *s,
gchar *header,
gint offset)
{
- struct _camel_header_raw *l, *n;
+ CamelHeaderRaw *l, *n;
gchar *content;
content = strchr (header, ':');
@@ -1203,7 +1203,7 @@ header_append_mempool (struct _header_scan_state *s,
n->offset = offset;
- l = (struct _camel_header_raw *) &h->headers;
+ l = (CamelHeaderRaw *) &h->headers;
while (l->next) {
l = l->next;
}
diff --git a/src/camel/camel-mime-parser.h b/src/camel/camel-mime-parser.h
index ce5c098..a50da80 100644
--- a/src/camel/camel-mime-parser.h
+++ b/src/camel/camel-mime-parser.h
@@ -129,7 +129,7 @@ CamelContentType *camel_mime_parser_content_type (CamelMimeParser *parser);
const gchar *camel_mime_parser_header (CamelMimeParser *m, const gchar *name, gint *offset);
/* get all raw headers. READ ONLY! */
-struct _camel_header_raw *camel_mime_parser_headers_raw (CamelMimeParser *m);
+CamelHeaderRaw *camel_mime_parser_headers_raw (CamelMimeParser *m);
/* get multipart pre/postface */
const gchar *camel_mime_parser_preface (CamelMimeParser *m);
diff --git a/src/camel/camel-mime-part-utils.c b/src/camel/camel-mime-part-utils.c
index 9fe0f9e..e27977d 100644
--- a/src/camel/camel-mime-part-utils.c
+++ b/src/camel/camel-mime-part-utils.c
@@ -30,6 +30,7 @@
#include "camel-charset-map.h"
#include "camel-html-parser.h"
+#include "camel-iconv.h"
#include "camel-mime-filter-basic.h"
#include "camel-mime-filter-charset.h"
#include "camel-mime-filter-crlf.h"
@@ -150,91 +151,129 @@ camel_mime_part_construct_content_from_parser (CamelMimePart *dw,
return success;
}
+
/**
- * camel_mime_message_build_preview:
+ * camel_message_content_info_new:
*
- * <note>
- * <para>
- * This function blocks like crazy.
- * </para>
- * </note>
+ * Allocate a new #CamelMessageContentInfo.
*
- * Since: 2.28
+ * Returns: a newly allocated #CamelMessageContentInfo
**/
-gboolean
-camel_mime_message_build_preview (CamelMimePart *msg,
- CamelMessageInfo *info)
+CamelMessageContentInfo *
+camel_message_content_info_new (void)
{
- CamelDataWrapper *dw;
- gboolean got_plain = FALSE;
+ return g_slice_alloc0 (sizeof (CamelMessageContentInfo));
+}
- dw = camel_medium_get_content ((CamelMedium *) msg);
- if (camel_content_type_is (dw->mime_type, "multipart", "*")) {
- gint i, nparts;
- CamelMultipart *mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) msg);
+/**
+ * camel_message_content_info_free:
+ * @ci: a #CamelMessageContentInfo
+ *
+ * Recursively frees the content info @ci, and all associated memory.
+ **/
+void
+camel_message_content_info_free (CamelMessageContentInfo *ci)
+{
+ CamelMessageContentInfo *pw, *pn;
- g_warn_if_fail (CAMEL_IS_MULTIPART (mp));
+ pw = ci->childs;
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts && !got_plain; i++) {
- CamelMimePart *part = camel_multipart_get_part (mp, i);
- got_plain = camel_mime_message_build_preview (part, info);
- }
+ camel_content_type_unref (ci->type);
+ g_free (ci->id);
+ g_free (ci->description);
+ g_free (ci->encoding);
+ g_slice_free1 (sizeof (CamelMessageContentInfo), ci);
- } else if (camel_content_type_is (dw->mime_type, "text", "*") &&
- /* !camel_content_type_is (dw->mime_type, "text", "html") && */
- !camel_content_type_is (dw->mime_type, "text", "calendar")) {
- CamelStream *mstream, *bstream;
-
- /* FIXME Pass a GCancellable and GError here. */
- mstream = camel_stream_mem_new ();
- if (camel_data_wrapper_decode_to_stream_sync (dw, mstream, NULL, NULL) > 0) {
- gchar *line = NULL;
- GString *str = g_string_new (NULL);
-
- g_seekable_seek (
- G_SEEKABLE (mstream), 0,
- G_SEEK_SET, NULL, NULL);
-
- bstream = camel_stream_buffer_new (mstream, CAMEL_STREAM_BUFFER_READ |
CAMEL_STREAM_BUFFER_BUFFER);
-
- /* We should fetch just 200 unquoted lines. */
- while ((line = camel_stream_buffer_read_line ((CamelStreamBuffer *) bstream, NULL,
NULL)) && str->len < 200) {
- gchar *tmp = line;
-
- if (*line == '>' || strstr (line, "wrote:")) {
- g_free (tmp);
- continue;
- }
- if (g_str_has_prefix (line, "--")) {
- g_free (tmp);
- line = NULL;
- break;
- }
- while (*line && ((*line == ' ') || *line == '\t'))
- line++;
- if (*line == '\0' || *line == '\n') {
- g_free (tmp);
- continue;
- }
-
- g_string_append (str, " ");
- g_string_append (str, line);
- g_free (tmp);
- line = NULL;
- }
- if (str->len > 100) {
- g_string_insert (str, 100, "\n");
- }
- /* We don't mark dirty, as we don't store these */
- ((CamelMessageInfoBase *) info)->preview = camel_utf8_make_valid (str->str);
- g_string_free (str, TRUE);
-
- g_object_unref (bstream);
+ while (pw) {
+ pn = pw->next;
+ camel_message_content_info_free (pw);
+ pw = pn;
+ }
+}
+
+CamelMessageContentInfo *
+camel_message_content_info_new_from_parser (CamelMimeParser *mp)
+{
+ CamelMessageContentInfo *ci = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_MIME_PARSER (mp), NULL);
+
+ switch (camel_mime_parser_state (mp)) {
+ case CAMEL_MIME_PARSER_STATE_HEADER:
+ case CAMEL_MIME_PARSER_STATE_MESSAGE:
+ case CAMEL_MIME_PARSER_STATE_MULTIPART:
+ ci = camel_message_content_info_new_from_header (camel_mime_parser_headers_raw (mp));
+ if (ci) {
+ if (ci->type)
+ camel_content_type_unref (ci->type);
+ ci->type = camel_mime_parser_content_type (mp);
+ camel_content_type_ref (ci->type);
}
- g_object_unref (mstream);
- return TRUE;
+ break;
+ default:
+ g_error ("Invalid parser state");
}
- return got_plain;
+ return ci;
+}
+
+CamelMessageContentInfo *
+camel_message_content_info_new_from_message (CamelMimePart *mp)
+{
+ g_return_val_if_fail (CAMEL_IS_MIME_PART (mp), NULL);
+
+ return camel_message_content_info_new_from_header (mp->headers);
+}
+
+CamelMessageContentInfo *
+camel_message_content_info_new_from_header (CamelHeaderRaw *h)
+{
+ CamelMessageContentInfo *ci;
+ const gchar *charset;
+
+ ci = camel_message_content_info_new ();
+
+ charset = camel_iconv_locale_charset ();
+ ci->id = camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL));
+ ci->description = camel_header_decode_string (camel_header_raw_find (&h, "content-description",
NULL), charset);
+ ci->encoding = camel_content_transfer_encoding_decode (camel_header_raw_find (&h,
"content-transfer-encoding", NULL));
+ ci->type = camel_content_type_decode (camel_header_raw_find (&h, "content-type", NULL));
+
+ return ci;
+}
+
+void
+camel_message_content_info_dump (CamelMessageContentInfo *ci,
+ gint depth)
+{
+ gchar *p;
+
+ p = alloca (depth * 4 + 1);
+ memset (p, ' ', depth * 4);
+ p[depth * 4] = 0;
+
+ if (ci == NULL) {
+ printf ("%s<empty>\n", p);
+ return;
+ }
+
+ if (ci->type)
+ printf (
+ "%scontent-type: %s/%s\n",
+ p, ci->type->type ? ci->type->type : "(null)",
+ ci->type->subtype ? ci->type->subtype : "(null)");
+ else
+ printf ("%scontent-type: <unset>\n", p);
+ printf (
+ "%scontent-transfer-encoding: %s\n",
+ p, ci->encoding ? ci->encoding : "(null)");
+ printf (
+ "%scontent-description: %s\n",
+ p, ci->description ? ci->description : "(null)");
+ printf ("%ssize: %lu\n", p, (gulong) ci->size);
+ ci = ci->childs;
+ while (ci) {
+ camel_message_content_info_dump (ci, depth + 1);
+ ci = ci->next;
+ }
}
diff --git a/src/camel/camel-mime-part-utils.h b/src/camel/camel-mime-part-utils.h
index 916cc33..c76a686 100644
--- a/src/camel/camel-mime-part-utils.h
+++ b/src/camel/camel-mime-part-utils.h
@@ -35,8 +35,39 @@ gboolean camel_mime_part_construct_content_from_parser
CamelMimeParser *mp,
GCancellable *cancellable,
GError **error);
-gboolean camel_mime_message_build_preview (CamelMimePart *mime_part,
- CamelMessageInfo *info);
+
+typedef struct _CamelMessageContentInfo CamelMessageContentInfo;
+
+/* A tree of message content info structures
+ * describe the content structure of the message (if it has any) */
+struct _CamelMessageContentInfo {
+ CamelMessageContentInfo *next;
+
+ CamelMessageContentInfo *childs;
+ CamelMessageContentInfo *parent;
+
+ CamelContentType *type;
+ gchar *id;
+ gchar *description;
+ gchar *encoding;
+ guint32 size;
+};
+
+CamelMessageContentInfo *
+ camel_message_content_info_new (void);
+void camel_message_content_info_free (CamelMessageContentInfo *ci);
+CamelMessageContentInfo *
+ camel_message_content_info_new_from_header
+ (CamelHeaderRaw *header);
+CamelMessageContentInfo *
+ camel_message_content_info_new_from_parser
+ (CamelMimeParser *parser);
+CamelMessageContentInfo *
+ camel_message_content_info_new_from_message
+ (CamelMimePart *mime_part);
+/* debugging functions */
+void camel_message_content_info_dump (CamelMessageContentInfo *ci,
+ gint depth);
G_END_DECLS
diff --git a/src/camel/camel-mime-part.c b/src/camel/camel-mime-part.c
index 70b842b..82e63e5 100644
--- a/src/camel/camel-mime-part.c
+++ b/src/camel/camel-mime-part.c
@@ -520,7 +520,7 @@ mime_part_get_headers (CamelMedium *medium)
CamelMimePart *part = (CamelMimePart *) medium;
GArray *headers;
CamelMediumHeader header;
- struct _camel_header_raw *h;
+ CamelHeaderRaw *h;
headers = g_array_new (FALSE, FALSE, sizeof (CamelMediumHeader));
for (h = part->headers; h; h = h->next) {
@@ -581,7 +581,7 @@ mime_part_write_to_stream_sync (CamelDataWrapper *dw,
/* TODO: content-languages header? */
if (mp->headers) {
- struct _camel_header_raw *h = mp->headers;
+ CamelHeaderRaw *h = mp->headers;
gchar *val;
gssize (*writefn) (
gpointer stream,
@@ -774,7 +774,7 @@ mime_part_write_to_output_stream_sync (CamelDataWrapper *dw,
/* TODO: content-languages header? */
if (mp->headers) {
- struct _camel_header_raw *h = mp->headers;
+ CamelHeaderRaw *h = mp->headers;
gchar *val;
gssize (*writefn) (
gpointer stream,
@@ -972,7 +972,7 @@ mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
GError **error)
{
CamelDataWrapper *dw = (CamelDataWrapper *) mime_part;
- struct _camel_header_raw *headers;
+ CamelHeaderRaw *headers;
const gchar *content;
gchar *buf;
gsize len;
diff --git a/src/camel/camel-mime-part.h b/src/camel/camel-mime-part.h
index bcacdcb..9284b17 100644
--- a/src/camel/camel-mime-part.h
+++ b/src/camel/camel-mime-part.h
@@ -59,7 +59,7 @@ struct _CamelMimePart {
CamelMedium parent;
CamelMimePartPrivate *priv;
- struct _camel_header_raw *headers; /* mime headers */
+ CamelHeaderRaw *headers; /* mime headers */
};
struct _CamelMimePartClass {
diff --git a/src/camel/camel-mime-utils.c b/src/camel/camel-mime-utils.c
index 7c33fb8..03bdd1a 100644
--- a/src/camel/camel-mime-utils.c
+++ b/src/camel/camel-mime-utils.c
@@ -41,6 +41,7 @@
#include "camel-iconv.h"
#include "camel-mime-utils.h"
#include "camel-net-utils.h"
+#include "camel-string-utils.h"
#ifdef G_OS_WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -4469,7 +4470,7 @@ camel_header_location_decode (const gchar *in)
#ifdef CHECKS
static void
-check_header (struct _camel_header_raw *header)
+check_header (CamelHeaderRaw *header)
{
guchar *cp;
@@ -4484,8 +4485,16 @@ check_header (struct _camel_header_raw *header)
}
#endif
+/**
+ * camel_header_raw_append_parse:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @header: an unparsed header
+ * @offset: the given offset
+ *
+ * Appends the parsed header to the list with the given offset.
+ **/
void
-camel_header_raw_append_parse (struct _camel_header_raw **list,
+camel_header_raw_append_parse (CamelHeaderRaw **list,
const gchar *header,
gint offset)
{
@@ -4510,13 +4519,22 @@ camel_header_raw_append_parse (struct _camel_header_raw **list,
camel_header_raw_append (list, name, in, offset);
}
+/**
+ * camel_header_raw_append:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the given name
+ * @value: the given value
+ * @offset: the given offset
+ *
+ * Appends a value with the given name and the given value to the list.
+ **/
void
-camel_header_raw_append (struct _camel_header_raw **list,
+camel_header_raw_append (CamelHeaderRaw **list,
const gchar *name,
const gchar *value,
gint offset)
{
- struct _camel_header_raw *l, *n;
+ CamelHeaderRaw *l, *n;
d (printf ("Header: %s: %s\n", name, value));
@@ -4528,7 +4546,7 @@ camel_header_raw_append (struct _camel_header_raw **list,
#ifdef CHECKS
check_header (n);
#endif
- l = (struct _camel_header_raw *) list;
+ l = (CamelHeaderRaw *) list;
while (l->next) {
l = l->next;
}
@@ -4549,11 +4567,20 @@ camel_header_raw_append (struct _camel_header_raw **list,
#endif
}
-static struct _camel_header_raw *
-header_raw_find_node (struct _camel_header_raw **list,
+/**
+ * header_raw_find_node:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the name to find
+ *
+ * Searches for the node with a given name.
+ *
+ * Returns: (transfer none) (nullable): the found #CamelHeaderRaw or NULL.
+ **/
+static CamelHeaderRaw *
+header_raw_find_node (CamelHeaderRaw **list,
const gchar *name)
{
- struct _camel_header_raw *l;
+ CamelHeaderRaw *l;
l = *list;
while (l) {
@@ -4564,12 +4591,22 @@ header_raw_find_node (struct _camel_header_raw **list,
return l;
}
+/**
+ * camel_header_raw_find:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the name to find
+ * @offset: (out) (nullable): the offset corresponding to the name
+ *
+ * Searches for the first node with a given name and returns its value.
+ *
+ * Returns: (transfer none) (nullable): the value associated with the name
+ **/
const gchar *
-camel_header_raw_find (struct _camel_header_raw **list,
+camel_header_raw_find (CamelHeaderRaw **list,
const gchar *name,
gint *offset)
{
- struct _camel_header_raw *l;
+ CamelHeaderRaw *l;
l = header_raw_find_node (list, name);
if (l) {
@@ -4580,13 +4617,24 @@ camel_header_raw_find (struct _camel_header_raw **list,
return NULL;
}
+/**
+ * camel_header_raw_find_next:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the name to find
+ * @offset: (out) (nullable): the offset corresponding to the name
+ * @last: the last found value
+ *
+ * Searches for the next node with a given name and returns its value.
+ *
+ * Returns: (transfer none) (nullable): the value associated with the name
+ **/
const gchar *
-camel_header_raw_find_next (struct _camel_header_raw **list,
+camel_header_raw_find_next (CamelHeaderRaw **list,
const gchar *name,
gint *offset,
const gchar *last)
{
- struct _camel_header_raw *l;
+ CamelHeaderRaw *l;
if (last == NULL || name == NULL)
return NULL;
@@ -4598,21 +4646,28 @@ camel_header_raw_find_next (struct _camel_header_raw **list,
}
static void
-header_raw_free (struct _camel_header_raw *l)
+header_raw_free (CamelHeaderRaw *l)
{
g_free (l->name);
g_free (l->value);
g_free (l);
}
+/**
+ * camel_header_raw_remove:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the name to remove
+ *
+ * Remove all values associated with the given name
+ **/
void
-camel_header_raw_remove (struct _camel_header_raw **list,
+camel_header_raw_remove (CamelHeaderRaw **list,
const gchar *name)
{
- struct _camel_header_raw *l, *p;
+ CamelHeaderRaw *l, *p;
/* the next pointer is at the head of the structure, so this is safe */
- p = (struct _camel_header_raw *) list;
+ p = (CamelHeaderRaw *) list;
l = *list;
while (l) {
if (!g_ascii_strcasecmp (l->name, name)) {
@@ -4626,8 +4681,17 @@ camel_header_raw_remove (struct _camel_header_raw **list,
}
}
+/**
+ * camel_header_raw_replace:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ * @name: the name to remove
+ * @value: the new value
+ * @offset: the new offset
+ *
+ * Replace the row associated with the given name by another value and offset.
+ **/
void
-camel_header_raw_replace (struct _camel_header_raw **list,
+camel_header_raw_replace (CamelHeaderRaw **list,
const gchar *name,
const gchar *value,
gint offset)
@@ -4636,10 +4700,17 @@ camel_header_raw_replace (struct _camel_header_raw **list,
camel_header_raw_append (list, name, value, offset);
}
+
+/**
+ * camel_header_raw_clear:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ *
+ * Removes all the raws of the list.
+ **/
void
-camel_header_raw_clear (struct _camel_header_raw **list)
+camel_header_raw_clear (CamelHeaderRaw **list)
{
- struct _camel_header_raw *l, *n;
+ CamelHeaderRaw *l, *n;
l = *list;
while (l) {
n = l->next;
@@ -4775,8 +4846,16 @@ mailing_list_init (gpointer param)
return NULL;
}
+/**
+ * camel_header_raw_check_mailing_list:
+ * @list: (array zero-terminated=1): a NULL-terminated list of #CamelHeaderRaw
+ *
+ * TODO: Document me.
+ *
+ * Returns: (transfer full) (nullable):
+ **/
gchar *
-camel_header_raw_check_mailing_list (struct _camel_header_raw **list)
+camel_header_raw_check_mailing_list (CamelHeaderRaw **list)
{
static GOnce once = G_ONCE_INIT;
const gchar *v;
diff --git a/src/camel/camel-mime-utils.h b/src/camel/camel-mime-utils.h
index 2a51044..12c647e 100644
--- a/src/camel/camel-mime-utils.h
+++ b/src/camel/camel-mime-utils.h
@@ -29,6 +29,9 @@
#include <glib.h>
#include <glib-object.h>
#include <camel/camel-enums.h>
+#include <camel/camel-utils.h>
+
+G_BEGIN_DECLS
/* maximum recommended size of a line from camel_header_fold() */
#define CAMEL_FOLD_SIZE (77)
@@ -43,8 +46,6 @@ typedef enum {
#define CAMEL_UUDECODE_STATE_MASK (CAMEL_UUDECODE_STATE_BEGIN | CAMEL_UUDECODE_STATE_END)
-G_BEGIN_DECLS
-
typedef struct _camel_header_param {
struct _camel_header_param *next;
gchar *name;
@@ -61,12 +62,12 @@ typedef struct {
/* a raw rfc822 header */
/* the value MUST be US-ASCII */
-struct _camel_header_raw {
+typedef struct _camel_header_raw {
struct _camel_header_raw *next;
gchar *name;
gchar *value;
gint offset; /* in file, if known */
-};
+} CamelHeaderRaw;
typedef struct _CamelContentDisposition {
gchar *disposition;
@@ -153,16 +154,15 @@ gchar *camel_content_disposition_format (CamelContentDisposition *disposition);
gchar *camel_content_transfer_encoding_decode (const gchar *in);
/* raw headers */
-void camel_header_raw_append (struct _camel_header_raw **list, const gchar *name, const gchar *value, gint
offset);
-void camel_header_raw_append_parse (struct _camel_header_raw **list, const gchar *header, gint offset);
-const gchar *camel_header_raw_find (struct _camel_header_raw **list, const gchar *name, gint *offset);
-const gchar *camel_header_raw_find_next (struct _camel_header_raw **list, const gchar *name, gint *offset,
const gchar *last);
-void camel_header_raw_replace (struct _camel_header_raw **list, const gchar *name, const gchar *value, gint
offset);
-void camel_header_raw_remove (struct _camel_header_raw **list, const gchar *name);
-void camel_header_raw_fold (struct _camel_header_raw **list);
-void camel_header_raw_clear (struct _camel_header_raw **list);
-
-gchar *camel_header_raw_check_mailing_list (struct _camel_header_raw **list);
+void camel_header_raw_append (CamelHeaderRaw **list, const gchar *name, const gchar *value, gint offset);
+void camel_header_raw_append_parse (CamelHeaderRaw **list, const gchar *header, gint offset);
+const gchar *camel_header_raw_find (CamelHeaderRaw **list, const gchar *name, gint *offset);
+const gchar *camel_header_raw_find_next (CamelHeaderRaw **list, const gchar *name, gint *offset, const gchar
*last);
+void camel_header_raw_replace (CamelHeaderRaw **list, const gchar *name, const gchar *value, gint offset);
+void camel_header_raw_remove (CamelHeaderRaw **list, const gchar *name);
+void camel_header_raw_clear (CamelHeaderRaw **list);
+
+gchar *camel_header_raw_check_mailing_list (CamelHeaderRaw **list);
/* fold a header */
gchar *camel_header_address_fold (const gchar *in, gsize headerlen);
diff --git a/src/camel/camel-movemail.c b/src/camel/camel-movemail.c
index 4e00e2e..05f065b 100644
--- a/src/camel/camel-movemail.c
+++ b/src/camel/camel-movemail.c
@@ -431,7 +431,7 @@ camel_movemail_copy_filter (gint fromfd,
* want to maintain it! */
static gint
solaris_header_write (gint fd,
- struct _camel_header_raw *header)
+ CamelHeaderRaw *header)
{
struct iovec iv[4];
gint outlen = 0, len;
diff --git a/src/camel/camel-msgport.c b/src/camel/camel-msgport.c
index 26a9cd0..d604cb5 100644
--- a/src/camel/camel-msgport.c
+++ b/src/camel/camel-msgport.c
@@ -304,6 +304,7 @@ camel_msgport_fd (CamelMsgPort *msgport)
/**
* camel_msgport_prfd:
*
+ * Returns: (transfer none):
* Since: 2.24
**/
PRFileDesc *
diff --git a/src/camel/camel-name-value-array.c b/src/camel/camel-name-value-array.c
new file mode 100644
index 0000000..4b76aeb
--- /dev/null
+++ b/src/camel/camel-name-value-array.c
@@ -0,0 +1,633 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "camel-string-utils.h"
+
+#include "camel-name-value-array.h"
+
+G_DEFINE_BOXED_TYPE (CamelNameValueArray,
+ camel_name_value_array,
+ camel_name_value_array_copy,
+ camel_name_value_array_free)
+
+typedef struct _CamelNameValuePair {
+ gchar *name;
+ gchar *value;
+} CamelNameValuePair;
+
+static void
+free_name_value_content (gpointer ptr)
+{
+ CamelNameValuePair *pair = ptr;
+
+ if (pair) {
+ g_free (pair->name);
+ g_free (pair->value);
+
+ pair->name = NULL;
+ pair->value = NULL;
+ }
+}
+
+/**
+ * camel_name_value_array_new:
+ *
+ * Created a new #CamelNameValueArray. The returned pointer should be freed
+ * with camel_name_value_array_free() when no longer needed.
+ *
+ * Returns: (transfer full): A new #CamelNameValueArray.
+ *
+ * See: camel_name_value_array_new_sized, camel_name_value_array_copy
+ *
+ * Since: 3.24
+ **/
+CamelNameValueArray *
+camel_name_value_array_new (void)
+{
+ GArray *arr;
+
+ arr = g_array_new (FALSE, FALSE, sizeof (CamelNameValuePair));
+ g_array_set_clear_func (arr, free_name_value_content);
+
+ return (CamelNameValueArray *) arr;
+}
+
+/**
+ * camel_name_value_array_new_sized:
+ * @reserve_size: an array size to reserve
+ *
+ * Created a new #CamelNameValueArray, which has reserved @reserve_size
+ * elements. This value doesn't influence the camel_name_value_array_get_length(),
+ * which returns zero on the array returned from this function. The returned
+ * pointer should be freed with camel_name_value_array_free() when no longer needed.
+ *
+ * Returns: (transfer full): A new #CamelNameValueArray.
+ *
+ * See: camel_name_value_array_new, camel_name_value_array_copy
+ *
+ * Since: 3.24
+ **/
+CamelNameValueArray *
+camel_name_value_array_new_sized (guint reserve_size)
+{
+ GArray *arr;
+
+ arr = g_array_sized_new (FALSE, FALSE, sizeof (CamelNameValuePair), reserve_size);
+ g_array_set_clear_func (arr, free_name_value_content);
+
+ return (CamelNameValueArray *) arr;
+}
+
+/**
+ * camel_name_value_array_copy:
+ * @array: (nullable): a #CamelNameValueArray
+ *
+ * Created a new copy of the @array. The returned pointer should be freed
+ * with camel_name_value_array_free() when no longer needed.
+ *
+ * Returns: (transfer full): A new copy of the @array.
+ *
+ * See: camel_name_value_array_new, camel_name_value_array_new_sized
+ *
+ * Since: 3.24
+ **/
+CamelNameValueArray *
+camel_name_value_array_copy (const CamelNameValueArray *array)
+{
+ CamelNameValueArray *copy;
+ guint ii, len;
+
+ if (!array)
+ return NULL;
+
+ len = camel_name_value_array_get_length (array);
+ copy = camel_name_value_array_new_sized (len);
+
+ for (ii = 0; ii < len; ii++) {
+ const gchar *name = NULL, *value = NULL;
+
+ if (camel_name_value_array_get (array, ii, &name, &value))
+ camel_name_value_array_append (copy, name, value);
+ }
+
+ return copy;
+}
+
+/**
+ * camel_name_value_array_free:
+ * @array: (nullable): a #CamelNameValueArray, or %NULL
+ *
+ * Frees the @array, previously allocated by camel_name_value_array_new(),
+ * camel_name_value_array_new_sized() or camel_name_value_array_copy().
+ * If the @array is %NULL, then does nothing.
+ *
+ * Since: 3.24
+ **/
+void
+camel_name_value_array_free (CamelNameValueArray *array)
+{
+ if (array)
+ g_array_free ((GArray *) array, TRUE);
+}
+
+/**
+ * camel_name_value_array_get_length:
+ * @array: (nullable): a #CamelNameValueArray
+ *
+ * Returns: Length of the @array, aka how many elements are stored in the @array.
+ *
+ * Since: 3.24
+ **/
+guint
+camel_name_value_array_get_length (const CamelNameValueArray *array)
+{
+ GArray *arr = (GArray *) array;
+
+ if (!array)
+ return 0;
+
+ return arr->len;
+}
+
+/**
+ * camel_name_value_array_get:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ * @out_name: (out) (nullable): A place to store the name of the element, or %NULL
+ * @out_value: (out) (nullable): A place to store the value of the element, or %NULL
+ *
+ * Returns the name and the value of the element at index @index. Either
+ * of the @out_name and @out_value can be %NULL, to not return that part.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise.
+ *
+ * See: camel_name_value_array_get_name, camel_name_value_array_get_value, camel_name_value_array_get_named
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_get (const CamelNameValueArray *array,
+ guint index,
+ const gchar **out_name,
+ const gchar **out_value)
+{
+ GArray *arr = (GArray *) array;
+ CamelNameValuePair *pair;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+
+ pair = &g_array_index (arr, CamelNameValuePair, index);
+
+ if (out_name)
+ *out_name = pair->name;
+ if (out_value)
+ *out_value= pair->value;
+
+ return TRUE;
+}
+
+static guint
+camel_name_value_array_find_named (const CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name)
+{
+ GArray *arr = (GArray *) array;
+ gint ii;
+
+ g_return_val_if_fail (array != NULL, (guint) -1);
+ g_return_val_if_fail (name != NULL, (guint) -1);
+
+ for (ii = 0; ii < arr->len; ii++) {
+ CamelNameValuePair *pair = &g_array_index (arr, CamelNameValuePair, ii);
+
+ if ((case_sensitive && g_strcmp0 (name, pair->name) == 0) ||
+ (!case_sensitive && pair->name && camel_strcase_equal (name, pair->name))) {
+ return ii;
+ }
+ }
+
+ return (guint) -1;
+}
+
+/**
+ * camel_name_value_array_get_named:
+ * @array: a #CamelNameValueArray
+ * @case_sensitive: whether to compare names case sensitively
+ * @name: a name
+ *
+ * Returns the value of the first element named @name, or %NULL when there
+ * is no element of such @name in the @array. The @case_sensitive determines
+ * whether compare names case sensitively (%TRUE) or insensitively (%FALSE).
+ *
+ * Returns: (transfer none) (nullable): Value of the first element named @name, or %NULL.
+ *
+ * See: camel_name_value_array_get, camel_name_value_array_get_name
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_name_value_array_get_named (const CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name)
+{
+ guint index;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ index = camel_name_value_array_find_named (array, case_sensitive, name);
+ if (index == (guint) -1)
+ return NULL;
+
+ return camel_name_value_array_get_value (array, index);
+}
+
+/**
+ * camel_name_value_array_get_name:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ *
+ * Returns the name of the element at index @index.
+ *
+ * Returns: (transfer none) (nullable): Name of the element at the given @index,
+ * or %NULL on error.
+ *
+ * See: camel_name_value_array_get, camel_name_value_array_get_value
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_name_value_array_get_name (const CamelNameValueArray *array,
+ guint index)
+{
+ const gchar *name = NULL;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), NULL);
+
+ if (!camel_name_value_array_get (array, index, &name, NULL))
+ return NULL;
+
+ return name;
+}
+
+/**
+ * camel_name_value_array_get_value:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ *
+ * Returns the value of the element at index @index.
+ *
+ * Returns: (transfer none) (nullable): Value of the element at the given @index,
+ * or %NULL on error.
+ *
+ * See: camel_name_value_array_get, camel_name_value_array_get_name
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_name_value_array_get_value (const CamelNameValueArray *array,
+ guint index)
+{
+ const gchar *value = NULL;
+
+ g_return_val_if_fail (array != NULL, NULL);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), NULL);
+
+ if (!camel_name_value_array_get (array, index, NULL, &value))
+ return NULL;
+
+ return value;
+}
+
+/**
+ * camel_name_value_array_append:
+ * @array: a #CamelNameValueArray
+ * @name: a name
+ * @value: a value
+ *
+ * Appends a new element of the name @name and the value @value
+ * at the end of @array.
+ *
+ * See: camel_name_value_array_set_named
+ *
+ * Since: 3.24
+ **/
+void
+camel_name_value_array_append (CamelNameValueArray *array,
+ const gchar *name,
+ const gchar *value)
+{
+ GArray *arr = (GArray *) array;
+ CamelNameValuePair pair;
+
+ g_return_if_fail (array != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (value != NULL);
+
+ pair.name = g_strdup (name);
+ pair.value = g_strdup (value);
+
+ g_array_append_val (arr, pair);
+}
+
+static gboolean
+camel_name_value_array_set_internal (CamelNameValueArray *array,
+ guint index,
+ const gchar *name,
+ const gchar *value)
+{
+ GArray *arr = (GArray *) array;
+ CamelNameValuePair *pair;
+ gboolean changed = FALSE;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+
+ pair = &g_array_index (arr, CamelNameValuePair, index);
+
+ if (name && g_strcmp0 (pair->name, name) != 0) {
+ g_free (pair->name);
+ pair->name = g_strdup (name);
+ changed = TRUE;
+ }
+
+ if (value && g_strcmp0 (pair->value, value) != 0) {
+ g_free (pair->value);
+ pair->value = g_strdup (value);
+ changed = TRUE;
+ }
+
+ return changed;
+}
+
+/**
+ * camel_name_value_array_set:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ * @name: a name
+ * @value: a value
+ *
+ * Sets both the @name and the @value of the element at index @index.
+ *
+ * Returns: Whether the @array changed.
+ *
+ * See: camel_name_value_array_append, camel_name_value_array_set_name, camel_name_value_array_set_value
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_set (CamelNameValueArray *array,
+ guint index,
+ const gchar *name,
+ const gchar *value)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ return camel_name_value_array_set_internal (array, index, name, value);
+}
+
+/**
+ * camel_name_value_array_set_name:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ * @name: a name
+ *
+ * Sets the @name of the element at index @index.
+ *
+ * Returns: Whether the @array changed.
+ *
+ * See: camel_name_value_array_set, camel_name_value_array_set_value
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_set_name (CamelNameValueArray *array,
+ guint index,
+ const gchar *name)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ return camel_name_value_array_set_internal (array, index, name, NULL);
+}
+
+/**
+ * camel_name_value_array_set_value:
+ * @array: a #CamelNameValueArray
+ * @index: an index
+ * @value: a value
+ *
+ * Sets the @value of the element at index @index.
+ *
+ * Returns: Whether the @array changed.
+ *
+ * See: camel_name_value_array_set, camel_name_value_array_set_name
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_set_value (CamelNameValueArray *array,
+ guint index,
+ const gchar *value)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ return camel_name_value_array_set_internal (array, index, NULL, value);
+}
+
+/**
+ * camel_name_value_array_set_named:
+ * @array: a #CamelNameValueArray
+ * @case_sensitive: whether to compare names case sensitively
+ * @name: a name
+ * @value: a value
+ *
+ * Finds an element named @name and sets its value to @value, or appends
+ * a new element, in case no such named lement exists in the @array yet.
+ * In case there are more elements named with @name only the first
+ * occurrence is changed. The @case_sensitive determines whether compare
+ * names case sensitively (%TRUE) or insensitively (%FALSE).
+ *
+ * Returns: Whether the @array changed.
+ *
+ * See: camel_name_value_array_append, camel_name_value_array_set
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_set_named (CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name,
+ const gchar *value)
+{
+ gboolean changed = FALSE;
+ guint index;
+
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ index = camel_name_value_array_find_named (array, case_sensitive, name);
+ if (index == (guint) -1) {
+ camel_name_value_array_append (array, name, value);
+ changed = TRUE;
+ } else {
+ changed = camel_name_value_array_set_value (array, index, value);
+ }
+
+ return changed;
+}
+
+/**
+ * camel_name_value_array_remove:
+ * @array: a #CamelNameValueArray
+ * @index: an index to remove
+ *
+ * Removes element at index @index.
+ *
+ * Returns: Whether the element was removed.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_remove (CamelNameValueArray *array,
+ guint index)
+{
+ g_return_val_if_fail (array != NULL, FALSE);
+ g_return_val_if_fail (index < camel_name_value_array_get_length (array), FALSE);
+
+ g_array_remove_index ((GArray *) array, index);
+
+ return TRUE;
+}
+
+/**
+ * camel_name_value_array_remove_named:
+ * @array: a #CamelNameValueArray
+ * @case_sensitive: whether to compare names case sensitively
+ * @name: a name to remove
+ * @all_occurrences: whether to remove all occurrences of the @name
+ *
+ * Removes elements of the @array with the given @name. The @case_sensitive
+ * determines whether compare case sensitively (%TRUE) or insensitively (%FALSE).
+ * If the @all_occurrences is set to %TRUE, then every elements with the @name
+ * are removed, otherwise only the first occurrence is removed.
+ *
+ * Returns: How many elements had been removed.
+ *
+ * Since: 3.24
+ **/
+guint
+camel_name_value_array_remove_named (CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name,
+ gboolean all_occurrences)
+{
+ guint index, removed = 0;
+
+ g_return_val_if_fail (array != NULL, 0);
+ g_return_val_if_fail (name != NULL, 0);
+
+ while (index = camel_name_value_array_find_named (array, case_sensitive, name), index != (guint) -1) {
+ if (!camel_name_value_array_remove (array, index))
+ break;
+
+ removed++;
+
+ if (!all_occurrences)
+ break;
+ }
+
+ return removed;
+}
+
+/**
+ * camel_name_value_array_clear:
+ * @array: a #CamelNameValueArray
+ *
+ * Removes all elements of the @array.
+ *
+ * Since: 3.24
+ **/
+void
+camel_name_value_array_clear (CamelNameValueArray *array)
+{
+ GArray *arr = (GArray *) array;
+
+ g_return_if_fail (array != NULL);
+
+ g_array_remove_range (arr, 0, arr->len);
+}
+
+/**
+ * camel_name_value_array_equal:
+ * @array_a: (nullable): the first #CamelNameValueArray
+ * @array_b: (nullable): the second #CamelNameValueArray
+ * @case_sensitive: whether to search for names case sensitively
+ *
+ * Compares content of the two #CamelNameValueArray and returns whether
+ * they equal. Note this is an expensive operation for large arrays.
+ *
+ * Returns: Whether the two #CamelNameValueArray have the same content.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_name_value_array_equal (const CamelNameValueArray *array_a,
+ const CamelNameValueArray *array_b,
+ gboolean case_sensitive)
+{
+ guint ii, len;
+
+ if (array_a == array_b)
+ return TRUE;
+
+ if (!array_a || !array_b)
+ return FALSE;
+
+ len = camel_name_value_array_get_length (array_a);
+ if (len != camel_name_value_array_get_length (array_b))
+ return FALSE;
+
+ for (ii = 0; ii < len; ii++) {
+ const gchar *value1, *value2;
+
+ value1 = camel_name_value_array_get_value (array_a, ii);
+ value2 = camel_name_value_array_get_named (array_b, case_sensitive,
+ camel_name_value_array_get_name (array_a, ii));
+
+ if (g_strcmp0 (value1, value2) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/camel/camel-name-value-array.h b/src/camel/camel-name-value-array.h
new file mode 100644
index 0000000..aa902a9
--- /dev/null
+++ b/src/camel/camel-name-value-array.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_NAME_VALUE_ARRAY_H
+#define CAMEL_NAME_VALUE_ARRAY_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * CamelNameValueArray:
+ *
+ * Since: 3.24
+ **/
+struct _CamelNameValueArray;
+typedef struct _CamelNameValueArray CamelNameValueArray;
+
+#define CAMEL_TYPE_NAME_VALUE_ARRAY (camel_name_value_array_get_type ())
+
+GType camel_name_value_array_get_type (void) G_GNUC_CONST;
+CamelNameValueArray *
+ camel_name_value_array_new (void);
+CamelNameValueArray *
+ camel_name_value_array_new_sized
+ (guint reserve_size);
+CamelNameValueArray *
+ camel_name_value_array_copy (const CamelNameValueArray *array);
+void camel_name_value_array_free (CamelNameValueArray *array);
+guint camel_name_value_array_get_length
+ (const CamelNameValueArray *array);
+gboolean camel_name_value_array_get (const CamelNameValueArray *array,
+ guint index,
+ const gchar **out_name,
+ const gchar **out_value);
+const gchar * camel_name_value_array_get_named
+ (const CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name);
+const gchar * camel_name_value_array_get_name (const CamelNameValueArray *array,
+ guint index);
+const gchar * camel_name_value_array_get_value
+ (const CamelNameValueArray *array,
+ guint index);
+void camel_name_value_array_append (CamelNameValueArray *array,
+ const gchar *name,
+ const gchar *value);
+gboolean camel_name_value_array_set (CamelNameValueArray *array,
+ guint index,
+ const gchar *name,
+ const gchar *value);
+gboolean camel_name_value_array_set_name (CamelNameValueArray *array,
+ guint index,
+ const gchar *name);
+gboolean camel_name_value_array_set_value
+ (CamelNameValueArray *array,
+ guint index,
+ const gchar *value);
+gboolean camel_name_value_array_set_named
+ (CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name,
+ const gchar *value);
+gboolean camel_name_value_array_remove (CamelNameValueArray *array,
+ guint index);
+guint camel_name_value_array_remove_named
+ (CamelNameValueArray *array,
+ gboolean case_sensitive,
+ const gchar *name,
+ gboolean all_occurrences);
+void camel_name_value_array_clear (CamelNameValueArray *array);
+gboolean camel_name_value_array_equal (const CamelNameValueArray *array_a,
+ const CamelNameValueArray *array_b,
+ gboolean case_sensitive);
+
+G_END_DECLS
+
+#endif /* CAMEL_NAME_VALUE_ARRAY_H */
diff --git a/src/camel/camel-named-flags.c b/src/camel/camel-named-flags.c
new file mode 100644
index 0000000..c2869b4
--- /dev/null
+++ b/src/camel/camel-named-flags.c
@@ -0,0 +1,317 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "camel-named-flags.h"
+
+G_DEFINE_BOXED_TYPE (CamelNamedFlags,
+ camel_named_flags,
+ camel_named_flags_copy,
+ camel_named_flags_free)
+
+/**
+ * camel_named_flags_new:
+ *
+ * Creates a new #CamelNamedFlags.
+ *
+ * Returns: (transfer full): A newly allocated #CamelNamedFlags.
+ * Free it with camel_named_flags_free() when done with it.
+ *
+ * Since: 3.24
+ **/
+CamelNamedFlags *
+camel_named_flags_new (void)
+{
+ return (CamelNamedFlags *) g_ptr_array_new_with_free_func (g_free);
+}
+
+/**
+ * camel_named_flags_new_sized:
+ * @reserve_size: an array size to reserve
+ *
+ * Created a new #CamelNamedFlags, which has reserved @reserve_size
+ * elements. This value doesn't influence the camel_named_flags_get_length(),
+ * which returns zero on the array returned from this function.
+ *
+ * Returns: (transfer full): A newly allocated #CamelNameValueArray.
+ * Free it with camel_named_flags_free() when done with it.
+ *
+ * See: camel_name_value_array_new, camel_name_value_array_copy
+ *
+ * Since: 3.24
+ **/
+CamelNamedFlags *
+camel_named_flags_new_sized (guint reserve_size)
+{
+ return (CamelNamedFlags *) g_ptr_array_new_full (reserve_size, g_free);
+}
+
+/**
+ * camel_named_flags_copy:
+ * @named_flags: (nullable): a #CamelNamedFlags
+ *
+ * Creates a copy of the @named_flags and returns it.
+ *
+ * Returns: (transfer full): A newly allocated #CamelNamedFlags.
+ * Free it with camel_named_flags_free() when done with it.
+ *
+ * Since: 3.24
+ **/
+CamelNamedFlags *
+camel_named_flags_copy (const CamelNamedFlags *named_flags)
+{
+ const GPtrArray *src = (const GPtrArray *) named_flags;
+ GPtrArray *arr;
+ guint ii;
+
+ if (!src)
+ return NULL;
+
+ arr = (GPtrArray *) camel_named_flags_new_sized (src->len);
+ for (ii = 0; ii < src->len; ii++) {
+ const gchar *name = g_ptr_array_index (src, ii);
+
+ if (name && *name)
+ g_ptr_array_add (arr, g_strdup (name));
+ }
+
+ return (CamelNamedFlags *) arr;
+}
+
+/**
+ * camel_named_flags_free:
+ * @named_flags: (nullable): a #CamelNamedFlags, or %NULL
+ *
+ * Frees memory associated iwth the @named_flags. Does nothing,
+ * if @named_flags is %NULL.
+ *
+ * Since: 3.24
+ **/
+void
+camel_named_flags_free (CamelNamedFlags *named_flags)
+{
+ if (named_flags)
+ g_ptr_array_unref ((GPtrArray *) named_flags);
+}
+
+static guint
+camel_named_flags_find (const CamelNamedFlags *named_flags,
+ const gchar *name)
+{
+ GPtrArray *arr = (GPtrArray *) named_flags;
+ guint ii;
+
+ g_return_val_if_fail (named_flags != NULL, (guint) -1);
+ g_return_val_if_fail (name != NULL, (guint) -1);
+
+ for (ii = 0; ii < arr->len; ii++) {
+ const gchar *nm = g_ptr_array_index (arr, ii);
+
+ if (g_strcmp0 (nm, name) == 0)
+ return ii;
+ }
+
+ return (guint) -1;
+}
+
+/**
+ * camel_named_flags_insert:
+ * @named_flags: a #CamelNamedFlags
+ * @name: name of the flag
+ *
+ * Inserts a flag named @name into the @named_flags, if it is not included
+ * already (comparing case sensitively), or does nothing otherwise.
+ *
+ * Returns: %TRUE the flag named @name was inserted; %FALSE otherwise.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_named_flags_insert (CamelNamedFlags *named_flags,
+ const gchar *name)
+{
+ GPtrArray *arr = (GPtrArray *) named_flags;
+ guint index;
+
+ g_return_val_if_fail (named_flags != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ index = camel_named_flags_find (named_flags, name);
+
+ /* already there */
+ if (index != (guint) -1)
+ return FALSE;
+
+ g_ptr_array_add (arr, g_strdup (name));
+
+ return TRUE;
+}
+
+/**
+ * camel_named_flags_remove:
+ * @named_flags: a #CamelNamedFlags
+ * @name: name of the flag
+ *
+ * Removes a flag named @name from the @named_flags.
+ *
+ * Returns: %TRUE when the @named_flags contained a flag named @name,
+ * comparing case sensitively, and it was removed; %FALSE otherwise.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_named_flags_remove (CamelNamedFlags *named_flags,
+ const gchar *name)
+{
+ GPtrArray *arr = (GPtrArray *) named_flags;
+ guint index;
+
+ g_return_val_if_fail (named_flags != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ index = camel_named_flags_find (named_flags, name);
+
+ /* not there */
+ if (index == (guint) -1)
+ return FALSE;
+
+ g_ptr_array_remove_index (arr, index);
+
+ return TRUE;
+}
+
+/**
+ * camel_named_flags_contains:
+ * @named_flags: a #CamelNamedFlags
+ * @name: name of the flag
+ *
+ * Returns: Whether the @named_flags contains a flag named @name,
+ * comparing case sensitively.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_named_flags_contains (const CamelNamedFlags *named_flags,
+ const gchar *name)
+{
+ g_return_val_if_fail (named_flags != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ return camel_named_flags_find (named_flags, name) != (guint) -1;
+}
+
+/**
+ * camel_named_flags_clear:
+ * @named_flags: a #CamelNamedFlags
+ *
+ * Removes all the elements of the array.
+ *
+ * Since: 3.24
+ **/
+void
+camel_named_flags_clear (CamelNamedFlags *named_flags)
+{
+ GPtrArray *arr = (GPtrArray *) named_flags;
+
+ g_return_if_fail (named_flags != NULL);
+
+ if (arr->len)
+ g_ptr_array_remove_range (arr, 0, arr->len);
+}
+
+/**
+ * camel_named_flags_get_length:
+ * @named_flags: (nullable): a #CamelNamedFlags
+ *
+ * Returns: Length of the array, aka how many named flags are stored there.
+ *
+ * Since: 3.24
+ **/
+guint
+camel_named_flags_get_length (const CamelNamedFlags *named_flags)
+{
+ const GPtrArray *arr = (const GPtrArray *) named_flags;
+
+ if (!named_flags)
+ return 0;
+
+ return arr->len;
+}
+
+/**
+ * camel_named_flags_get:
+ * @named_flags: a #CamelNamedFlags
+ * @index: an index of an element
+ *
+ * Returns: (transfer none) (nullable): Name of the flag in at the given @index,
+ * or %NULL on error.
+ *
+ * Since: 3.24
+ **/
+const gchar *
+camel_named_flags_get (const CamelNamedFlags *named_flags,
+ guint index)
+{
+ const GPtrArray *arr = (const GPtrArray *) named_flags;
+
+ g_return_val_if_fail (named_flags != NULL, NULL);
+ g_return_val_if_fail (index < camel_named_flags_get_length (named_flags), NULL);
+
+ return g_ptr_array_index (arr, index);
+}
+
+/**
+ * camel_named_flags_equal:
+ * @named_flags_a: (nullable): the first #CamelNamedFlags
+ * @named_flags_b: (nullable): the second #CamelNamedFlags
+ *
+ * Compares content of the two #CamelNamedFlags and returns whether
+ * they equal. Note this is an expensive operation for large sets.
+ *
+ * Returns: Whether the two #CamelNamedFlags have the same content.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_named_flags_equal (const CamelNamedFlags *named_flags_a,
+ const CamelNamedFlags *named_flags_b)
+{
+ guint ii, len;
+
+ if (named_flags_a == named_flags_b)
+ return TRUE;
+
+ if (!named_flags_a || !named_flags_b)
+ return FALSE;
+
+ len = camel_named_flags_get_length (named_flags_a);
+ if (len != camel_named_flags_get_length (named_flags_b))
+ return FALSE;
+
+ for (ii = 0; ii < len; ii++) {
+ if (!camel_named_flags_contains (named_flags_a, camel_named_flags_get (named_flags_b, ii)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/camel/camel-named-flags.h b/src/camel/camel-named-flags.h
new file mode 100644
index 0000000..e5e7ca5
--- /dev/null
+++ b/src/camel/camel-named-flags.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_NAMED_FLAGS_H
+#define CAMEL_NAMED_FLAGS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * CamelNamedFlags:
+ *
+ * Since: 3.24
+ **/
+struct _CamelNamedFlags;
+typedef struct _CamelNamedFlags CamelNamedFlags;
+
+#define CAMEL_TYPE_NAMED_FLAGS (camel_named_flags_get_type ())
+
+GType camel_named_flags_get_type (void) G_GNUC_CONST;
+CamelNamedFlags *
+ camel_named_flags_new (void);
+CamelNamedFlags *
+ camel_named_flags_new_sized (guint reserve_size);
+CamelNamedFlags *
+ camel_named_flags_copy (const CamelNamedFlags *named_flags);
+void camel_named_flags_free (CamelNamedFlags *named_flags);
+gboolean camel_named_flags_insert (CamelNamedFlags *named_flags,
+ const gchar *name);
+gboolean camel_named_flags_remove (CamelNamedFlags *named_flags,
+ const gchar *name);
+gboolean camel_named_flags_contains (const CamelNamedFlags *named_flags,
+ const gchar *name);
+void camel_named_flags_clear (CamelNamedFlags *named_flags);
+guint camel_named_flags_get_length (const CamelNamedFlags *named_flags);
+const gchar * camel_named_flags_get (const CamelNamedFlags *named_flags,
+ guint index);
+gboolean camel_named_flags_equal (const CamelNamedFlags *named_flags_a,
+ const CamelNamedFlags *named_flags_b);
+
+G_END_DECLS
+
+#endif /* CAMEL_NAMED_FLAGS_H */
diff --git a/src/camel/camel-provider.c b/src/camel/camel-provider.c
index 45d2611..625dd10 100644
--- a/src/camel/camel-provider.c
+++ b/src/camel/camel-provider.c
@@ -138,8 +138,8 @@ provider_setup (gpointer param)
(GEqualFunc) camel_strcase_equal);
vee_provider.object_types[CAMEL_PROVIDER_STORE] = CAMEL_TYPE_VEE_STORE;
- vee_provider.url_hash = camel_url_hash;
- vee_provider.url_equal = camel_url_equal;
+ vee_provider.url_hash = (GHashFunc) camel_url_hash;
+ vee_provider.url_equal = (GEqualFunc) camel_url_equal;
provider_register_internal (&vee_provider);
return NULL;
diff --git a/src/camel/camel-sasl-gssapi.c b/src/camel/camel-sasl-gssapi.c
index 08d429d..536fea9 100644
--- a/src/camel/camel-sasl-gssapi.c
+++ b/src/camel/camel-sasl-gssapi.c
@@ -578,8 +578,8 @@ camel_sasl_gssapi_is_available (void)
/**
* camel_sasl_gssapi_override_host_and_user:
- * @override_host: Host name to use during challenge processing; can be %NULL
- * @override_user: User name to use during challenge processing; can be %NULL
+ * @override_host: (nullable): Host name to use during challenge processing; can be %NULL
+ * @override_user: (nullable): User name to use during challenge processing; can be %NULL
*
* Set host and user to use, instead of those in CamelService's settings.
* It's both or none, aka either set both, or the settings values are used.
diff --git a/src/camel/camel-sasl.c b/src/camel/camel-sasl.c
index 38a55ce..c903545 100644
--- a/src/camel/camel-sasl.c
+++ b/src/camel/camel-sasl.c
@@ -341,7 +341,7 @@ camel_sasl_init (CamelSasl *sasl)
* @mechanism: the SASL mechanism
* @service: the CamelService that will be using this SASL
*
- * Returns: a new #CamelSasl object for the given @service_name,
+ * Returns: (nullable): a new #CamelSasl object for the given @service_name,
* @mechanism, and @service, or %NULL if the mechanism is not
* supported.
**/
diff --git a/src/camel/camel-service.c b/src/camel/camel-service.c
index cc4cac9..cd6e681 100644
--- a/src/camel/camel-service.c
+++ b/src/camel/camel-service.c
@@ -35,8 +35,8 @@
#include "camel-network-service.h"
#include "camel-network-settings.h"
#include "camel-operation.h"
-#include "camel-service.h"
#include "camel-session.h"
+#include "camel-service.h"
#define d(x)
#define w(x)
@@ -1560,14 +1560,14 @@ camel_service_set_proxy_resolver (CamelService *service,
/**
* camel_service_ref_session:
- * @service: (type CamelService): a #CamelService
+ * @service: a #CamelService
*
* Returns the #CamelSession associated with the service.
*
* The returned #CamelSession is referenced for thread-safety. Unreference
* the #CamelSession with g_object_unref() when finished with it.
*
- * Returns: (transfer full): the #CamelSession
+ * Returns: (transfer full) (type CamelSession): the #CamelSession
*
* Since: 3.8
**/
diff --git a/src/camel/camel-session.c b/src/camel/camel-session.c
index 1c4fcc5..c7d76b9 100644
--- a/src/camel/camel-session.c
+++ b/src/camel/camel-session.c
@@ -704,7 +704,7 @@ camel_session_class_init (CamelSessionClass *class)
NULL, NULL, NULL,
G_TYPE_NONE, 2,
G_TYPE_CANCELLABLE,
- G_TYPE_POINTER);
+ G_TYPE_ERROR);
/**
* CamelSession::user-alert:
diff --git a/src/camel/camel-sexp.h b/src/camel/camel-sexp.h
index e0d824a..d4d9aa7 100644
--- a/src/camel/camel-sexp.h
+++ b/src/camel/camel-sexp.h
@@ -91,6 +91,7 @@ struct _CamelSExpResult {
/**
* CamelSExpFunc:
+ * @argv: (inout) (array length=argc):
*
* Since: 3.4
**/
@@ -98,17 +99,18 @@ typedef CamelSExpResult *
(*CamelSExpFunc) (CamelSExp *sexp,
gint argc,
CamelSExpResult **argv,
- gpointer data);
+ gpointer user_data);
/**
* CamelSExpIFunc:
+ * @argv: (inout) (array length=argc):
*
* Since: 3.4
**/
typedef CamelSExpResult *
(*CamelSExpIFunc) (CamelSExp *sexp, gint argc,
CamelSExpTerm **argv,
- gpointer data);
+ gpointer user_data);
/**
* CamelSExpTermType:
diff --git a/src/camel/camel-store-summary.c b/src/camel/camel-store-summary.c
index 23527bc..f43e6f8 100644
--- a/src/camel/camel-store-summary.c
+++ b/src/camel/camel-store-summary.c
@@ -31,8 +31,8 @@
#include <glib/gstdio.h>
#include "camel-file-utils.h"
-#include "camel-store-summary.h"
#include "camel-folder-summary.h"
+#include "camel-store-summary.h"
#include "camel-url.h"
#include "camel-win32.h"
diff --git a/src/camel/camel-store-summary.h b/src/camel/camel-store-summary.h
index 68e1557..d46fa80 100644
--- a/src/camel/camel-store-summary.h
+++ b/src/camel/camel-store-summary.h
@@ -175,10 +175,10 @@ const gchar * camel_store_info_name (CamelStoreSummary *summary,
gboolean camel_store_summary_connect_folder_summary
(CamelStoreSummary *summary,
const gchar *path,
- struct _CamelFolderSummary *folder_summary);
+ CamelFolderSummary *folder_summary);
gboolean camel_store_summary_disconnect_folder_summary
(CamelStoreSummary *summary,
- struct _CamelFolderSummary *folder_summary);
+ CamelFolderSummary *folder_summary);
G_END_DECLS
diff --git a/src/camel/camel-store.c b/src/camel/camel-store.c
index 4d4f112..7325343 100644
--- a/src/camel/camel-store.c
+++ b/src/camel/camel-store.c
@@ -606,7 +606,7 @@ camel_store_class_init (CamelStoreClass *class)
G_STRUCT_OFFSET (CamelStoreClass, folder_created),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ CAMEL_TYPE_FOLDER_INFO);
signals[FOLDER_DELETED] = g_signal_new (
"folder-deleted",
@@ -615,7 +615,7 @@ camel_store_class_init (CamelStoreClass *class)
G_STRUCT_OFFSET (CamelStoreClass, folder_deleted),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ CAMEL_TYPE_FOLDER_INFO);
/**
* CamelStore::folder-info-stale:
@@ -660,7 +660,7 @@ camel_store_class_init (CamelStoreClass *class)
NULL, NULL, NULL,
G_TYPE_NONE, 2,
G_TYPE_STRING,
- G_TYPE_POINTER);
+ CAMEL_TYPE_FOLDER_INFO);
}
static void
diff --git a/src/camel/camel-store.h b/src/camel/camel-store.h
index 19d930e..c0690cd 100644
--- a/src/camel/camel-store.h
+++ b/src/camel/camel-store.h
@@ -53,6 +53,14 @@
(G_TYPE_INSTANCE_GET_CLASS \
((obj), CAMEL_TYPE_STORE, CamelStoreClass))
+#define CAMEL_TYPE_FOLDER_INFO \
+ (camel_folder_info_get_type ())
+#define CAMEL_FOLDER_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_FOLDER_INFO, CamelFolderInfo))
+#define CAMEL_IS_FOLDER_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_FOLDER_INFO))
/**
* CAMEL_STORE_ERROR:
*
diff --git a/src/camel/camel-stream-buffer.c b/src/camel/camel-stream-buffer.c
index 7ad8c62..c490b52 100644
--- a/src/camel/camel-stream-buffer.c
+++ b/src/camel/camel-stream-buffer.c
@@ -400,7 +400,7 @@ camel_stream_buffer_new (CamelStream *stream,
/**
* camel_stream_buffer_gets:
* @sbf: a #CamelStreamBuffer object
- * @buf: (out) (array): Memory to write the string to.
+ * @buf: (array length=max) (type gchar): Memory to write the string to.
* @max: Maxmimum number of characters to store.
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
diff --git a/src/camel/camel-stream.c b/src/camel/camel-stream.c
index 3841819..8204b0e 100644
--- a/src/camel/camel-stream.c
+++ b/src/camel/camel-stream.c
@@ -479,12 +479,12 @@ camel_stream_set_base_stream (CamelStream *stream,
/**
* camel_stream_read:
* @stream: a #CamelStream object.
- * @buffer: output buffer
+ * @buffer: (array length=n) (type gchar): output buffer
* @n: max number of bytes to read.
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Attempts to read up to @len bytes from @stream into @buf.
+ * Attempts to read up to @n bytes from @stream into @buffer.
*
* Returns: the number of bytes actually read, or %-1 on error and set
* errno.
@@ -514,7 +514,7 @@ camel_stream_read (CamelStream *stream,
/**
* camel_stream_write:
* @stream: a #CamelStream object
- * @buffer: buffer to write.
+ * @buffer: (array length=n) (type gchar): buffer to write.
* @n: number of bytes to write
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
diff --git a/src/camel/camel-subscribable.c b/src/camel/camel-subscribable.c
index 3ec4f58..ebb0683 100644
--- a/src/camel/camel-subscribable.c
+++ b/src/camel/camel-subscribable.c
@@ -157,7 +157,7 @@ camel_subscribable_default_init (CamelSubscribableInterface *iface)
folder_subscribed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ CAMEL_TYPE_FOLDER_INFO);
signals[FOLDER_UNSUBSCRIBED] = g_signal_new (
"folder-unsubscribed",
@@ -168,7 +168,7 @@ camel_subscribable_default_init (CamelSubscribableInterface *iface)
folder_unsubscribed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ CAMEL_TYPE_FOLDER_INFO);
}
/**
diff --git a/src/camel/camel-trie.c b/src/camel/camel-trie.c
index 4d9ea9f..641643f 100644
--- a/src/camel/camel-trie.c
+++ b/src/camel/camel-trie.c
@@ -331,13 +331,13 @@ camel_trie_add (CamelTrie *trie,
/**
* camel_trie_search:
* @trie: The #CamelTrie to search in.
- * @buffer: The string to match against a pattern in @trie.
+ * @buffer: (array length=buflen) (type gchar): The string to match against a pattern in @trie.
* @buflen: The length of @buffer.
- * @matched_id: An integer address to store the matched pattern id in.
+ * @matched_id: (out): An integer address to store the matched pattern id in.
*
* Try to match the string @buffer with a pattern in @trie.
*
- * Returns: The matched pattern, or %NULL if no pattern is matched.
+ * Returns: (nullable): The matched pattern, or %NULL if no pattern is matched.
*
* Since: 2.24
**/
diff --git a/src/camel/camel-url-scanner.c b/src/camel/camel-url-scanner.c
index c977e14..1438d70 100644
--- a/src/camel/camel-url-scanner.c
+++ b/src/camel/camel-url-scanner.c
@@ -64,6 +64,17 @@ camel_url_scanner_add (CamelUrlScanner *scanner,
g_ptr_array_add (scanner->patterns, pattern);
}
+/**
+ * camel_url_scanner_scan:
+ * @scanner: a #CamelUrlScanner object.
+ * @in: (array length=inlen) (type gchar): the url to scan.
+ * @inlen: length of the in array.
+ * @match: the #CamelUrlMatch structure containing the criterias.
+ *
+ * Scan the @in string with the @match criterias.
+ *
+ * Returns: %TRUE if there is a result.
+ **/
gboolean
camel_url_scanner_scan (CamelUrlScanner *scanner,
const gchar *in,
diff --git a/src/camel/camel-url.c b/src/camel/camel-url.c
index b51ed09..c089b15 100644
--- a/src/camel/camel-url.c
+++ b/src/camel/camel-url.c
@@ -703,10 +703,15 @@ camel_url_decode (gchar *part)
} while (*s++);
}
+/**
+ * camel_url_hash:
+ * @u: the base URL
+ *
+ * Returns: the url hash
+ */
guint
-camel_url_hash (gconstpointer v)
+camel_url_hash (const CamelURL *u)
{
- const CamelURL *u = v;
guint hash = 0;
#define ADD_HASH(s) if (s) hash ^= g_str_hash (s);
@@ -722,7 +727,7 @@ camel_url_hash (gconstpointer v)
return hash;
}
-static gint
+static gboolean
check_equal (gchar *s1,
gchar *s2)
{
@@ -739,19 +744,24 @@ check_equal (gchar *s1,
return strcmp (s1, s2) == 0;
}
-gint
-camel_url_equal (gconstpointer v,
- gconstpointer v2)
+/**
+ * camel_url_equal:
+ * @u: the base URL
+ * @u2: the URL to compare
+ *
+ * Returns: return %TRUE if the two urls are equal
+ */
+gboolean
+camel_url_equal (const CamelURL *u,
+ const CamelURL *u2)
{
- const CamelURL *u1 = v, *u2 = v2;
-
- return check_equal (u1->protocol, u2->protocol)
- && check_equal (u1->user, u2->user)
- && check_equal (u1->authmech, u2->authmech)
- && check_equal (u1->host, u2->host)
- && check_equal (u1->path, u2->path)
- && check_equal (u1->query, u2->query)
- && u1->port == u2->port;
+ return check_equal (u->protocol, u2->protocol)
+ && check_equal (u->user, u2->user)
+ && check_equal (u->authmech, u2->authmech)
+ && check_equal (u->host, u2->host)
+ && check_equal (u->path, u2->path)
+ && check_equal (u->query, u2->query)
+ && u->port == u2->port;
}
/**
@@ -760,7 +770,7 @@ camel_url_equal (gconstpointer v,
*
* Copy a #CamelURL.
*
- * Returns: a duplicate copy of @in
+ * Returns:(transfer full): a duplicate copy of @in
**/
CamelURL *
camel_url_copy (CamelURL *in)
diff --git a/src/camel/camel-url.h b/src/camel/camel-url.h
index db3a26e..951a52a 100644
--- a/src/camel/camel-url.h
+++ b/src/camel/camel-url.h
@@ -62,9 +62,9 @@ CamelURL * camel_url_new (const gchar *url_string,
GError **error);
gchar * camel_url_to_string (CamelURL *url,
CamelURLFlags flags);
-guint camel_url_hash (gconstpointer v);
-gint camel_url_equal (gconstpointer v,
- gconstpointer v2);
+guint camel_url_hash (const CamelURL *u);
+gboolean camel_url_equal (const CamelURL *u,
+ const CamelURL *u2);
CamelURL * camel_url_copy (CamelURL *in);
void camel_url_free (CamelURL *url);
diff --git a/src/camel/camel-utils.c b/src/camel/camel-utils.c
new file mode 100644
index 0000000..b7a0f5d
--- /dev/null
+++ b/src/camel/camel-utils.c
@@ -0,0 +1,173 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "camel-utils.h"
+
+/**
+ * camel_util_bdata_get_number:
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ * @default_value: a value to return, when no data can be read
+ *
+ * Reads a numeric data from the @bdata_ptr and moves the @bdata_ptr
+ * after that number. If the number cannot be read, then the @default_value
+ * is returned instead and the @bdata_ptr is left unchanged. The number
+ * might be previously stored with the camel_util_bdata_put_number().
+ *
+ * Returns: The read number, or the @default_value, if the @bdata_ptr doesn't
+ * point to a number.
+ *
+ * Since: 3.24
+ **/
+gint64
+camel_util_bdata_get_number (/* const */ gchar **bdata_ptr,
+ gint64 default_value)
+{
+ gint64 result;
+ gchar *endptr;
+
+ g_return_val_if_fail (bdata_ptr != NULL, default_value);
+
+ if (!bdata_ptr || !*bdata_ptr || !**bdata_ptr)
+ return default_value;
+
+ if (**bdata_ptr == ' ')
+ *bdata_ptr += 1;
+
+ if (!**bdata_ptr)
+ return default_value;
+
+ endptr = *bdata_ptr;
+
+ result = g_ascii_strtoll (*bdata_ptr, &endptr, 10);
+
+ if (endptr == *bdata_ptr)
+ result = default_value;
+ else
+ *bdata_ptr = endptr;
+
+ return result;
+}
+
+/**
+ * camel_util_bdata_put_number:
+ * @bdata_str: a #GString to store a backend specific data (bdata)
+ * @value: a value to store
+ *
+ * Puts the number @value at the end of the @bdata_str. In case the @bdata_str
+ * is not empty a space is added before the numeric @value. The stored value
+ * can be read back with the camel_util_bdata_get_number().
+ *
+ * Since: 3.24
+ **/
+void
+camel_util_bdata_put_number (GString *bdata_str,
+ gint64 value)
+{
+ g_return_if_fail (bdata_str != NULL);
+
+ if (bdata_str->len && bdata_str->str[bdata_str->len - 1] != ' ')
+ g_string_append_c (bdata_str, ' ');
+
+ g_string_append_printf (bdata_str, "%" G_GINT64_FORMAT, value);
+}
+
+/**
+ * camel_util_bdata_get_string:
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ * @default_value: a value to return, when no data can be read
+ *
+ * Reads a string data from the @bdata_ptr and moves the @bdata_ptr
+ * after that string. If the string cannot be read, then the @default_value
+ * is returned instead and the @bdata_ptr is left unchanged. The string
+ * might be previously stored with the camel_util_bdata_put_string().
+ *
+ * Returns: (transfer full): Newly allocated string, which was read, or
+ * dupped the @default_value, if the @bdata_ptr doesn't point to a string.
+ * Free returned pointer with g_free() when done with it.
+ *
+ * Since: 3.24
+ **/
+gchar *
+camel_util_bdata_get_string (/* const */ gchar **bdata_ptr,
+ const gchar *default_value)
+{
+ gint64 length, has_length;
+ gchar *orig_bdata_ptr;
+ gchar *result;
+
+ g_return_val_if_fail (bdata_ptr != NULL, NULL);
+
+ orig_bdata_ptr = *bdata_ptr;
+
+ length = camel_util_bdata_get_number (bdata_ptr, -1);
+
+ /* might be a '-' sign */
+ if (*bdata_ptr && **bdata_ptr == '-')
+ *bdata_ptr += 1;
+ else
+ length = -1;
+
+ if (length < 0 || !*bdata_ptr || !**bdata_ptr || *bdata_ptr == orig_bdata_ptr) {
+ *bdata_ptr = orig_bdata_ptr;
+
+ return g_strdup (default_value);
+ }
+
+ if (!length)
+ return g_strdup ("");
+
+ has_length = strlen (*bdata_ptr);
+ if (has_length < length)
+ length = has_length;
+
+ result = g_strndup (*bdata_ptr, length);
+ *bdata_ptr += length;
+
+ return result;
+}
+
+/**
+ * camel_util_bdata_put_string:
+ * @bdata_str: a #GString to store a backend specific data (bdata)
+ * @value: a value to store
+ *
+ * Puts the string @value at the end of the @bdata_str. In case the @bdata_str
+ * is not empty a space is added before the string @value. The stored value
+ * can be read back with the camel_util_bdata_get_string().
+ *
+ * The strings are encoded as "length-value", quotes for clarity only.
+ *
+ * Since: 3.24
+ **/
+void
+camel_util_bdata_put_string (GString *bdata_str,
+ const gchar *value)
+{
+ g_return_if_fail (bdata_str != NULL);
+ g_return_if_fail (value != NULL);
+
+ camel_util_bdata_put_number (bdata_str, strlen (value));
+
+ g_string_append_printf (bdata_str, "-%s", value);
+}
diff --git a/src/camel/camel-utils.h b/src/camel/camel-utils.h
new file mode 100644
index 0000000..25c2864
--- /dev/null
+++ b/src/camel/camel-utils.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_UTILS_H
+#define CAMEL_UTILS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+gint64 camel_util_bdata_get_number (/* const */ gchar **bdata_ptr,
+ gint64 default_value);
+void camel_util_bdata_put_number (GString *bdata_str,
+ gint64 value);
+gchar * camel_util_bdata_get_string (/* const */ gchar **bdata_ptr,
+ const gchar *default_value);
+void camel_util_bdata_put_string (GString *bdata_str,
+ const gchar *value);
+
+G_END_DECLS
+
+#endif /* CAMEL_UTILS_H */
diff --git a/src/camel/camel-vee-data-cache.h b/src/camel/camel-vee-data-cache.h
index 9c42cc4..3228597 100644
--- a/src/camel/camel-vee-data-cache.h
+++ b/src/camel/camel-vee-data-cache.h
@@ -199,9 +199,7 @@ CamelVeeMessageInfoData *
void camel_vee_data_cache_foreach_message_info_data
(CamelVeeDataCache *data_cache,
CamelFolder *fromfolder,
- void (* func) (CamelVeeMessageInfoData *mi_data,
- CamelFolder *subfolder,
- gpointer user_data),
+ CamelForeachInfoData func,
gpointer user_data);
void camel_vee_data_cache_remove_message_info_data
(CamelVeeDataCache *data_cache,
diff --git a/src/camel/camel-vee-folder.c b/src/camel/camel-vee-folder.c
index a6355ad..d82b276 100644
--- a/src/camel/camel-vee-folder.c
+++ b/src/camel/camel-vee-folder.c
@@ -145,7 +145,7 @@ vee_folder_note_added_uid (CamelVeeFolder *vfolder,
if (vmi) {
if (changes)
camel_folder_change_info_add_uid (changes, vuid);
- camel_message_info_unref (vmi);
+ g_clear_object (&vmi);
if (vfolder->priv->parent_vee_store)
camel_vee_store_note_vuid_used (vfolder->priv->parent_vee_store,
added_mi_data, vfolder);
@@ -905,9 +905,9 @@ vee_folder_get_message_sync (CamelFolder *folder,
mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, uid);
if (mi) {
msg = camel_folder_get_message_sync (
- camel_folder_summary_get_folder (mi->orig_summary), camel_message_info_get_uid (mi) +
8,
+ camel_vee_message_info_get_original_folder (mi), camel_message_info_get_uid
(CAMEL_MESSAGE_INFO (mi)) + 8,
cancellable, error);
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
} else {
g_set_error (
error, CAMEL_FOLDER_ERROR,
@@ -1531,6 +1531,9 @@ camel_vee_folder_set_folders (CamelVeeFolder *vf,
/**
* camel_vee_folder_add_vuid:
+ * @vfolder:
+ * @mi_data: (type CamelVeeMessageInfoData):
+ * @changes:
*
* FIXME Document me!
*
@@ -1582,6 +1585,9 @@ camel_vee_folder_add_vuid (CamelVeeFolder *vfolder,
/**
* camel_vee_folder_remove_vuid:
+ * @vfolder:
+ * @mi_data: (type CamelVeeMessageInfoData):
+ * @changes:
*
* FIXME Document me!
*
@@ -1653,25 +1659,29 @@ camel_vee_folder_get_location (CamelVeeFolder *vf,
gchar **realuid)
{
CamelFolder *folder;
+ const gchar *uid;
g_return_val_if_fail (CAMEL_IS_VEE_FOLDER (vf), NULL);
g_return_val_if_fail (vinfo != NULL, NULL);
- folder = camel_folder_summary_get_folder (vinfo->orig_summary);
+ folder = camel_vee_message_info_get_original_folder (vinfo);
+ uid = camel_message_info_get_uid (CAMEL_MESSAGE_INFO (vinfo));
+
+ g_return_val_if_fail (uid != NULL && strlen (uid) > 8, NULL);
/* locking? yes? no? although the vfolderinfo is valid when obtained
* the folder in it might not necessarily be so ...? */
if (CAMEL_IS_VEE_FOLDER (folder)) {
CamelFolder *res;
- const CamelVeeMessageInfo *vfinfo;
+ CamelMessageInfo *vfinfo;
- vfinfo = (CamelVeeMessageInfo *) camel_folder_get_message_info (folder,
camel_message_info_get_uid (vinfo) + 8);
- res = camel_vee_folder_get_location ((CamelVeeFolder *) folder, vfinfo, realuid);
- camel_message_info_unref ((CamelMessageInfo *) vfinfo);
+ vfinfo = camel_folder_get_message_info (folder, uid + 8);
+ res = camel_vee_folder_get_location ((CamelVeeFolder *) folder, CAMEL_VEE_MESSAGE_INFO
(vfinfo), realuid);
+ g_clear_object (&vfinfo);
return res;
} else {
if (realuid)
- *realuid = g_strdup (camel_message_info_get_uid (vinfo)+8);
+ *realuid = g_strdup (uid + 8);
return folder;
}
diff --git a/src/camel/camel-vee-folder.h b/src/camel/camel-vee-folder.h
index c1854bc..ebb43b7 100644
--- a/src/camel/camel-vee-folder.h
+++ b/src/camel/camel-vee-folder.h
@@ -95,7 +95,7 @@ void camel_vee_folder_construct (CamelVeeFolder *vf,
guint32 flags);
CamelFolder * camel_vee_folder_get_location (CamelVeeFolder *vf,
- const struct _CamelVeeMessageInfo *vinfo,
+ const CamelVeeMessageInfo *vinfo,
gchar **realuid);
CamelFolder * camel_vee_folder_get_vee_uid_folder (CamelVeeFolder *vf,
const gchar *vee_message_uid);
diff --git a/src/camel/camel-vee-message-info.c b/src/camel/camel-vee-message-info.c
new file mode 100644
index 0000000..b0b3e0d
--- /dev/null
+++ b/src/camel/camel-vee-message-info.c
@@ -0,0 +1,532 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "camel-folder.h"
+#include "camel-folder-summary.h"
+#include "camel-message-info.h"
+#include "camel-string-utils.h"
+#include "camel-vee-folder.h"
+#include "camel-vee-summary.h"
+#include "camel-vtrash-folder.h"
+
+#include "camel-vee-message-info.h"
+
+struct _CamelVeeMessageInfoPrivate {
+ CamelFolderSummary *orig_summary;
+};
+
+G_DEFINE_TYPE (CamelVeeMessageInfo, camel_vee_message_info, CAMEL_TYPE_MESSAGE_INFO)
+
+static CamelMessageInfo *
+vee_message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfo *result;
+
+ g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (mi), NULL);
+
+ result = CAMEL_MESSAGE_INFO_CLASS (camel_vee_message_info_parent_class)->clone (mi, assign_summary);
+ if (!result)
+ return NULL;
+
+ if (CAMEL_IS_VEE_MESSAGE_INFO (result)) {
+ CamelVeeMessageInfo *vmi, *vmi_result;
+
+ vmi = CAMEL_VEE_MESSAGE_INFO (mi);
+ vmi_result = CAMEL_VEE_MESSAGE_INFO (result);
+
+ if (vmi->priv->orig_summary)
+ vmi_result->priv->orig_summary = g_object_ref (vmi->priv->orig_summary);
+ }
+
+ return result;
+}
+
+static void
+vee_message_info_notify_mi_changed (CamelFolder *folder,
+ const gchar *mi_uid)
+{
+ CamelFolderChangeInfo *changes;
+
+ g_return_if_fail (CAMEL_IS_VEE_FOLDER (folder));
+ g_return_if_fail (mi_uid != NULL);
+
+ changes = camel_folder_change_info_new ();
+ camel_folder_change_info_change_uid (changes, mi_uid);
+ camel_folder_changed (folder, changes);
+ camel_folder_change_info_free (changes);
+}
+
+#define vee_call_from_parent_mi(_err_ret, _ret_type, _call_what, _call_args, _is_set) G_STMT_START { \
+ CamelVeeMessageInfo *vmi; \
+ CamelMessageInfo *orig_mi; \
+ CamelFolderSummary *this_summary, *sub_summary; \
+ CamelFolder *this_folder, *sub_folder; \
+ gboolean ignore_changes; \
+ const gchar *uid; \
+ _ret_type result; \
+ \
+ g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (mi), _err_ret); \
+ \
+ vmi = CAMEL_VEE_MESSAGE_INFO (mi); \
+ g_return_val_if_fail (vmi->priv->orig_summary != NULL, _err_ret); \
+ \
+ uid = camel_message_info_pooldup_uid (mi); \
+ g_return_val_if_fail (uid != NULL, _err_ret); \
+ \
+ if (!uid[0] || !uid[1] || !uid[2] || !uid[3] || !uid[4] || \
+ !uid[5] || !uid[6] || !uid[7] || !uid[8]) { \
+ camel_pstring_free (uid); \
+ g_warn_if_reached (); \
+ return _err_ret; \
+ } \
+ \
+ orig_mi = (CamelMessageInfo *) camel_folder_summary_get (vmi->priv->orig_summary, uid + 8);
\
+ if (!orig_mi) { \
+ g_warning ("%s: Failed to get orig uid '%s'\n", G_STRFUNC, uid); \
+ camel_pstring_free (uid); \
+ return _err_ret; \
+ } \
+ \
+ this_summary = camel_message_info_ref_summary (mi); \
+ this_folder = this_summary ? camel_folder_summary_get_folder (this_summary) : NULL; \
+ sub_summary = camel_message_info_ref_summary (orig_mi); \
+ sub_folder = sub_summary ? camel_folder_summary_get_folder (sub_summary) : NULL; \
+ \
+ ignore_changes = _is_set && !CAMEL_IS_VTRASH_FOLDER (this_folder); \
+ \
+ /* ignore changes done in the folder itself, \
+ * unless it's a vTrash or vJunk folder */ \
+ if (ignore_changes) \
+ camel_vee_folder_ignore_next_changed_event (CAMEL_VEE_FOLDER (this_folder),
sub_folder); \
+ \
+ result = _call_what _call_args; \
+ \
+ if (ignore_changes) { \
+ if (result) \
+ vee_message_info_notify_mi_changed (this_folder, uid); \
+ else \
+ camel_vee_folder_remove_from_ignore_changed_event ( \
+ CAMEL_VEE_FOLDER (this_folder), sub_folder); \
+ } \
+ \
+ g_clear_object (&this_summary); \
+ g_clear_object (&sub_summary); \
+ g_clear_object (&orig_mi); \
+ camel_pstring_free (uid); \
+ \
+ return result; \
+ } G_STMT_END
+
+static guint32
+vee_message_info_get_flags (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (0, guint32, camel_message_info_get_flags, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_flags_real (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_flags, (orig_mi, mask, set), TRUE);
+}
+
+static gboolean
+vee_message_info_set_flags (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set)
+{
+ gboolean result;
+
+ result = vee_message_info_set_flags_real (mi, mask, set);
+
+ if (result) {
+ CamelFolderSummary *summary;
+
+ summary = camel_message_info_ref_summary (mi);
+ if (summary)
+ camel_folder_summary_replace_flags (summary, mi);
+ g_clear_object (&summary);
+ }
+
+ return result;
+}
+
+static gboolean
+vee_message_info_get_user_flag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_get_user_flag, (orig_mi, name), FALSE);
+}
+
+static gboolean
+vee_message_info_set_user_flag (CamelMessageInfo *mi,
+ const gchar *name,
+ gboolean state)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_user_flag, (orig_mi, name, state),
TRUE);
+}
+
+static const CamelNamedFlags *
+vee_message_info_get_user_flags (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const CamelNamedFlags *, camel_message_info_get_user_flags, (orig_mi),
FALSE);
+}
+
+static CamelNamedFlags *
+vee_message_info_dup_user_flags (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, CamelNamedFlags *, camel_message_info_dup_user_flags, (orig_mi),
FALSE);
+}
+
+static gboolean
+vee_message_info_take_user_flags (CamelMessageInfo *mi,
+ CamelNamedFlags *user_flags)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_take_user_flags, (orig_mi, user_flags),
TRUE);
+}
+
+static const gchar *
+vee_message_info_get_user_tag (const CamelMessageInfo *mi,
+ const gchar *name)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_user_tag, (orig_mi, name),
FALSE);
+}
+
+static gboolean
+vee_message_info_set_user_tag (CamelMessageInfo *mi,
+ const gchar *name,
+ const gchar *value)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_user_tag, (orig_mi, name, value),
TRUE);
+}
+
+static CamelNameValueArray *
+vee_message_info_dup_user_tags (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, CamelNameValueArray *, camel_message_info_dup_user_tags, (orig_mi),
FALSE);
+}
+
+static const CamelNameValueArray *
+vee_message_info_get_user_tags (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const CamelNameValueArray *, camel_message_info_get_user_tags,
(orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_take_user_tags (CamelMessageInfo *mi,
+ CamelNameValueArray *user_tags)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_take_user_tags, (orig_mi, user_tags),
TRUE);
+}
+
+static const gchar *
+vee_message_info_get_subject (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_subject, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_subject (CamelMessageInfo *mi,
+ const gchar *subject)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_subject, (orig_mi, subject), TRUE);
+}
+
+static const gchar *
+vee_message_info_get_from (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_from, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_from (CamelMessageInfo *mi,
+ const gchar *from)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_from, (orig_mi, from), TRUE);
+}
+
+static const gchar *
+vee_message_info_get_to (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_to, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_to (CamelMessageInfo *mi,
+ const gchar *to)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_to, (orig_mi, to), TRUE);
+}
+
+static const gchar *
+vee_message_info_get_cc (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_cc, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_cc (CamelMessageInfo *mi,
+ const gchar *cc)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_cc, (orig_mi, cc), TRUE);
+}
+
+static const gchar *
+vee_message_info_get_mlist (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const gchar *, camel_message_info_get_mlist, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_mlist (CamelMessageInfo *mi,
+ const gchar *mlist)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_mlist, (orig_mi, mlist), TRUE);
+}
+
+static guint32
+vee_message_info_get_size (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (0, guint32, camel_message_info_get_size, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_size (CamelMessageInfo *mi,
+ guint32 size)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_size, (orig_mi, size), TRUE);
+}
+
+static gint64
+vee_message_info_get_date_sent (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (0, gint64, camel_message_info_get_date_sent, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_date_sent (CamelMessageInfo *mi,
+ gint64 date_sent)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_date_sent, (orig_mi, date_sent),
TRUE);
+}
+
+static gint64
+vee_message_info_get_date_received (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (0, gint64, camel_message_info_get_date_received, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_date_received (CamelMessageInfo *mi,
+ gint64 date_received)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_date_received, (orig_mi,
date_received), TRUE);
+}
+
+static guint64
+vee_message_info_get_message_id (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (0, guint64, camel_message_info_get_message_id, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_set_message_id (CamelMessageInfo *mi,
+ guint64 message_id)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_set_message_id, (orig_mi, message_id),
TRUE);
+}
+
+static const GArray *
+vee_message_info_get_references (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const GArray *, camel_message_info_get_references, (orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_take_references (CamelMessageInfo *mi,
+ GArray *references)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_take_references, (orig_mi, references),
TRUE);
+}
+
+static const CamelNameValueArray *
+vee_message_info_get_headers (const CamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const CamelNameValueArray *, camel_message_info_get_headers,
(orig_mi), FALSE);
+}
+
+static gboolean
+vee_message_info_take_headers (CamelMessageInfo *mi,
+ CamelNameValueArray *headers)
+{
+ vee_call_from_parent_mi (FALSE, gboolean, camel_message_info_take_headers, (orig_mi, headers), TRUE);
+}
+
+#undef vee_call_from_parent_mi
+
+static void
+vee_message_info_dispose (GObject *object)
+{
+ CamelVeeMessageInfo *vmi = CAMEL_VEE_MESSAGE_INFO (object);
+
+ g_clear_object (&vmi->priv->orig_summary);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_vee_message_info_parent_class)->dispose (object);
+}
+
+static void
+camel_vee_message_info_class_init (CamelVeeMessageInfoClass *class)
+{
+ CamelMessageInfoClass *mi_class;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelVeeMessageInfoPrivate));
+
+ mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
+ mi_class->clone = vee_message_info_clone;
+ mi_class->get_flags = vee_message_info_get_flags;
+ mi_class->set_flags = vee_message_info_set_flags;
+ mi_class->get_user_flag = vee_message_info_get_user_flag;
+ mi_class->set_user_flag = vee_message_info_set_user_flag;
+ mi_class->get_user_flags = vee_message_info_get_user_flags;
+ mi_class->dup_user_flags = vee_message_info_dup_user_flags;
+ mi_class->take_user_flags = vee_message_info_take_user_flags;
+ mi_class->get_user_tag = vee_message_info_get_user_tag;
+ mi_class->set_user_tag = vee_message_info_set_user_tag;
+ mi_class->get_user_tags = vee_message_info_get_user_tags;
+ mi_class->dup_user_tags = vee_message_info_dup_user_tags;
+ mi_class->take_user_tags = vee_message_info_take_user_tags;
+ mi_class->get_subject = vee_message_info_get_subject;
+ mi_class->set_subject = vee_message_info_set_subject;
+ mi_class->get_from = vee_message_info_get_from;
+ mi_class->set_from = vee_message_info_set_from;
+ mi_class->get_to = vee_message_info_get_to;
+ mi_class->set_to = vee_message_info_set_to;
+ mi_class->get_cc = vee_message_info_get_cc;
+ mi_class->set_cc = vee_message_info_set_cc;
+ mi_class->get_mlist = vee_message_info_get_mlist;
+ mi_class->set_mlist = vee_message_info_set_mlist;
+ mi_class->get_size = vee_message_info_get_size;
+ mi_class->set_size = vee_message_info_set_size;
+ mi_class->get_date_sent = vee_message_info_get_date_sent;
+ mi_class->set_date_sent = vee_message_info_set_date_sent;
+ mi_class->get_date_received = vee_message_info_get_date_received;
+ mi_class->set_date_received = vee_message_info_set_date_received;
+ mi_class->get_message_id = vee_message_info_get_message_id;
+ mi_class->set_message_id = vee_message_info_set_message_id;
+ mi_class->get_references = vee_message_info_get_references;
+ mi_class->take_references = vee_message_info_take_references;
+ mi_class->get_headers = vee_message_info_get_headers;
+ mi_class->take_headers = vee_message_info_take_headers;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = vee_message_info_dispose;
+}
+
+static void
+camel_vee_message_info_init (CamelVeeMessageInfo *vmi)
+{
+ vmi->priv = G_TYPE_INSTANCE_GET_PRIVATE (vmi, CAMEL_TYPE_VEE_MESSAGE_INFO,
CamelVeeMessageInfoPrivate);
+}
+
+/**
+ * camel_vee_message_info_new:
+ * @summary: a #CamelVeeSummary, the "owner" of the created message info
+ * @original_summary: an original #CamelFolderSummary to reference to
+ * @vuid: what UID to set on the resulting message info
+ *
+ * Creates a new instance of #CamelVeeMessageInfo which references
+ * a message from the @original_summary internally.
+ *
+ * The @vuid should be encoded in a way which the vFolder understands,
+ * which is like the one returned by camel_vee_message_info_data_get_vee_message_uid().
+ *
+ * Returns: (transfer full): a newly created #CamelVeeMessageInfo
+ * which references @orig_mi. Free with g_object_unref() when done
+ * with it.
+ *
+ * Since: 3.24
+ **/
+CamelMessageInfo *
+camel_vee_message_info_new (CamelFolderSummary *summary,
+ CamelFolderSummary *original_summary,
+ const gchar *vuid)
+{
+ CamelMessageInfo *mi;
+ CamelVeeMessageInfo *vmi;
+
+ g_return_val_if_fail (CAMEL_IS_VEE_SUMMARY (summary), NULL);
+ g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (original_summary), NULL);
+ g_return_val_if_fail (vuid != NULL, NULL);
+ g_return_val_if_fail (vuid[0] && vuid[1] && vuid[2] && vuid[3] && vuid[4] && vuid[5] && vuid[6] &&
vuid[7] && vuid[8], NULL);
+
+ mi = camel_message_info_new (summary);
+ g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (mi), NULL);
+
+ vmi = CAMEL_VEE_MESSAGE_INFO (mi);
+ vmi->priv->orig_summary = g_object_ref (original_summary);
+
+ camel_message_info_set_uid (mi, vuid);
+
+ return mi;
+}
+
+/**
+ * camel_vee_message_info_get_original_summary:
+ * @vmi: a #CamelVeeMessageInfo
+ *
+ * Returns: (transfer none): A #CamelFolderSummary of the original
+ * message info, which this @vmi is proxying.
+ *
+ * Since: 3.24
+ **/
+CamelFolderSummary *
+camel_vee_message_info_get_original_summary (const CamelVeeMessageInfo *vmi)
+{
+ g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (vmi), NULL);
+
+ return vmi->priv->orig_summary;
+}
+
+/**
+ * camel_vee_message_info_get_original_folder:
+ * @vmi: a #CamelVeeMessageInfo
+ *
+ * Returns: (transfer none): A #CamelFolder of the original
+ * message info, which this @vmi is proxying.
+ *
+ * Since: 3.24
+ **/
+CamelFolder *
+camel_vee_message_info_get_original_folder (const CamelVeeMessageInfo *vmi)
+{
+ g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (vmi), NULL);
+
+ if (!vmi->priv->orig_summary)
+ return NULL;
+
+ return camel_folder_summary_get_folder (vmi->priv->orig_summary);
+}
diff --git a/src/camel/camel-vee-message-info.h b/src/camel/camel-vee-message-info.h
new file mode 100644
index 0000000..fa79459
--- /dev/null
+++ b/src/camel/camel-vee-message-info.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_VEE_MESSAGE_INFO_H
+#define CAMEL_VEE_MESSAGE_INFO_H
+
+#include <glib-object.h>
+
+#include <camel/camel-message-info.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_VEE_MESSAGE_INFO \
+ (camel_vee_message_info_get_type ())
+#define CAMEL_VEE_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_VEE_MESSAGE_INFO, CamelVeeMessageInfo))
+#define CAMEL_VEE_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_VEE_MESSAGE_INFO, CamelVeeMessageInfoClass))
+#define CAMEL_IS_VEE_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_VEE_MESSAGE_INFO))
+#define CAMEL_IS_VEE_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_VEE_MESSAGE_INFO))
+#define CAMEL_VEE_MESSAGE_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_VEE_MESSAGE_INFO, CamelVeeMessageInfoClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelVeeMessageInfo CamelVeeMessageInfo;
+typedef struct _CamelVeeMessageInfoClass CamelVeeMessageInfoClass;
+typedef struct _CamelVeeMessageInfoPrivate CamelVeeMessageInfoPrivate;
+
+struct _CamelVeeMessageInfo {
+ CamelMessageInfo parent;
+ CamelVeeMessageInfoPrivate *priv;
+};
+
+struct _CamelVeeMessageInfoClass {
+ CamelMessageInfoClass parent_class;
+};
+
+GType camel_vee_message_info_get_type (void);
+CamelMessageInfo *
+ camel_vee_message_info_new (CamelFolderSummary *summary,
+ CamelFolderSummary *original_summary,
+ const gchar *vuid);
+CamelFolderSummary *
+ camel_vee_message_info_get_original_summary
+ (const CamelVeeMessageInfo *vmi);
+CamelFolder *
+ camel_vee_message_info_get_original_folder
+ (const CamelVeeMessageInfo *vmi);
+
+G_END_DECLS
+
+#endif /* CAMEL_VEE_MESSAGE_INFO_H */
diff --git a/src/camel/camel-vee-store.c b/src/camel/camel-vee-store.c
index 393207c..8e789a5 100644
--- a/src/camel/camel-vee-store.c
+++ b/src/camel/camel-vee-store.c
@@ -577,7 +577,7 @@ camel_vee_store_new (void)
*
* FIXME Document me!
*
- * Returns: (transfer none):
+ * Returns: (type CamelVeeFolder) (transfer none):
*
* Since: 3.6
**/
@@ -686,6 +686,9 @@ add_to_unmatched_folder_cb (CamelVeeMessageInfoData *mi_data,
/**
* camel_vee_store_note_subfolder_used:
+ * @vstore:
+ * @subfolder:
+ * @used_by: (type CamelVeeFolder):
*
* FIXME Document me!
*
@@ -765,6 +768,9 @@ remove_vuid_count_record_cb (CamelVeeMessageInfoData *mi_data,
/**
* camel_vee_store_note_subfolder_unused:
+ * @vstore:
+ * @subfolder:
+ * @unused_by: (type CamelVeeFolder):
*
* FIXME Document me!
*
@@ -814,6 +820,9 @@ camel_vee_store_note_subfolder_unused (CamelVeeStore *vstore,
/**
* camel_vee_store_note_vuid_used:
+ * @vstore:
+ * @mi_data:
+ * @used_by: (type CamelVeeFolder):
*
* FIXME Document me!
*
@@ -871,6 +880,9 @@ camel_vee_store_note_vuid_used (CamelVeeStore *vstore,
/**
* camel_vee_store_note_vuid_unused:
+ * @vstore:
+ * @mi_data:
+ * @unused_by: (type CamelVeeFolder):
*
* FIXME Document me!
*
diff --git a/src/camel/camel-vee-summary.c b/src/camel/camel-vee-summary.c
index ddd527d..e1ac50f 100644
--- a/src/camel/camel-vee-summary.c
+++ b/src/camel/camel-vee-summary.c
@@ -29,12 +29,14 @@
#include "camel-debug.h"
#include "camel-folder.h"
#include "camel-store.h"
-#include "camel-vee-summary.h"
#include "camel-vee-folder.h"
+#include "camel-vee-message-info.h"
#include "camel-vee-store.h"
#include "camel-vtrash-folder.h"
#include "camel-string-utils.h"
+#include "camel-vee-summary.h"
+
#define d(x)
#define CAMEL_VEE_SUMMARY_GET_PRIVATE(obj) \
@@ -48,240 +50,6 @@ struct _CamelVeeSummaryPrivate {
G_DEFINE_TYPE (CamelVeeSummary, camel_vee_summary, CAMEL_TYPE_FOLDER_SUMMARY)
-static void
-vee_message_info_free (CamelFolderSummary *s,
- CamelMessageInfo *info)
-{
- CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) info;
-
- g_object_unref (mi->orig_summary);
-
- CAMEL_FOLDER_SUMMARY_CLASS (camel_vee_summary_parent_class)->message_info_free (s, info);
-}
-
-static CamelMessageInfo *
-vee_message_info_clone (CamelFolderSummary *s,
- const CamelMessageInfo *mi)
-{
- CamelVeeMessageInfo *to;
- const CamelVeeMessageInfo *from = (const CamelVeeMessageInfo *) mi;
-
- to = (CamelVeeMessageInfo *) camel_message_info_new (s);
-
- to->orig_summary = g_object_ref (from->orig_summary);
- to->info.summary = s;
- to->info.uid = camel_pstring_strdup (from->info.uid);
-
- return (CamelMessageInfo *) to;
-}
-
-#define HANDLE_NULL_INFO(value) if (!rmi) { d(g_warning (G_STRLOC ": real info is NULL for %s,
safeguarding\n", mi->uid)); return value; }
-
-static gconstpointer
-vee_info_ptr (const CamelMessageInfo *mi,
- gint id)
-{
- CamelVeeMessageInfo *vmi = (CamelVeeMessageInfo *) mi;
- CamelMessageInfo *rmi;
- gpointer p;
-
- rmi = camel_folder_summary_get (vmi->orig_summary, mi->uid + 8);
- HANDLE_NULL_INFO (NULL);
- p = (gpointer) camel_message_info_get_ptr (rmi, id);
- camel_message_info_unref (rmi);
-
- return p;
-}
-
-static guint32
-vee_info_uint32 (const CamelMessageInfo *mi,
- gint id)
-{
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid
+ 8);
- guint32 ret;
-
- HANDLE_NULL_INFO (0);
- ret = camel_message_info_get_uint32 (rmi, id);
- camel_message_info_unref (rmi);
-
- return ret;
-
-}
-
-static time_t
-vee_info_time (const CamelMessageInfo *mi,
- gint id)
-{
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid
+ 8);
- time_t ret;
-
- HANDLE_NULL_INFO (0);
- ret = camel_message_info_get_time (rmi, id);
- camel_message_info_unref (rmi);
-
- return ret;
-}
-
-static gboolean
-vee_info_user_flag (const CamelMessageInfo *mi,
- const gchar *id)
-{
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid
+ 8);
- gboolean ret;
-
- HANDLE_NULL_INFO (FALSE);
- ret = camel_message_info_get_user_flag (rmi, id);
- camel_message_info_unref (rmi);
-
- return ret;
-}
-
-static const gchar *
-vee_info_user_tag (const CamelMessageInfo *mi,
- const gchar *id)
-{
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid
+ 8);
- const gchar *ret;
-
- HANDLE_NULL_INFO ("");
- ret = camel_message_info_get_user_tag (rmi, id);
- camel_message_info_unref (rmi);
-
- return ret;
-}
-
-static void
-vee_summary_notify_mi_changed (CamelVeeFolder *vfolder,
- CamelMessageInfo *mi)
-{
- CamelFolderChangeInfo *changes;
-
- g_return_if_fail (vfolder != NULL);
- g_return_if_fail (mi != NULL);
-
- changes = camel_folder_change_info_new ();
-
- camel_folder_change_info_change_uid (changes, camel_message_info_get_uid (mi));
- camel_folder_changed (CAMEL_FOLDER (vfolder), changes);
- camel_folder_change_info_free (changes);
-}
-
-static gboolean
-vee_info_set_user_flag (CamelMessageInfo *mi,
- const gchar *name,
- gboolean value)
-{
- gint res = FALSE;
- CamelVeeFolder *vf = (CamelVeeFolder *) camel_folder_summary_get_folder (mi->summary);
-
- if (mi->uid) {
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary,
mi->uid + 8);
- gboolean ignore_changes = !CAMEL_IS_VTRASH_FOLDER (vf);
-
- HANDLE_NULL_INFO (FALSE);
-
- /* ignore changes done in the folder itself,
- * unless it's a vTrash or vJunk folder */
- if (ignore_changes)
- camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder
(rmi->summary));
-
- res = camel_message_info_set_user_flag (rmi, name, value);
-
- if (ignore_changes) {
- if (res)
- vee_summary_notify_mi_changed (vf, mi);
- else
- camel_vee_folder_remove_from_ignore_changed_event (vf,
camel_folder_summary_get_folder (rmi->summary));
- }
-
- camel_message_info_unref (rmi);
- }
-
- return res;
-}
-
-static gboolean
-vee_info_set_user_tag (CamelMessageInfo *mi,
- const gchar *name,
- const gchar *value)
-{
- gint res = FALSE;
-
- if (mi->uid) {
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary,
mi->uid + 8);
- CamelVeeFolder *vf = (CamelVeeFolder *) camel_folder_summary_get_folder (mi->summary);
- gboolean ignore_changes = !CAMEL_IS_VTRASH_FOLDER (vf);
-
- HANDLE_NULL_INFO (FALSE);
-
- /* ignore changes done in the folder itself,
- * unless it's a vTrash or vJunk folder */
- if (ignore_changes)
- camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder
(rmi->summary));
-
- res = camel_message_info_set_user_tag (rmi, name, value);
-
- if (ignore_changes) {
- if (res)
- vee_summary_notify_mi_changed (vf, mi);
- else
- camel_vee_folder_remove_from_ignore_changed_event (vf,
camel_folder_summary_get_folder (rmi->summary));
- }
-
- camel_message_info_unref (rmi);
- }
-
- return res;
-}
-
-static gboolean
-vee_info_set_flags (CamelMessageInfo *mi,
- guint32 flags,
- guint32 set)
-{
- gint res = FALSE;
- CamelVeeFolder *vf = CAMEL_VEE_FOLDER (camel_folder_summary_get_folder (mi->summary));
-
- /* first update original message info... */
- if (mi->uid) {
- CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary,
mi->uid + 8);
- gboolean ignore_changes = !CAMEL_IS_VTRASH_FOLDER (vf);
-
- HANDLE_NULL_INFO (FALSE);
-
- /* ignore changes done in the folder itself,
- * unless it's a vTrash or vJunk folder */
- if (ignore_changes)
- camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder
(rmi->summary));
-
- res = camel_message_info_set_flags (rmi, flags, set);
-
- if (res) {
- /* update flags on itself too */
- camel_folder_summary_replace_flags (mi->summary, mi);
- }
-
- if (ignore_changes) {
- if (res)
- vee_summary_notify_mi_changed (vf, mi);
- else
- camel_vee_folder_remove_from_ignore_changed_event (vf,
camel_folder_summary_get_folder (rmi->summary));
- }
-
- camel_message_info_unref (rmi);
- }
-
- /* Do not call parent class' info_set_flags, to not do flood
- * of change notifications, rather wait for a notification
- * from original folder, and propagate the change in counts
- * through camel_vee_summary_replace_flags().
- */
- /*if (res)
- CAMEL_FOLDER_SUMMARY_CLASS (camel_vee_summary_parent_class)->info_set_flags (mi, flags,
set);*/
-
- return res;
-}
-
static CamelMessageInfo *
message_info_from_uid (CamelFolderSummary *s,
const gchar *uid)
@@ -290,7 +58,6 @@ message_info_from_uid (CamelFolderSummary *s,
info = camel_folder_summary_peek_loaded (s, uid);
if (!info) {
- CamelVeeMessageInfo *vinfo;
CamelFolder *orig_folder;
/* This function isn't really nice. But no great way
@@ -305,22 +72,16 @@ message_info_from_uid (CamelFolderSummary *s,
return NULL;
}
- /* Create the info and load it, its so easy. */
- info = camel_message_info_new (s);
- info->dirty = FALSE;
- info->uid = camel_pstring_strdup (uid);
-
orig_folder = camel_vee_folder_get_vee_uid_folder (
(CamelVeeFolder *) camel_folder_summary_get_folder (s), uid);
g_return_val_if_fail (orig_folder != NULL, NULL);
- vinfo = (CamelVeeMessageInfo *) info;
- vinfo->orig_summary = orig_folder->summary;
+ /* Create the info and load it, its so easy. */
+ info = camel_vee_message_info_new (s, orig_folder->summary, uid);
- g_object_ref (vinfo->orig_summary);
- camel_message_info_ref (info);
+ camel_message_info_set_dirty (info, FALSE);
- camel_folder_summary_insert (s, info, FALSE);
+ camel_folder_summary_add (s, info, TRUE);
}
return info;
@@ -351,18 +112,7 @@ camel_vee_summary_class_init (CamelVeeSummaryClass *class)
object_class->finalize = vee_summary_finalize;
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelVeeMessageInfo);
- folder_summary_class->content_info_size = 0;
- folder_summary_class->message_info_clone = vee_message_info_clone;
- folder_summary_class->message_info_free = vee_message_info_free;
- folder_summary_class->info_ptr = vee_info_ptr;
- folder_summary_class->info_uint32 = vee_info_uint32;
- folder_summary_class->info_time = vee_info_time;
- folder_summary_class->info_user_flag = vee_info_user_flag;
- folder_summary_class->info_user_tag = vee_info_user_tag;
- folder_summary_class->info_set_user_flag = vee_info_set_user_flag;
- folder_summary_class->info_set_user_tag = vee_info_set_user_tag;
- folder_summary_class->info_set_flags = vee_info_set_flags;
+ folder_summary_class->message_info_type = CAMEL_TYPE_VEE_MESSAGE_INFO;
folder_summary_class->message_info_from_uid = message_info_from_uid;
}
@@ -446,7 +196,15 @@ camel_vee_summary_get_uids_for_subfolder (CamelVeeSummary *summary,
return known_uids;
}
-/* unref returned pointer with camel_message_info_unref() */
+/**
+ * camel_vee_summary_add:
+ * @s: the CamelVeeSummary
+ * @mi_data: (type CamelVeeMessageInfoData): the #CamelVeeMessageInfoData to add
+ *
+ * Unref returned pointer with g_object_unref()
+ *
+ * Returns: (transfer full): A new #CamelVeeMessageInfo object.
+ **/
CamelVeeMessageInfo *
camel_vee_summary_add (CamelVeeSummary *s,
CamelVeeMessageInfoData *mi_data)
@@ -470,19 +228,14 @@ camel_vee_summary_add (CamelVeeSummary *s,
if (vmi) {
/* Possible that the entry is loaded, see if it has the summary */
d (g_message ("%s - already there\n", vuid));
- if (!vmi->orig_summary)
- vmi->orig_summary = g_object_ref (orig_folder->summary);
+ g_warn_if_fail (camel_vee_message_info_get_original_summary (vmi) != NULL);
camel_folder_summary_unlock (&s->summary);
return vmi;
}
- vmi = (CamelVeeMessageInfo *) camel_message_info_new (&s->summary);
- vmi->orig_summary = g_object_ref (orig_folder->summary);
- vmi->info.uid = (gchar *) camel_pstring_strdup (vuid);
-
- camel_message_info_ref (vmi);
+ vmi = (CamelVeeMessageInfo *) camel_vee_message_info_new (CAMEL_FOLDER_SUMMARY (s),
orig_folder->summary, vuid);
vuids = g_hash_table_lookup (s->priv->vuids_by_subfolder, orig_folder);
if (vuids) {
@@ -493,7 +246,7 @@ camel_vee_summary_add (CamelVeeSummary *s,
g_hash_table_insert (s->priv->vuids_by_subfolder, orig_folder, vuids);
}
- camel_folder_summary_insert (&s->summary, (CamelMessageInfo *) vmi, FALSE);
+ camel_folder_summary_add (&s->summary, (CamelMessageInfo *) vmi, TRUE);
camel_folder_summary_unlock (&s->summary);
return vmi;
@@ -534,8 +287,8 @@ camel_vee_summary_remove (CamelVeeSummary *summary,
if (mi) {
/* under twice, the first for camel_folder_summary_peek_loaded(),
* the second to actually free the mi */
- camel_message_info_unref (mi);
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
+ g_clear_object (&mi);
}
camel_folder_summary_unlock (&summary->summary);
@@ -570,7 +323,7 @@ camel_vee_summary_replace_flags (CamelVeeSummary *summary,
}
camel_folder_summary_replace_flags (&summary->summary, mi);
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
camel_folder_summary_unlock (&summary->summary);
}
diff --git a/src/camel/camel-vee-summary.h b/src/camel/camel-vee-summary.h
index 94a95dc..629b2f4 100644
--- a/src/camel/camel-vee-summary.h
+++ b/src/camel/camel-vee-summary.h
@@ -25,6 +25,7 @@
#define CAMEL_VEE_SUMMARY_H
#include <camel/camel-folder-summary.h>
+#include <camel/camel-vee-message-info.h>
/* Standard GObject macros */
#define CAMEL_TYPE_VEE_SUMMARY \
@@ -55,13 +56,6 @@ typedef struct _CamelVeeSummary CamelVeeSummary;
typedef struct _CamelVeeSummaryClass CamelVeeSummaryClass;
typedef struct _CamelVeeSummaryPrivate CamelVeeSummaryPrivate;
-typedef struct _CamelVeeMessageInfo CamelVeeMessageInfo;
-
-struct _CamelVeeMessageInfo {
- CamelMessageInfoBase info;
- CamelFolderSummary *orig_summary;
-};
-
struct _CamelVeeSummary {
CamelFolderSummary summary;
@@ -74,7 +68,7 @@ struct _CamelVeeSummaryClass {
GType camel_vee_summary_get_type (void);
CamelFolderSummary *
- camel_vee_summary_new (struct _CamelFolder *parent);
+ camel_vee_summary_new (CamelFolder *parent);
CamelVeeMessageInfo *
camel_vee_summary_add (CamelVeeSummary *s,
struct _CamelVeeMessageInfoData *mi_data);
diff --git a/src/camel/camel-vtrash-folder.c b/src/camel/camel-vtrash-folder.c
index b8eef41..6b0888d 100644
--- a/src/camel/camel-vtrash-folder.c
+++ b/src/camel/camel-vtrash-folder.c
@@ -79,7 +79,7 @@ transfer_messages (CamelFolder *folder,
CamelMessageInfo *mi = camel_folder_get_message_info (md->source_folder,
md->source_uids->pdata[i]);
if (mi) {
camel_message_info_set_flags (mi, md->sbit, md->sbit);
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
}
}
@@ -166,18 +166,18 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
continue;
}
- if (dest == camel_folder_summary_get_folder (mi->orig_summary)) {
+ if (dest == camel_vee_message_info_get_original_folder (mi)) {
/* Just unset the flag on the original message */
camel_folder_set_message_flags (
source, uids->pdata[i], sbit, 0);
} else {
if (batch == NULL)
batch = g_hash_table_new (NULL, NULL);
- md = g_hash_table_lookup (batch, camel_folder_summary_get_folder (mi->orig_summary));
+ md = g_hash_table_lookup (batch, camel_vee_message_info_get_original_folder (mi));
if (md == NULL) {
md = g_malloc0 (sizeof (*md));
md->cancellable = cancellable;
- md->folder = g_object_ref (camel_folder_summary_get_folder
(mi->orig_summary));
+ md->folder = g_object_ref (camel_vee_message_info_get_original_folder (mi));
md->uids = g_ptr_array_new ();
md->dest = dest;
md->delete = delete_originals;
@@ -187,7 +187,7 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
if (cancellable != NULL)
g_object_ref (cancellable);
camel_folder_freeze (md->folder);
- g_hash_table_insert (batch, camel_folder_summary_get_folder
(mi->orig_summary), md);
+ g_hash_table_insert (batch, camel_vee_message_info_get_original_folder (mi),
md);
}
/* unset the bit temporarily */
@@ -199,7 +199,7 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
g_ptr_array_add (md->uids, g_strdup (tuid));
g_ptr_array_add (md->source_uids, uids->pdata[i]);
}
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
}
if (batch) {
diff --git a/src/camel/camel.h b/src/camel/camel.h
index 5710717..b405baf 100644
--- a/src/camel/camel.h
+++ b/src/camel/camel.h
@@ -56,6 +56,8 @@
#include <camel/camel-medium.h>
#include <camel/camel-memchunk.h>
#include <camel/camel-mempool.h>
+#include <camel/camel-message-info.h>
+#include <camel/camel-message-info-base.h>
#include <camel/camel-mime-filter.h>
#include <camel/camel-mime-filter-basic.h>
#include <camel/camel-mime-filter-bestenc.h>
@@ -83,6 +85,8 @@
#include <camel/camel-multipart.h>
#include <camel/camel-multipart-encrypted.h>
#include <camel/camel-multipart-signed.h>
+#include <camel/camel-named-flags.h>
+#include <camel/camel-name-value-array.h>
#include <camel/camel-net-utils.h>
#include <camel/camel-network-service.h>
#include <camel/camel-nntp-address.h>
@@ -128,8 +132,10 @@
#include <camel/camel-url.h>
#include <camel/camel-url-scanner.h>
#include <camel/camel-utf8.h>
+#include <camel/camel-utils.h>
#include <camel/camel-vee-data-cache.h>
#include <camel/camel-vee-folder.h>
+#include <camel/camel-vee-message-info.h>
#include <camel/camel-vee-store.h>
#include <camel/camel-vee-summary.h>
#include <camel/camel-vtrash-folder.h>
diff --git a/src/camel/providers/imapx/CMakeLists.txt b/src/camel/providers/imapx/CMakeLists.txt
index 5395f24..dcdf24b 100644
--- a/src/camel/providers/imapx/CMakeLists.txt
+++ b/src/camel/providers/imapx/CMakeLists.txt
@@ -16,6 +16,8 @@ set(SOURCES
camel-imapx-logger.h
camel-imapx-mailbox.c
camel-imapx-mailbox.h
+ camel-imapx-message-info.c
+ camel-imapx-message-info.h
camel-imapx-namespace.c
camel-imapx-namespace.h
camel-imapx-namespace-response.c
diff --git a/src/camel/providers/imapx/camel-imapx-command.c b/src/camel/providers/imapx/camel-imapx-command.c
index cf54416..7e9ec7f 100644
--- a/src/camel/providers/imapx/camel-imapx-command.c
+++ b/src/camel/providers/imapx/camel-imapx-command.c
@@ -188,7 +188,7 @@ camel_imapx_command_addv (CamelIMAPXCommand *ic,
gint d;
glong l;
guint32 f;
- CamelFlag *F;
+ const CamelNamedFlags *F;
CamelDataWrapper *D;
CamelSasl *A;
gchar literal_format[16];
@@ -307,7 +307,7 @@ camel_imapx_command_addv (CamelIMAPXCommand *ic,
goto output_string;
case 'F': /* IMAP flags set */
f = va_arg (ap, guint32);
- F = va_arg (ap, CamelFlag *);
+ F = va_arg (ap, const CamelNamedFlags *);
imapx_write_flags (buffer, f, F);
break;
case 'c':
diff --git a/src/camel/providers/imapx/camel-imapx-folder.c b/src/camel/providers/imapx/camel-imapx-folder.c
index 0d73287..c14b3fb 100644
--- a/src/camel/providers/imapx/camel-imapx-folder.c
+++ b/src/camel/providers/imapx/camel-imapx-folder.c
@@ -498,7 +498,7 @@ imapx_expunge_sync (CamelFolder *folder,
info = camel_folder_summary_get (folder->summary, g_ptr_array_index
(known_uids, ii));
if (info) {
camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED,
CAMEL_MESSAGE_DELETED);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
@@ -649,7 +649,7 @@ imapx_get_message_sync (CamelFolder *folder,
has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0);
}
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
}
}
diff --git a/src/camel/providers/imapx/camel-imapx-message-info.c
b/src/camel/providers/imapx/camel-imapx-message-info.c
new file mode 100644
index 0000000..9a324d1
--- /dev/null
+++ b/src/camel/providers/imapx/camel-imapx-message-info.c
@@ -0,0 +1,435 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "camel/camel.h"
+#include "camel-imapx-summary.h"
+
+#include "camel-imapx-message-info.h"
+
+struct _CamelIMAPXMessageInfoPrivate {
+ guint32 server_flags;
+ CamelNamedFlags *server_user_flags;
+ CamelNameValueArray *server_user_tags;
+};
+
+enum {
+ PROP_0,
+ PROP_SERVER_FLAGS,
+ PROP_SERVER_USER_FLAGS,
+ PROP_SERVER_USER_TAGS
+};
+
+G_DEFINE_TYPE (CamelIMAPXMessageInfo, camel_imapx_message_info, CAMEL_TYPE_MESSAGE_INFO_BASE)
+
+static CamelMessageInfo *
+imapx_message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfo *result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (mi), NULL);
+
+ result = CAMEL_MESSAGE_INFO_CLASS (camel_imapx_message_info_parent_class)->clone (mi, assign_summary);
+ if (!result)
+ return NULL;
+
+ if (CAMEL_IS_IMAPX_MESSAGE_INFO (result)) {
+ CamelIMAPXMessageInfo *imi, *imi_result;
+
+ imi = CAMEL_IMAPX_MESSAGE_INFO (mi);
+ imi_result = CAMEL_IMAPX_MESSAGE_INFO (result);
+
+ camel_imapx_message_info_set_server_flags (imi_result,
camel_imapx_message_info_get_server_flags (imi));
+ camel_imapx_message_info_take_server_user_flags (imi_result,
camel_imapx_message_info_dup_server_user_flags (imi));
+ camel_imapx_message_info_take_server_user_tags (imi_result,
camel_imapx_message_info_dup_server_user_tags (imi));
+ }
+
+ return result;
+}
+
+static gboolean
+imapx_message_info_load (CamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ CamelIMAPXMessageInfo *imi;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!CAMEL_MESSAGE_INFO_CLASS (camel_imapx_message_info_parent_class)->load ||
+ !CAMEL_MESSAGE_INFO_CLASS (camel_imapx_message_info_parent_class)->load (mi, record, bdata_ptr))
+ return FALSE;
+
+ imi = CAMEL_IMAPX_MESSAGE_INFO (mi);
+
+ camel_imapx_message_info_set_server_flags (imi, camel_util_bdata_get_number (bdata_ptr, 0));
+
+ /* Reset server-side information, which is not saved into the summary. */
+ camel_imapx_message_info_take_server_user_flags (imi, NULL);
+ camel_imapx_message_info_take_server_user_tags (imi, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+imapx_message_info_save (const CamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ CamelIMAPXMessageInfo *imi;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ if (!CAMEL_MESSAGE_INFO_CLASS (camel_imapx_message_info_parent_class)->save ||
+ !CAMEL_MESSAGE_INFO_CLASS (camel_imapx_message_info_parent_class)->save (mi, record, bdata_str))
+ return FALSE;
+
+ imi = CAMEL_IMAPX_MESSAGE_INFO (mi);
+
+ camel_util_bdata_put_number (bdata_str, camel_imapx_message_info_get_server_flags (imi));
+
+ return TRUE;
+}
+
+static void
+imapx_message_info_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CamelIMAPXMessageInfo *imi = CAMEL_IMAPX_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_SERVER_FLAGS:
+ camel_imapx_message_info_set_server_flags (imi, g_value_get_uint (value));
+ return;
+
+ case PROP_SERVER_USER_FLAGS:
+ camel_imapx_message_info_take_server_user_flags (imi, g_value_dup_boxed (value));
+ return;
+
+ case PROP_SERVER_USER_TAGS:
+ camel_imapx_message_info_take_server_user_tags (imi, g_value_dup_boxed (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+imapx_message_info_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CamelIMAPXMessageInfo *imi = CAMEL_IMAPX_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_SERVER_FLAGS:
+ g_value_set_uint (value, camel_imapx_message_info_get_server_flags (imi));
+ return;
+
+ case PROP_SERVER_USER_FLAGS:
+ g_value_take_boxed (value, camel_imapx_message_info_dup_server_user_flags (imi));
+ return;
+
+ case PROP_SERVER_USER_TAGS:
+ g_value_take_boxed (value, camel_imapx_message_info_dup_server_user_tags (imi));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+imapx_message_info_dispose (GObject *object)
+{
+ CamelIMAPXMessageInfo *imi = CAMEL_IMAPX_MESSAGE_INFO (object);
+
+ camel_named_flags_free (imi->priv->server_user_flags);
+ imi->priv->server_user_flags = NULL;
+
+ camel_name_value_array_free (imi->priv->server_user_tags);
+ imi->priv->server_user_tags = NULL;
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_imapx_message_info_parent_class)->dispose (object);
+}
+
+static void
+camel_imapx_message_info_class_init (CamelIMAPXMessageInfoClass *class)
+{
+ CamelMessageInfoClass *mi_class;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelIMAPXMessageInfoPrivate));
+
+ mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
+ mi_class->clone = imapx_message_info_clone;
+ mi_class->load = imapx_message_info_load;
+ mi_class->save = imapx_message_info_save;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = imapx_message_info_set_property;
+ object_class->get_property = imapx_message_info_get_property;
+ object_class->dispose = imapx_message_info_dispose;
+
+ /**
+ * CamelIMAPXMessageInfo:server-flags
+ *
+ * Bit-or of #CamelMessageFlags of the flags stored on the server.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SERVER_FLAGS,
+ g_param_spec_uint (
+ "server-flags",
+ "Server Flags",
+ NULL,
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelIMAPXMessageInfo:server-user-flags
+ *
+ * User flags for the associated message, as stored on the server.
+ * Can be %NULL.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SERVER_USER_FLAGS,
+ g_param_spec_boxed (
+ "server-user-flags",
+ "Server User Flags",
+ NULL,
+ CAMEL_TYPE_NAMED_FLAGS,
+ G_PARAM_READWRITE));
+
+ /**
+ * CamelIMAPXMessageInfo:server-user-tags
+ *
+ * User tags for the associated message, as stored on the server.
+ * Can be %NULL.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_SERVER_USER_TAGS,
+ g_param_spec_boxed (
+ "server-user-tags",
+ "Server User tags",
+ NULL,
+ CAMEL_TYPE_NAME_VALUE_ARRAY,
+ G_PARAM_READWRITE));
+}
+
+static void
+camel_imapx_message_info_init (CamelIMAPXMessageInfo *imi)
+{
+ imi->priv = G_TYPE_INSTANCE_GET_PRIVATE (imi, CAMEL_TYPE_IMAPX_MESSAGE_INFO,
CamelIMAPXMessageInfoPrivate);
+}
+
+guint32
+camel_imapx_message_info_get_server_flags (const CamelIMAPXMessageInfo *imi)
+{
+ CamelMessageInfo *mi;
+ guint32 result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), 0);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+ result = imi->priv->server_flags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gboolean
+camel_imapx_message_info_set_server_flags (CamelIMAPXMessageInfo *imi,
+ guint32 server_flags)
+{
+ CamelMessageInfo *mi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), FALSE);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = imi->priv->server_flags != server_flags;
+ if (changed)
+ imi->priv->server_flags = server_flags;
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !camel_message_info_get_abort_notifications (mi)) {
+ g_object_notify (G_OBJECT (imi), "server-flags");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
+
+const CamelNamedFlags *
+camel_imapx_message_info_get_server_user_flags (const CamelIMAPXMessageInfo *imi)
+{
+ CamelMessageInfo *mi;
+ const CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+ result = imi->priv->server_user_flags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+CamelNamedFlags *
+camel_imapx_message_info_dup_server_user_flags (const CamelIMAPXMessageInfo *imi)
+{
+ CamelMessageInfo *mi;
+ CamelNamedFlags *result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+ result = camel_named_flags_copy (imi->priv->server_user_flags);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gboolean
+camel_imapx_message_info_take_server_user_flags (CamelIMAPXMessageInfo *imi,
+ CamelNamedFlags *server_user_flags)
+{
+ CamelMessageInfo *mi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), FALSE);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !camel_named_flags_equal (imi->priv->server_user_flags, server_user_flags);
+
+ if (changed) {
+ camel_named_flags_free (imi->priv->server_user_flags);
+ imi->priv->server_user_flags = server_user_flags;
+ } else {
+ camel_named_flags_free (server_user_flags);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !camel_message_info_get_abort_notifications (mi)) {
+ g_object_notify (G_OBJECT (imi), "server-user-flags");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
+
+const CamelNameValueArray *
+camel_imapx_message_info_get_server_user_tags (const CamelIMAPXMessageInfo *imi)
+{
+ CamelMessageInfo *mi;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+ result = imi->priv->server_user_tags;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+CamelNameValueArray *
+camel_imapx_message_info_dup_server_user_tags (const CamelIMAPXMessageInfo *imi)
+{
+ CamelMessageInfo *mi;
+ CamelNameValueArray *result;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+ result = camel_name_value_array_copy (imi->priv->server_user_tags);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gboolean
+camel_imapx_message_info_take_server_user_tags (CamelIMAPXMessageInfo *imi,
+ CamelNameValueArray *server_user_tags)
+{
+ CamelMessageInfo *mi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MESSAGE_INFO (imi), FALSE);
+
+ mi = CAMEL_MESSAGE_INFO (imi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = !camel_name_value_array_equal (imi->priv->server_user_tags, server_user_tags, TRUE);
+
+ if (changed) {
+ camel_name_value_array_free (imi->priv->server_user_tags);
+ imi->priv->server_user_tags = server_user_tags;
+ } else {
+ camel_name_value_array_free (server_user_tags);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !camel_message_info_get_abort_notifications (mi)) {
+ g_object_notify (G_OBJECT (imi), "server-user-tags");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
diff --git a/src/camel/providers/imapx/camel-imapx-message-info.h
b/src/camel/providers/imapx/camel-imapx-message-info.h
new file mode 100644
index 0000000..748c75b
--- /dev/null
+++ b/src/camel/providers/imapx/camel-imapx-message-info.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAMEL_IMAPX_MESSAGE_INFO_H
+#define CAMEL_IMAPX_MESSAGE_INFO_H
+
+#include <glib-object.h>
+
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_IMAPX_MESSAGE_INFO \
+ (camel_imapx_message_info_get_type ())
+#define CAMEL_IMAPX_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_IMAPX_MESSAGE_INFO, CamelIMAPXMessageInfo))
+#define CAMEL_IMAPX_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_IMAPX_MESSAGE_INFO, CamelIMAPXMessageInfoClass))
+#define CAMEL_IS_IMAPX_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_IMAPX_MESSAGE_INFO))
+#define CAMEL_IS_IMAPX_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_IMAPX_MESSAGE_INFO))
+#define CAMEL_IMAPX_MESSAGE_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_IMAPX_MESSAGE_INFO, CamelIMAPXMessageInfoClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelIMAPXMessageInfo CamelIMAPXMessageInfo;
+typedef struct _CamelIMAPXMessageInfoClass CamelIMAPXMessageInfoClass;
+typedef struct _CamelIMAPXMessageInfoPrivate CamelIMAPXMessageInfoPrivate;
+
+struct _CamelIMAPXMessageInfo {
+ CamelMessageInfoBase parent;
+ CamelIMAPXMessageInfoPrivate *priv;
+};
+
+struct _CamelIMAPXMessageInfoClass {
+ CamelMessageInfoBaseClass parent_class;
+};
+
+GType camel_imapx_message_info_get_type (void);
+
+guint32 camel_imapx_message_info_get_server_flags
+ (const CamelIMAPXMessageInfo *imi);
+gboolean camel_imapx_message_info_set_server_flags
+ (CamelIMAPXMessageInfo *imi,
+ guint32 server_flags);
+const CamelNamedFlags *
+ camel_imapx_message_info_get_server_user_flags
+ (const CamelIMAPXMessageInfo *imi);
+CamelNamedFlags *
+ camel_imapx_message_info_dup_server_user_flags
+ (const CamelIMAPXMessageInfo *imi);
+gboolean camel_imapx_message_info_take_server_user_flags
+ (CamelIMAPXMessageInfo *imi,
+ CamelNamedFlags *server_user_flags);
+const CamelNameValueArray *
+ camel_imapx_message_info_get_server_user_tags
+ (const CamelIMAPXMessageInfo *imi);
+CamelNameValueArray *
+ camel_imapx_message_info_dup_server_user_tags
+ (const CamelIMAPXMessageInfo *imi);
+gboolean camel_imapx_message_info_take_server_user_tags
+ (CamelIMAPXMessageInfo *imi,
+ CamelNameValueArray *server_user_tags);
+
+G_END_DECLS
+
+#endif /* CAMEL_IMAPX_MESSAGE_INFO_H */
diff --git a/src/camel/providers/imapx/camel-imapx-search.c b/src/camel/providers/imapx/camel-imapx-search.c
index b4e0a80..48e6760 100644
--- a/src/camel/providers/imapx/camel-imapx-search.c
+++ b/src/camel/providers/imapx/camel-imapx-search.c
@@ -258,8 +258,7 @@ imapx_search_match_all (CamelSExp *sexp,
if (search->current) {
result = camel_sexp_term_eval (sexp, argv[0]);
camel_sexp_result_free (sexp, result);
- camel_message_info_unref (search->current);
- search->current = NULL;
+ g_clear_object (&search->current);
break;
}
}
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index 518dbe3..dd3eac5 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -41,6 +41,7 @@
#include "camel-imapx-input-stream.h"
#include "camel-imapx-job.h"
#include "camel-imapx-logger.h"
+#include "camel-imapx-message-info.h"
#include "camel-imapx-settings.h"
#include "camel-imapx-store.h"
#include "camel-imapx-summary.h"
@@ -362,7 +363,7 @@ G_DEFINE_TYPE (CamelIMAPXServer, camel_imapx_server, G_TYPE_OBJECT)
typedef struct _FetchChangesInfo {
guint32 server_flags;
- CamelFlag *server_user_flags;
+ CamelNamedFlags *server_user_flags;
} FetchChangesInfo;
static void
@@ -371,7 +372,7 @@ fetch_changes_info_free (gpointer ptr)
FetchChangesInfo *nfo = ptr;
if (nfo) {
- camel_flag_list_free (&nfo->server_user_flags);
+ camel_named_flags_free (nfo->server_user_flags);
g_free (nfo);
}
}
@@ -1282,8 +1283,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
g_mutex_unlock (&is->priv->changes_lock);
}
- if (mi)
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
g_object_unref (select_folder);
}
@@ -1337,11 +1337,12 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
if (mi != NULL) {
guint32 server_flags;
- CamelFlag *server_user_flags;
- CamelMessageInfoBase *binfo;
+ CamelNamedFlags *server_user_flags;
gboolean free_user_flags = FALSE;
- mi->uid = camel_pstring_strdup (finfo->uid);
+ camel_message_info_set_abort_notifications (mi, TRUE);
+
+ camel_message_info_set_uid (mi, finfo->uid);
if (!(finfo->got & FETCH_FLAGS) && is->priv->fetch_changes_infos) {
FetchChangesInfo *nfo;
@@ -1367,29 +1368,29 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
if (!(server_flags & CAMEL_MESSAGE_SEEN)) {
guint64 uidl;
- uidl = strtoull (mi->uid, NULL, 10);
+ uidl = strtoull (finfo->uid, NULL, 10);
if (uidl >= uidnext) {
- c (is->priv->tagprefix, "Updating unseen count for new message %s\n",
mi->uid);
+ c (is->priv->tagprefix, "Updating unseen count for new message %s\n",
finfo->uid);
camel_imapx_mailbox_set_unseen (mailbox, unseen + 1);
} else {
- c (is->priv->tagprefix, "Not updating unseen count for new message
%s\n", mi->uid);
+ c (is->priv->tagprefix, "Not updating unseen count for new message
%s\n", finfo->uid);
}
}
- binfo = (CamelMessageInfoBase *) mi;
- binfo->size = finfo->size;
+ camel_message_info_set_size (mi, finfo->size);
+ camel_message_info_set_abort_notifications (mi, FALSE);
camel_folder_summary_lock (folder->summary);
- if (!camel_folder_summary_check_uid (folder->summary, mi->uid)) {
+ if (!camel_folder_summary_check_uid (folder->summary, finfo->uid)) {
imapx_set_message_info_flags_for_new_message (mi, server_flags,
server_user_flags, FALSE, NULL, camel_imapx_mailbox_get_permanentflags (mailbox));
- camel_folder_summary_add (folder->summary, mi);
+ camel_folder_summary_add (folder->summary, mi, FALSE);
g_mutex_lock (&is->priv->changes_lock);
- camel_folder_change_info_add_uid (is->priv->changes, mi->uid);
- camel_folder_change_info_recent_uid (is->priv->changes, mi->uid);
+ camel_folder_change_info_add_uid (is->priv->changes, finfo->uid);
+ camel_folder_change_info_recent_uid (is->priv->changes, finfo->uid);
g_mutex_unlock (&is->priv->changes_lock);
@@ -1398,14 +1399,13 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
camel_operation_progress (cancellable, cnt ? cnt : 1);
}
- } else {
- camel_message_info_unref (mi);
}
+ g_clear_object (&mi);
camel_folder_summary_unlock (folder->summary);
- if (free_user_flags && server_user_flags)
- camel_flag_list_free (&server_user_flags);
+ if (free_user_flags)
+ camel_named_flags_free (server_user_flags);
}
g_clear_object (&mailbox);
@@ -4080,12 +4080,12 @@ camel_imapx_server_get_message_sync (CamelIMAPXServer *is,
cache_stream = camel_data_cache_add (message_cache, "tmp", message_uid, error);
if (cache_stream == NULL) {
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
return NULL;
}
settings = camel_imapx_server_ref_settings (is);
- data_size = ((CamelMessageInfoBase *) mi)->size;
+ data_size = camel_message_info_get_size (mi);
use_multi_fetch = data_size > MULTI_SIZE && camel_imapx_settings_get_use_multi_fetch (settings);
g_object_unref (settings);
@@ -4316,7 +4316,7 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
g_mutex_unlock (&is->priv->stream_lock);
}
- source_infos = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, camel_message_info_unref);
+ source_infos = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
data_uids = g_ptr_array_new ();
for (ii = 0; ii < uids->len; ii++) {
@@ -4395,31 +4395,32 @@ camel_imapx_server_copy_message_sync (CamelIMAPXServer *is,
if (!destination_info) {
is_new = TRUE;
- destination_info = camel_message_info_clone
(source_info);
- destination_info->summary =
destination_folder->summary;
- camel_pstring_free (destination_info->uid);
- destination_info->uid = camel_pstring_strdup (uid);
+ destination_info = camel_message_info_clone
(source_info, destination_folder->summary);
+ camel_message_info_set_uid (destination_info, uid);
}
g_free (uid);
+ camel_message_info_property_lock (source_info);
+
imapx_set_message_info_flags_for_new_message (
destination_info,
- ((CamelMessageInfoBase *) source_info)->flags,
- ((CamelMessageInfoBase *) source_info)->user_flags,
+ camel_message_info_get_flags (source_info),
+ camel_message_info_get_user_flags (source_info),
TRUE,
- ((CamelMessageInfoBase *) source_info)->user_tags,
+ camel_message_info_get_user_tags (source_info),
camel_imapx_mailbox_get_permanentflags (destination));
if (remove_deleted_flags)
camel_message_info_set_flags (destination_info,
CAMEL_MESSAGE_DELETED, 0);
if (remove_junk_flags)
camel_message_info_set_flags (destination_info,
CAMEL_MESSAGE_JUNK, 0);
if (is_new)
- camel_folder_summary_add
(destination_folder->summary, destination_info);
- camel_folder_change_info_add_uid (changes,
destination_info->uid);
+ camel_folder_summary_add
(destination_folder->summary, destination_info, FALSE);
+ camel_folder_change_info_add_uid (changes,
camel_message_info_get_uid (destination_info));
+
+ camel_message_info_property_unlock (source_info);
- if (!is_new)
- camel_message_info_unref (destination_info);
+ g_clear_object (&destination_info);
}
if (camel_folder_change_info_changed (changes)) {
@@ -4570,35 +4571,22 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
date_time = camel_mime_message_get_date (message, NULL);
path = camel_data_cache_get_filename (message_cache, "new", uid);
- info = camel_folder_summary_info_new_from_message (summary, message, NULL);
- info->uid = camel_pstring_strdup (uid);
+ info = camel_folder_summary_info_new_from_message (summary, message);
+
+ camel_message_info_set_abort_notifications (info, TRUE);
+ camel_message_info_set_uid (info, uid);
if (mi != NULL) {
struct icaltimetype icaltime;
- CamelMessageInfoBase *base_info = (CamelMessageInfoBase *) info;
- const CamelFlag *flag;
- const CamelTag *tag;
-
- base_info->flags = camel_message_info_get_flags (mi);
- base_info->size = camel_message_info_get_size (mi);
-
- flag = camel_message_info_get_user_flags (mi);
- while (flag != NULL) {
- if (*flag->name != '\0')
- camel_flag_set (
- &base_info->user_flags,
- flag->name, TRUE);
- flag = flag->next;
- }
- tag = camel_message_info_get_user_tags (mi);
- while (tag != NULL) {
- if (*tag->name != '\0')
- camel_tag_set (
- &base_info->user_tags,
- tag->name, tag->value);
- tag = tag->next;
- }
+ camel_message_info_property_lock (mi);
+
+ camel_message_info_set_flags (info, ~0, camel_message_info_get_flags (mi));
+ camel_message_info_set_size (info, camel_message_info_get_size (mi));
+ camel_message_info_take_user_flags (info,
+ camel_named_flags_copy (camel_message_info_get_user_flags (mi)));
+ camel_message_info_take_user_tags (info,
+ camel_name_value_array_copy (camel_message_info_get_user_tags (mi)));
if (date_time > 0) {
icaltime = icaltime_from_timet (date_time, FALSE);
@@ -4614,6 +4602,8 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
if (!icaltime_is_valid_time (icaltime))
date_time = -1;
}
+
+ camel_message_info_property_unlock (mi);
}
if (!camel_message_info_get_size (info)) {
@@ -4622,14 +4612,14 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
camel_data_wrapper_write_to_stream_sync (
CAMEL_DATA_WRAPPER (message),
CAMEL_STREAM (sn), NULL, NULL);
- ((CamelMessageInfoBase *) info)->size = sn->written;
+ camel_message_info_set_size (info, sn->written);
g_object_unref (sn);
}
g_free (uid);
if (camel_mime_message_has_attachment (message))
- ((CamelMessageInfoBase *) info)->flags |= CAMEL_MESSAGE_ATTACHMENTS;
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_ATTACHMENTS, CAMEL_MESSAGE_ATTACHMENTS);
if (date_time > 0) {
gchar *date_time_str;
@@ -4649,8 +4639,8 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_APPEND_MESSAGE, "APPEND %M %F %t %P",
mailbox,
- ((CamelMessageInfoBase *) info)->flags,
- ((CamelMessageInfoBase *) info)->user_flags,
+ camel_message_info_get_flags (info),
+ camel_message_info_get_user_flags (info),
date_time_str,
path);
@@ -4658,11 +4648,13 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
} else {
ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_APPEND_MESSAGE, "APPEND %M %F %P",
mailbox,
- ((CamelMessageInfoBase *) info)->flags,
- ((CamelMessageInfoBase *) info)->user_flags,
+ camel_message_info_get_flags (info),
+ camel_message_info_get_user_flags (info),
path);
}
+ camel_message_info_set_abort_notifications (info, FALSE);
+
success = camel_imapx_server_process_command_sync (is, ic, _("Error appending message"), cancellable,
error);
if (success) {
@@ -4685,36 +4677,42 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
* numbered MessageInfo, without losing any information. Otherwise
* we have to wait for the server to let us know it was appended. */
- mi = camel_message_info_clone (info);
- old_uid = g_strdup (info->uid);
+ mi = camel_message_info_clone (info, NULL);
+ old_uid = g_strdup (camel_message_info_get_uid (info));
if (ic->status && ic->status->condition == IMAPX_APPENDUID) {
c (is->priv->tagprefix, "Got appenduid %d %d\n", (gint)
ic->status->u.appenduid.uidvalidity, (gint) ic->status->u.appenduid.uid);
if (ic->status->u.appenduid.uidvalidity == uidvalidity) {
- if (appended_uid)
- *appended_uid = g_strdup_printf ("%u", (guint)
ic->status->u.appenduid.uid);
- mi->uid = camel_pstring_add (g_strdup_printf ("%u", (guint)
ic->status->u.appenduid.uid), TRUE);
+ gchar *uid;
- cur = camel_data_cache_get_filename (imapx_folder->cache, "cur", mi->uid);
+ uid = g_strdup_printf ("%u", (guint) ic->status->u.appenduid.uid);
+ camel_message_info_set_uid (mi, uid);
+
+ cur = camel_data_cache_get_filename (imapx_folder->cache, "cur", uid);
if (g_rename (path, cur) == -1 && errno != ENOENT) {
g_warning ("%s: Failed to rename '%s' to '%s': %s", G_STRFUNC, path,
cur, g_strerror (errno));
}
imapx_set_message_info_flags_for_new_message (
mi,
- ((CamelMessageInfoBase *) info)->flags,
- ((CamelMessageInfoBase *) info)->user_flags,
+ camel_message_info_get_flags (info),
+ camel_message_info_get_user_flags (info),
TRUE,
- ((CamelMessageInfoBase *) info)->user_tags,
+ camel_message_info_get_user_tags (info),
camel_imapx_mailbox_get_permanentflags (mailbox));
- camel_folder_summary_add (folder->summary, mi);
+ camel_folder_summary_add (folder->summary, mi, FALSE);
g_mutex_lock (&is->priv->changes_lock);
- camel_folder_change_info_add_uid (is->priv->changes, mi->uid);
+ camel_folder_change_info_add_uid (is->priv->changes,
camel_message_info_get_uid (mi));
g_mutex_unlock (&is->priv->changes_lock);
- mi = NULL;
+ if (appended_uid)
+ *appended_uid = uid;
+ else
+ g_free (uid);
+
+ g_clear_object (&mi);
g_free (cur);
} else {
@@ -4726,8 +4724,7 @@ camel_imapx_server_append_message_sync (CamelIMAPXServer *is,
g_free (old_uid);
camel_imapx_command_unref (ic);
- if (mi)
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
g_object_unref (folder);
}
@@ -4860,7 +4857,7 @@ imapx_server_process_fetch_changes_infos (CamelIMAPXServer *is,
g_mutex_unlock (&is->priv->changes_lock);
}
- camel_message_info_unref (minfo);
+ g_clear_object (&minfo);
}
}
@@ -5167,7 +5164,7 @@ imapx_sync_free_user (GArray *user_set)
for (j = 0; j < infos->len; j++) {
CamelMessageInfo *info = g_ptr_array_index (infos, j);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
g_ptr_array_free (infos, TRUE);
@@ -5192,17 +5189,14 @@ imapx_unset_folder_flagged_flag (CamelFolderSummary *summary,
info = camel_folder_summary_get (summary, changed_uids->pdata[ii]);
if (info) {
- CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info;
-
/* some infos could be only 'dirty' (needed to save into summary) */
- if ((mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 &&
- (!except_deleted_messages || (mi->flags & CAMEL_MESSAGE_DELETED) == 0)) {
- mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
- mi->dirty = TRUE;
+ if (camel_message_info_get_folder_flagged (info) &&
+ (!except_deleted_messages || (camel_message_info_get_flags (info) &
CAMEL_MESSAGE_DELETED) == 0)) {
+ camel_message_info_set_folder_flagged (info, FALSE);
changed = TRUE;
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
@@ -5212,25 +5206,6 @@ imapx_unset_folder_flagged_flag (CamelFolderSummary *summary,
}
}
-static void
-imapx_server_info_changed_cb (CamelIMAPXSummary *summary,
- CamelMessageInfo *info,
- gpointer user_data)
-{
- GHashTable *changed_meanwhile = user_data;
-
- g_return_if_fail (info != NULL);
- g_return_if_fail (changed_meanwhile != NULL);
-
- /* The UID can be NULL in case of a newly fetched message, for example when creating
- the message info in imapx_untagged_fetch() by camel_folder_summary_info_new_from_parser() */
- if (camel_message_info_get_uid (info)) {
- g_hash_table_insert (changed_meanwhile,
- (gpointer) camel_pstring_strdup (camel_message_info_get_uid (info)),
- GINT_TO_POINTER (1));
- }
-}
-
gboolean
camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
CamelIMAPXMailbox *mailbox,
@@ -5242,9 +5217,8 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
GPtrArray *changed_uids;
GArray *on_user = NULL, *off_user = NULL;
CamelFolder *folder;
- CamelIMAPXMessageInfo *info;
- GHashTable *changed_meanwhile;
- gulong changed_meanwhile_handler_id;
+ CamelMessageInfo *info;
+ GHashTable *stamps;
guint32 permanentflags;
struct _uidset_state uidset;
gint unread_change = 0;
@@ -5278,9 +5252,7 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
return TRUE;
}
- changed_meanwhile = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)
camel_pstring_free, NULL);
- changed_meanwhile_handler_id = g_signal_connect (folder->summary, "info-changed",
- G_CALLBACK (imapx_server_info_changed_cb), changed_meanwhile);
+ stamps = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL);
if (can_influence_flags) {
CamelIMAPXSettings *settings;
@@ -5314,26 +5286,34 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
off_orset = on_orset = 0;
for (i = 0; i < changed_uids->len; i++) {
+ CamelIMAPXMessageInfo *xinfo;
guint32 flags, sflags;
- CamelFlag *uflags, *suflags;
+ const CamelNamedFlags *local_uflags, *server_uflags;
const gchar *uid;
guint j = 0;
uid = g_ptr_array_index (changed_uids, i);
- info = (CamelIMAPXMessageInfo *)
- camel_folder_summary_get (folder->summary, uid);
+ info = camel_folder_summary_get (folder->summary, uid);
+ xinfo = info ? CAMEL_IMAPX_MESSAGE_INFO (info) : NULL;
- if (info == NULL)
+ if (!info || !xinfo) {
+ g_clear_object (&info);
continue;
+ }
- if (!(info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- camel_message_info_unref (info);
+ if (!camel_message_info_get_folder_flagged (info)) {
+ g_clear_object (&info);
continue;
}
- flags = info->info.flags & CAMEL_IMAPX_SERVER_FLAGS;
- sflags = info->server_flags & CAMEL_IMAPX_SERVER_FLAGS;
+ camel_message_info_property_lock (info);
+
+ g_hash_table_insert (stamps, (gpointer) camel_message_info_pooldup_uid (info),
+ GUINT_TO_POINTER (camel_message_info_get_folder_flagged_stamp (info)));
+
+ flags = camel_message_info_get_flags (info) & CAMEL_IMAPX_SERVER_FLAGS;
+ sflags = camel_imapx_message_info_get_server_flags (xinfo) & CAMEL_IMAPX_SERVER_FLAGS;
if (can_influence_flags) {
gboolean move_to_real_junk;
@@ -5361,63 +5341,76 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
on_orset |= (flags ^ sflags) & flags;
}
- uflags = info->info.user_flags;
- suflags = info->server_user_flags;
- while (uflags || suflags) {
- gint res;
-
- if (uflags) {
- if (suflags)
- res = strcmp (uflags->name, suflags->name);
- else if (*uflags->name)
- res = -1;
- else {
- uflags = uflags->next;
- continue;
- }
- } else {
- res = 1;
- }
+ local_uflags = camel_message_info_get_user_flags (info);
+ server_uflags = camel_imapx_message_info_get_server_user_flags (xinfo);
- if (res == 0) {
- uflags = uflags->next;
- suflags = suflags->next;
- } else {
- GArray *user_set;
- CamelFlag *user_flag;
- struct _imapx_flag_change *change = NULL, add = { 0 };
-
- if (res < 0) {
- if (on_user == NULL)
- on_user = g_array_new (FALSE, FALSE, sizeof (struct
_imapx_flag_change));
- user_set = on_user;
- user_flag = uflags;
- uflags = uflags->next;
+ if (!camel_named_flags_equal (local_uflags, server_uflags)) {
+ guint ii, jj, llen, slen;
+
+ llen = local_uflags ? camel_named_flags_get_length (local_uflags) : 0;
+ slen = server_uflags ? camel_named_flags_get_length (server_uflags) : 0;
+ for (ii = 0, jj = 0; ii < llen || jj < slen;) {
+ gint res;
+
+ if (ii < llen) {
+ const gchar *local_name = camel_named_flags_get (local_uflags, ii);
+
+ if (jj < slen) {
+ const gchar *server_name = camel_named_flags_get
(server_uflags, jj);
+
+ res = g_strcmp0 (local_name, server_name);
+ } else if (local_name && *local_name)
+ res = -1;
+ else {
+ ii++;
+ continue;
+ }
} else {
- if (off_user == NULL)
- off_user = g_array_new (FALSE, FALSE, sizeof (struct
_imapx_flag_change));
- user_set = off_user;
- user_flag = suflags;
- suflags = suflags->next;
+ res = 1;
}
- /* Could sort this and binary search */
- for (j = 0; j < user_set->len; j++) {
- change = &g_array_index (user_set, struct _imapx_flag_change, j);
- if (strcmp (change->name, user_flag->name) == 0)
- goto found;
+ if (res == 0) {
+ ii++;
+ jj++;
+ } else {
+ GArray *user_set;
+ const gchar *user_flag_name;
+ struct _imapx_flag_change *change = NULL, add = { 0 };
+
+ if (res < 0) {
+ if (on_user == NULL)
+ on_user = g_array_new (FALSE, FALSE, sizeof (struct
_imapx_flag_change));
+ user_set = on_user;
+ user_flag_name = camel_named_flags_get (local_uflags, ii);
+ ii++;
+ } else {
+ if (off_user == NULL)
+ off_user = g_array_new (FALSE, FALSE, sizeof (struct
_imapx_flag_change));
+ user_set = off_user;
+ user_flag_name = camel_named_flags_get (server_uflags, jj);
+ jj++;
+ }
+
+ /* Could sort this and binary search */
+ for (j = 0; j < user_set->len; j++) {
+ change = &g_array_index (user_set, struct _imapx_flag_change,
j);
+ if (g_strcmp0 (change->name, user_flag_name) == 0)
+ goto found;
+ }
+ add.name = g_strdup (user_flag_name);
+ add.infos = g_ptr_array_new ();
+ g_array_append_val (user_set, add);
+ change = &add;
+ found:
+ g_object_ref (info);
+ g_ptr_array_add (change->infos, info);
}
- add.name = g_strdup (user_flag->name);
- add.infos = g_ptr_array_new ();
- g_array_append_val (user_set, add);
- change = &add;
- found:
- camel_message_info_ref (info);
- g_ptr_array_add (change->infos, info);
}
}
- camel_message_info_unref (info);
+ camel_message_info_property_unlock (info);
+
+ g_clear_object (&info);
}
nothing_to_do =
@@ -5427,24 +5420,20 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
(off_user == NULL);
if (nothing_to_do) {
- g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
-
imapx_sync_free_user (on_user);
imapx_sync_free_user (off_user);
imapx_unset_folder_flagged_flag (folder->summary, changed_uids, remove_deleted_flags);
camel_folder_free_uids (folder, changed_uids);
- g_hash_table_destroy (changed_meanwhile);
+ g_hash_table_destroy (stamps);
g_object_unref (folder);
return TRUE;
}
if (!camel_imapx_server_ensure_selected_sync (is, mailbox, cancellable, error)) {
- g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
-
imapx_sync_free_user (on_user);
imapx_sync_free_user (off_user);
camel_folder_free_uids (folder, changed_uids);
- g_hash_table_destroy (changed_meanwhile);
+ g_hash_table_destroy (stamps);
g_object_unref (folder);
return FALSE;
}
@@ -5466,22 +5455,23 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
c (is->priv->tagprefix, "checking/storing %s flags '%s'\n", on ? "on" : "off",
flags_table[jj].name);
imapx_uidset_init (&uidset, 0, 100);
for (i = 0; i < changed_uids->len && success; i++) {
- CamelIMAPXMessageInfo *info;
+ CamelMessageInfo *info;
+ CamelIMAPXMessageInfo *xinfo;
gboolean remove_deleted_flag;
guint32 flags;
guint32 sflags;
gint send;
- info = (CamelIMAPXMessageInfo *)
- camel_folder_summary_get (
- folder->summary,
- changed_uids->pdata[i]);
+ info = camel_folder_summary_get (folder->summary, changed_uids->pdata[i]);
+ xinfo = info ? CAMEL_IMAPX_MESSAGE_INFO (info) : NULL;
- if (info == NULL)
+ if (!info || !xinfo) {
+ g_clear_object (&info);
continue;
+ }
- flags = (info->info.flags & CAMEL_IMAPX_SERVER_FLAGS) & permanentflags;
- sflags = (info->server_flags & CAMEL_IMAPX_SERVER_FLAGS) & permanentflags;
+ flags = (camel_message_info_get_flags (info) & CAMEL_IMAPX_SERVER_FLAGS) &
permanentflags;
+ sflags = (camel_imapx_message_info_get_server_flags (xinfo) &
CAMEL_IMAPX_SERVER_FLAGS) & permanentflags;
send = 0;
remove_deleted_flag =
@@ -5525,10 +5515,11 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
/* The second round and the server doesn't support saving user flags,
thus store them at least locally */
if (on && (permanentflags & CAMEL_MESSAGE_USER) == 0) {
- camel_flag_list_copy (&info->server_user_flags,
&info->info.user_flags);
+ camel_imapx_message_info_take_server_user_flags (xinfo,
+ camel_message_info_dup_user_flags (info));
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
g_warn_if_fail (ic == NULL);
@@ -5542,7 +5533,7 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
imapx_uidset_init (&uidset, 0, 100);
for (i = 0; i < c->infos->len; i++) {
- CamelIMAPXMessageInfo *info = c->infos->pdata[i];
+ CamelMessageInfo *info = c->infos->pdata[i];
if (ic == NULL)
ic = camel_imapx_command_new (is,
CAMEL_IMAPX_JOB_SYNC_CHANGES, "UID STORE ");
@@ -5570,8 +5561,6 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
}
}
- g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
-
if (success) {
CamelStore *parent_store;
guint32 unseen;
@@ -5581,31 +5570,50 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
camel_folder_summary_lock (folder->summary);
for (i = 0; i < changed_uids->len; i++) {
- CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get
(folder->summary,
- changed_uids->pdata[i]);
+ CamelMessageInfo *info;
+ CamelIMAPXMessageInfo *xinfo;
+ gboolean set_folder_flagged;
+ guint32 has_flags, set_server_flags;
+ gboolean changed_meanwhile;
+
+ info = camel_folder_summary_get (folder->summary, changed_uids->pdata[i]);
+ xinfo = info ? CAMEL_IMAPX_MESSAGE_INFO (info) : NULL;
- if (!xinfo)
+ if (!info || !xinfo) {
+ g_clear_object (&info);
continue;
+ }
+
+ camel_message_info_property_lock (info);
+
+ changed_meanwhile = camel_message_info_get_folder_flagged_stamp (info) !=
+ GPOINTER_TO_UINT (g_hash_table_lookup (stamps, changed_uids->pdata[i]));
- xinfo->server_flags = xinfo->info.flags & CAMEL_IMAPX_SERVER_FLAGS;
+ has_flags = camel_message_info_get_flags (info);
+ set_server_flags = has_flags & CAMEL_IMAPX_SERVER_FLAGS;
if (!remove_deleted_flags ||
- !(xinfo->info.flags & CAMEL_MESSAGE_DELETED)) {
- xinfo->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
+ !(has_flags & CAMEL_MESSAGE_DELETED)) {
+ set_folder_flagged = FALSE;
} else {
/* to stare back the \Deleted flag */
- xinfo->server_flags &= ~CAMEL_MESSAGE_DELETED;
- xinfo->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+ set_server_flags &= ~CAMEL_MESSAGE_DELETED;
+ set_folder_flagged = TRUE;
}
- xinfo->info.dirty = TRUE;
+
if ((permanentflags & CAMEL_MESSAGE_USER) != 0 ||
- camel_flag_list_size (&xinfo->server_user_flags) == 0)
- camel_flag_list_copy (&xinfo->server_user_flags, &xinfo->info.user_flags);
+ !camel_named_flags_get_length (camel_imapx_message_info_get_server_user_flags
(xinfo))) {
+ camel_imapx_message_info_take_server_user_flags (xinfo,
camel_message_info_dup_user_flags (info));
+ }
+
+ if (changed_meanwhile)
+ set_folder_flagged = TRUE;
- if (g_hash_table_lookup (changed_meanwhile, changed_uids->pdata[i]))
- xinfo->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+ camel_imapx_message_info_set_server_flags (xinfo, set_server_flags);
+ camel_message_info_set_folder_flagged (info, set_folder_flagged);
+ camel_message_info_property_unlock (info);
camel_folder_summary_touch (folder->summary);
- camel_message_info_unref (xinfo);
+ g_clear_object (&info);
}
camel_folder_summary_unlock (folder->summary);
@@ -5640,7 +5648,7 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
imapx_sync_free_user (on_user);
imapx_sync_free_user (off_user);
camel_folder_free_uids (folder, changed_uids);
- g_hash_table_destroy (changed_meanwhile);
+ g_hash_table_destroy (stamps);
g_object_unref (folder);
return success;
diff --git a/src/camel/providers/imapx/camel-imapx-summary.c b/src/camel/providers/imapx/camel-imapx-summary.c
index 6e3a2d2..7485af3 100644
--- a/src/camel/providers/imapx/camel-imapx-summary.c
+++ b/src/camel/providers/imapx/camel-imapx-summary.c
@@ -28,17 +28,11 @@
#include <camel/camel.h>
+#include "camel-imapx-message-info.h"
#include "camel-imapx-summary.h"
#define CAMEL_IMAPX_SUMMARY_VERSION (4)
-enum {
- INFO_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
G_DEFINE_TYPE (
CamelIMAPXSummary,
camel_imapx_summary,
@@ -61,12 +55,12 @@ imapx_summary_summary_header_from_db (CamelFolderSummary *s,
ims = CAMEL_IMAPX_SUMMARY (s);
- ims->version = bdata_extract_digit (&part);
- ims->validity = bdata_extract_digit (&part);
+ ims->version = camel_util_bdata_get_number (&part, 0);
+ ims->validity = camel_util_bdata_get_number (&part, 0);
if (ims->version >= 4) {
- ims->uidnext = bdata_extract_digit (&part);
- ims->modseq = bdata_extract_digit (&part);
+ ims->uidnext = camel_util_bdata_get_number (&part, 0);
+ ims->modseq = camel_util_bdata_get_number (&part, 0);
}
if (ims->version > CAMEL_IMAPX_SUMMARY_VERSION) {
@@ -109,236 +103,15 @@ imapx_summary_summary_header_to_db (CamelFolderSummary *s,
return fir;
}
-static CamelMessageInfo *
-imapx_summary_message_info_from_db (CamelFolderSummary *s,
- CamelMIRecord *mir)
-{
- CamelMessageInfo *info;
-
- /* Chain up parent's message_info_from_db() method. */
- info = CAMEL_FOLDER_SUMMARY_CLASS (
- camel_imapx_summary_parent_class)->
- message_info_from_db (s, mir);
-
- if (info != NULL) {
- CamelIMAPXMessageInfo *imapx_info;
- gchar *part = mir->bdata;
-
- imapx_info = (CamelIMAPXMessageInfo *) info;
- imapx_info->server_flags = bdata_extract_digit (&part);
- }
-
- return info;
-}
-
-static CamelMIRecord *
-imapx_summary_message_info_to_db (CamelFolderSummary *s,
- CamelMessageInfo *info)
-{
- struct _CamelMIRecord *mir;
-
- /* Chain up to parent's message_info_to_db() method. */
- mir = CAMEL_FOLDER_SUMMARY_CLASS (
- camel_imapx_summary_parent_class)->
- message_info_to_db (s, info);
-
- if (mir != NULL) {
- CamelIMAPXMessageInfo *imapx_info;
-
- imapx_info = (CamelIMAPXMessageInfo *) info;
- mir->bdata = g_strdup_printf ("%u", imapx_info->server_flags);
- }
-
- return mir;
-}
-
-static CamelMessageContentInfo *
-imapx_summary_content_info_from_db (CamelFolderSummary *summary,
- CamelMIRecord *mir)
-{
- gchar *part = mir->cinfo;
- guint32 type = 0;
-
- if (part != NULL) {
- if (*part == ' ')
- part++;
- if (part != NULL)
- type = bdata_extract_digit (&part);
- }
- mir->cinfo = part;
-
- if (type) {
- /* Chain up to parent's content_info_from_db() method. */
- return CAMEL_FOLDER_SUMMARY_CLASS (
- camel_imapx_summary_parent_class)->
- content_info_from_db (summary, mir);
- } else {
- return camel_folder_summary_content_info_new (summary);
- }
-}
-
-static gboolean
-imapx_summary_content_info_to_db (CamelFolderSummary *summary,
- CamelMessageContentInfo *info,
- CamelMIRecord *mir)
-{
- gchar *oldr;
-
- if (info->type) {
- oldr = mir->cinfo;
- if (oldr != NULL)
- mir->cinfo = g_strdup_printf ("%s 1", oldr);
- else
- mir->cinfo = g_strdup ("1");
- g_free (oldr);
-
- /* Chain up to parent's content_info_to_db() method. */
- return CAMEL_FOLDER_SUMMARY_CLASS (
- camel_imapx_summary_parent_class)->
- content_info_to_db (summary, info, mir);
-
- } else {
- oldr = mir->cinfo;
- if (oldr != NULL)
- mir->cinfo = g_strdup_printf ("%s 0", oldr);
- else
- mir->cinfo = g_strdup ("0");
- g_free (oldr);
-
- return TRUE;
- }
-}
-
-static void
-imapx_summary_message_info_free (CamelFolderSummary *summary,
- CamelMessageInfo *info)
-{
- CamelIMAPXMessageInfo *imapx_info;
-
- imapx_info = (CamelIMAPXMessageInfo *) info;
- camel_flag_list_free (&imapx_info->server_user_flags);
-
- /* Chain up to parent's message_info_free() method. */
- CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->
- message_info_free (summary, info);
-}
-
-static CamelMessageInfo *
-imapx_summary_message_info_clone (CamelFolderSummary *summary,
- const CamelMessageInfo *info)
-{
- CamelMessageInfo *copy;
- CamelIMAPXMessageInfo *imapx_copy;
- CamelIMAPXMessageInfo *imapx_info;
-
- /* Chain up to parent's message_info_clone() method. */
- copy = CAMEL_FOLDER_SUMMARY_CLASS (
- camel_imapx_summary_parent_class)->
- message_info_clone (summary, info);
-
- imapx_info = (CamelIMAPXMessageInfo *) info;
- imapx_copy = (CamelIMAPXMessageInfo *) copy;
-
- if (imapx_info->server_user_flags) {
- camel_flag_list_copy (
- &imapx_copy->server_user_flags,
- &imapx_info->server_user_flags);
- }
-
- imapx_copy->server_flags = imapx_info->server_flags;
-
- /* FIXME: parent clone should do this */
- imapx_copy->info.content =
- camel_folder_summary_content_info_new (summary);
-
- return copy;
-}
-
-static void
-imapx_summary_emit_info_changed (CamelMessageInfo *info)
-{
- g_return_if_fail (info != NULL);
- g_return_if_fail (CAMEL_IS_IMAPX_SUMMARY (info->summary));
-
- g_signal_emit (info->summary, signals[INFO_CHANGED], 0, info);
-}
-
-static gboolean
-imapx_summary_info_set_user_flag (CamelMessageInfo *info,
- const gchar *id,
- gboolean state)
-{
- gboolean changed;
-
- /* Chain up to parent's method. */
- changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_user_flag (info,
id, state);
-
- if (changed)
- imapx_summary_emit_info_changed (info);
-
- return changed;
-}
-
-static gboolean
-imapx_summary_info_set_user_tag (CamelMessageInfo *info,
- const gchar *name,
- const gchar *value)
-{
- gboolean changed;
-
- /* Chain up to parent's method. */
- changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_user_tag (info,
name, value);
-
- if (changed)
- imapx_summary_emit_info_changed (info);
-
- return changed;
-}
-
-static gboolean
-imapx_summary_info_set_flags (CamelMessageInfo *info,
- guint32 flags,
- guint32 set)
-{
- gboolean changed;
-
- /* Chain up to parent's method. */
- changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_flags (info, flags,
set);
-
- if (changed)
- imapx_summary_emit_info_changed (info);
-
- return changed;
-}
-
static void
camel_imapx_summary_class_init (CamelIMAPXSummaryClass *class)
{
CamelFolderSummaryClass *folder_summary_class;
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelIMAPXMessageInfo);
- folder_summary_class->content_info_size = sizeof (CamelIMAPXMessageContentInfo);
+ folder_summary_class->message_info_type = CAMEL_TYPE_IMAPX_MESSAGE_INFO;
folder_summary_class->summary_header_from_db = imapx_summary_summary_header_from_db;
folder_summary_class->summary_header_to_db = imapx_summary_summary_header_to_db;
- folder_summary_class->message_info_from_db = imapx_summary_message_info_from_db;
- folder_summary_class->message_info_to_db = imapx_summary_message_info_to_db;
- folder_summary_class->content_info_from_db = imapx_summary_content_info_from_db;
- folder_summary_class->content_info_to_db = imapx_summary_content_info_to_db;
- folder_summary_class->message_info_free = imapx_summary_message_info_free;
- folder_summary_class->message_info_clone = imapx_summary_message_info_clone;
- folder_summary_class->info_set_user_flag = imapx_summary_info_set_user_flag;
- folder_summary_class->info_set_user_tag = imapx_summary_info_set_user_tag;
- folder_summary_class->info_set_flags = imapx_summary_info_set_flags;
-
- signals[INFO_CHANGED] = g_signal_new (
- "info-changed",
- G_OBJECT_CLASS_TYPE (class),
- G_SIGNAL_RUN_LAST,
- 0 /* G_STRUCT_OFFSET (CamelIMAPXSummaryClass, info_changed) */,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER /* CamelMessageInfo * */);
}
static void
@@ -401,8 +174,6 @@ camel_imapx_summary_new (CamelFolder *folder)
summary->collate = "imapx_uid_sort";
}
- camel_folder_summary_set_build_content (summary, TRUE);
-
if (!camel_folder_summary_load_from_db (summary, &local_error)) {
/* FIXME: Isn't this dangerous ? We clear the summary
if it cannot be loaded, for some random reason.
@@ -414,4 +185,3 @@ camel_imapx_summary_new (CamelFolder *folder)
return summary;
}
-
diff --git a/src/camel/providers/imapx/camel-imapx-summary.h b/src/camel/providers/imapx/camel-imapx-summary.h
index c515c19..0db09fa 100644
--- a/src/camel/providers/imapx/camel-imapx-summary.h
+++ b/src/camel/providers/imapx/camel-imapx-summary.h
@@ -55,20 +55,6 @@ G_BEGIN_DECLS
typedef struct _CamelIMAPXSummary CamelIMAPXSummary;
typedef struct _CamelIMAPXSummaryClass CamelIMAPXSummaryClass;
-typedef struct _CamelIMAPXMessageInfo CamelIMAPXMessageInfo;
-typedef struct _CamelIMAPXMessageContentInfo CamelIMAPXMessageContentInfo;
-
-struct _CamelIMAPXMessageContentInfo {
- CamelMessageContentInfo info;
-};
-
-struct _CamelIMAPXMessageInfo {
- CamelMessageInfoBase info;
-
- guint32 server_flags;
- CamelFlag *server_user_flags;
-};
-
struct _CamelIMAPXSummary {
CamelFolderSummary parent;
diff --git a/src/camel/providers/imapx/camel-imapx-utils.c b/src/camel/providers/imapx/camel-imapx-utils.c
index c60666d..6522db4 100644
--- a/src/camel/providers/imapx/camel-imapx-utils.c
+++ b/src/camel/providers/imapx/camel-imapx-utils.c
@@ -24,6 +24,7 @@
#include "camel-imapx-command.h"
#include "camel-imapx-folder.h"
+#include "camel-imapx-message-info.h"
#include "camel-imapx-settings.h"
#include "camel-imapx-summary.h"
#include "camel-imapx-store.h"
@@ -101,7 +102,7 @@ static struct {
gboolean
imapx_parse_flags (CamelIMAPXInputStream *stream,
guint32 *flagsp,
- CamelFlag **user_flagsp,
+ CamelNamedFlags *user_flags,
GCancellable *cancellable,
GError **error)
{
@@ -149,7 +150,7 @@ imapx_parse_flags (CamelIMAPXInputStream *stream,
}
}
- if (!match_found && user_flagsp != NULL) {
+ if (!match_found && user_flags) {
const gchar *flag_name;
gchar *utf8;
@@ -163,7 +164,7 @@ imapx_parse_flags (CamelIMAPXInputStream *stream,
utf8 = NULL;
}
- camel_flag_set (user_flagsp, utf8 ? utf8 : flag_name, TRUE);
+ camel_named_flags_insert (user_flags, utf8 ? utf8 : flag_name);
g_free (utf8);
}
@@ -225,44 +226,50 @@ rename_label_flag (const gchar *flag,
void
imapx_write_flags (GString *string,
guint32 flags,
- CamelFlag *user_flags)
+ const CamelNamedFlags *user_flags)
{
- gint i;
+ guint ii;
gboolean first = TRUE;
g_string_append_c (string, '(');
- for (i = 0; flags != 0 && i< G_N_ELEMENTS (flag_table); i++) {
- if (flag_table[i].flag & flags) {
- if (flag_table[i].flag & CAMEL_IMAPX_MESSAGE_RECENT)
+ for (ii = 0; flags != 0 && ii < G_N_ELEMENTS (flag_table); ii++) {
+ if (flag_table[ii].flag & flags) {
+ if (flag_table[ii].flag & CAMEL_IMAPX_MESSAGE_RECENT)
continue;
if (!first)
g_string_append_c (string, ' ');
first = FALSE;
- g_string_append (string, flag_table[i].name);
+ g_string_append (string, flag_table[ii].name);
- flags &= ~flag_table[i].flag;
+ flags &= ~flag_table[ii].flag;
}
}
- while (user_flags) {
- const gchar *flag_name;
- gchar *utf7;
+ if (user_flags) {
+ guint len = camel_named_flags_get_length (user_flags);
+
+ for (ii = 0; ii < len; ii++) {
+ const gchar *name = camel_named_flags_get (user_flags, ii);
+ const gchar *flag_name;
+ gchar *utf7;
- flag_name = rename_label_flag (
- user_flags->name, strlen (user_flags->name), FALSE);
+ if (!name || !*name)
+ continue;
- if (!first)
- g_string_append_c (string, ' ');
- first = FALSE;
- utf7 = camel_utf8_utf7 (flag_name);
+ flag_name = rename_label_flag (name, strlen (name), FALSE);
+
+ if (!first)
+ g_string_append_c (string, ' ');
+ first = FALSE;
- g_string_append (string, utf7 ? utf7 : flag_name);
+ utf7 = camel_utf8_utf7 (flag_name);
- g_free (utf7);
+ g_string_append (string, utf7 ? utf7 : flag_name);
- user_flags = user_flags->next;
+ g_free (utf7);
+ }
}
g_string_append_c (string, ')');
@@ -270,26 +277,38 @@ imapx_write_flags (GString *string,
static gboolean
imapx_update_user_flags (CamelMessageInfo *info,
- CamelFlag *server_user_flags)
+ const CamelNamedFlags *server_user_flags)
{
gboolean changed = FALSE;
- CamelMessageInfoBase *binfo = (CamelMessageInfoBase *) info;
- CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
+ const CamelNamedFlags *mi_user_flags;
gboolean set_cal = FALSE, set_note = FALSE;
- if (camel_flag_get (&binfo->user_flags, "$has_cal"))
+ mi_user_flags = camel_message_info_get_user_flags (info);
+ if (camel_named_flags_equal (mi_user_flags, server_user_flags)) {
+ mi_user_flags = camel_imapx_message_info_get_server_user_flags (CAMEL_IMAPX_MESSAGE_INFO
(info));
+
+ if (!camel_named_flags_equal (mi_user_flags, server_user_flags)) {
+ camel_imapx_message_info_take_server_user_flags (CAMEL_IMAPX_MESSAGE_INFO (info),
+ camel_named_flags_copy (server_user_flags));
+ }
+
+ return FALSE;
+ }
+
+ if (mi_user_flags && camel_named_flags_contains (mi_user_flags, "$has_cal"))
set_cal = TRUE;
- if (camel_flag_get (&binfo->user_flags, "$has_note"))
+ if (mi_user_flags && camel_named_flags_contains (mi_user_flags, "$has_note"))
set_note = TRUE;
- changed = camel_flag_list_copy (&binfo->user_flags, &server_user_flags);
- camel_flag_list_copy (&xinfo->server_user_flags, &server_user_flags);
+ changed = camel_message_info_take_user_flags (info, camel_named_flags_copy (server_user_flags));
+ camel_imapx_message_info_take_server_user_flags (CAMEL_IMAPX_MESSAGE_INFO (info),
+ camel_named_flags_copy (server_user_flags));
/* reset the flags as they were set in messageinfo before */
if (set_cal)
- camel_flag_set (&binfo->user_flags, "$has_cal", TRUE);
+ camel_message_info_set_user_flag (info, "$has_cal", TRUE);
if (set_note)
- camel_flag_set (&binfo->user_flags, "$has_note", TRUE);
+ camel_message_info_set_user_flag (info, "$has_note", TRUE);
return changed;
}
@@ -297,16 +316,16 @@ imapx_update_user_flags (CamelMessageInfo *info,
gboolean
imapx_update_message_info_flags (CamelMessageInfo *info,
guint32 server_flags,
- CamelFlag *server_user_flags,
+ const CamelNamedFlags *server_user_flags,
guint32 permanent_flags,
CamelFolder *folder,
gboolean unsolicited)
{
gboolean changed = FALSE;
- CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
+ CamelIMAPXMessageInfo *xinfo = CAMEL_IMAPX_MESSAGE_INFO (info);
/* Locally made changes should not be overwritten, it'll be (re)saved later */
- if ((camel_message_info_get_flags (info) & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0) {
+ if (camel_message_info_get_folder_flagged (info)) {
d ('?', "Skipping update of locally changed uid:'%s'\n", camel_message_info_get_uid (info));
return FALSE;
}
@@ -314,15 +333,21 @@ imapx_update_message_info_flags (CamelMessageInfo *info,
/* This makes sure that server flags has precedence from locally stored flags,
* thus a user actually sees what is stored on the server */
if ((camel_message_info_get_flags (info) & CAMEL_IMAPX_SERVER_FLAGS) != (server_flags &
CAMEL_IMAPX_SERVER_FLAGS)) {
- xinfo->server_flags = (xinfo->server_flags & ~CAMEL_IMAPX_SERVER_FLAGS) |
- (camel_message_info_get_flags (info) & CAMEL_IMAPX_SERVER_FLAGS);
+ guint32 old_server_flags;
+
+ old_server_flags = camel_imapx_message_info_get_server_flags (xinfo);
+
+ camel_imapx_message_info_set_server_flags (xinfo,
+ (old_server_flags & ~CAMEL_IMAPX_SERVER_FLAGS) |
+ (camel_message_info_get_flags (info) & CAMEL_IMAPX_SERVER_FLAGS));
}
- if (server_flags != xinfo->server_flags) {
- guint32 server_set, server_cleared;
+ if (server_flags != camel_imapx_message_info_get_server_flags (xinfo)) {
+ guint32 server_set, server_cleared, old_server_flags;
- server_set = server_flags & ~xinfo->server_flags;
- server_cleared = xinfo->server_flags & ~server_flags;
+ old_server_flags = camel_imapx_message_info_get_server_flags (xinfo);
+ server_set = server_flags & ~old_server_flags;
+ server_cleared = old_server_flags & ~server_flags;
/* Don't clear non-permanent server-side flags.
* This avoids overwriting local flags that we
@@ -330,13 +355,11 @@ imapx_update_message_info_flags (CamelMessageInfo *info,
if (permanent_flags > 0)
server_cleared &= permanent_flags;
- changed = camel_message_info_set_flags ((
- CamelMessageInfo *) xinfo,
+ changed = camel_message_info_set_flags (info,
server_set | server_cleared,
- (xinfo->info.flags | server_set) & ~server_cleared);
+ (camel_message_info_get_flags (info) | server_set) & ~server_cleared);
- xinfo->server_flags = server_flags;
- xinfo->info.dirty = TRUE;
+ camel_imapx_message_info_set_server_flags (xinfo, server_flags);
}
if ((permanent_flags & CAMEL_MESSAGE_USER) != 0 && imapx_update_user_flags (info, server_user_flags))
@@ -348,29 +371,22 @@ imapx_update_message_info_flags (CamelMessageInfo *info,
void
imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info,
guint32 server_flags,
- CamelFlag *server_user_flags,
+ const CamelNamedFlags *server_user_flags,
gboolean force_user_flags,
- CamelTag *user_tags,
+ const CamelNameValueArray *user_tags,
guint32 permanent_flags)
{
- CamelMessageInfoBase *binfo = (CamelMessageInfoBase *) info;
- CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info;
-
- binfo->flags |= server_flags;
- camel_message_info_set_flags (info, server_flags, binfo->flags | server_flags);
+ CamelIMAPXMessageInfo *xinfo = CAMEL_IMAPX_MESSAGE_INFO (info);
- xinfo->server_flags = server_flags;
+ camel_message_info_set_flags (info, server_flags, camel_message_info_get_flags (info) | server_flags);
+ camel_imapx_message_info_set_server_flags (xinfo, server_flags);
if (force_user_flags || (permanent_flags & CAMEL_MESSAGE_USER) != 0)
imapx_update_user_flags (info, server_user_flags);
- while (user_tags) {
- camel_message_info_set_user_tag (info, user_tags->name, user_tags->value);
- user_tags = user_tags->next;
- }
+ camel_message_info_take_user_tags (info, camel_name_value_array_copy (user_tags));
- binfo->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
- binfo->dirty = TRUE;
+ camel_message_info_set_folder_flagged (info, FALSE);
}
void
@@ -1150,7 +1166,7 @@ imapx_parse_address_list (CamelIMAPXInputStream *stream,
return list;
}
-struct _CamelMessageInfo *
+CamelMessageInfo *
imapx_parse_envelope (CamelIMAPXInputStream *stream,
GCancellable *cancellable,
GError **error)
@@ -1160,7 +1176,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
guchar *token;
CamelHeaderAddress *addr, *addr_from;
gchar *addrstr;
- struct _CamelMessageInfoBase *minfo = NULL;
+ CamelMessageInfo *info;
GError *local_error = NULL;
/* envelope ::= "(" env_date SPACE env_subject SPACE env_from
@@ -1168,7 +1184,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
* SPACE env_cc SPACE env_bcc SPACE env_in_reply_to
* SPACE env_message_id ")" */
- minfo = (CamelMessageInfoBase *) camel_message_info_new (NULL);
+ info = camel_message_info_new (NULL);
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
@@ -1178,7 +1194,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
if (tok != '(') {
g_clear_error (&local_error);
- camel_message_info_unref (minfo);
+ g_clear_object (&info);
g_set_error (error, CAMEL_IMAPX_ERROR, CAMEL_IMAPX_ERROR_SERVER_RESPONSE_MALFORMED,
"envelope: expecting '('");
return NULL;
}
@@ -1188,14 +1204,14 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
if (local_error)
goto error;
- minfo->date_sent = camel_header_decode_date ((gchar *) token, NULL);
+ camel_message_info_set_date_sent (info, camel_header_decode_date ((gchar *) token, NULL));
/* env_subject ::= nstring */
camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
if (local_error)
goto error;
- minfo->subject = camel_pstring_strdup ((gchar *) token);
+ camel_message_info_set_subject (info, (const gchar *) token);
/* we merge from/sender into from, append should probably merge more smartly? */
@@ -1218,7 +1234,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
if (addr_from) {
addrstr = camel_header_address_list_format (addr_from);
- minfo->from = camel_pstring_strdup (addrstr);
+ camel_message_info_set_from (info, addrstr);
g_free (addrstr);
camel_header_address_list_clear (&addr_from);
}
@@ -1236,7 +1252,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
addr = imapx_parse_address_list (stream, cancellable, &local_error);
if (addr) {
addrstr = camel_header_address_list_format (addr);
- minfo->to = camel_pstring_strdup (addrstr);
+ camel_message_info_set_to (info, addrstr);
g_free (addrstr);
camel_header_address_list_clear (&addr);
}
@@ -1248,7 +1264,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
addr = imapx_parse_address_list (stream, cancellable, &local_error);
if (addr) {
addrstr = camel_header_address_list_format (addr);
- minfo->cc = camel_pstring_strdup (addrstr);
+ camel_message_info_set_cc (info, addrstr);
g_free (addrstr);
camel_header_address_list_clear (&addr);
}
@@ -1285,7 +1301,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
if (tok != ')') {
g_clear_error (&local_error);
- camel_message_info_unref (minfo);
+ g_clear_object (&info);
g_set_error (error, CAMEL_IMAPX_ERROR, CAMEL_IMAPX_ERROR_SERVER_RESPONSE_MALFORMED,
"expecting ')'");
return NULL;
}
@@ -1294,15 +1310,14 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
/* CHEN TODO handle exceptions better */
if (local_error != NULL) {
g_propagate_error (error, local_error);
- if (minfo)
- camel_message_info_unref (minfo);
+ g_clear_object (&info);
return NULL;
}
- return (CamelMessageInfo *) minfo;
+ return info;
}
-struct _CamelMessageContentInfo *
+CamelMessageContentInfo *
imapx_parse_body (CamelIMAPXInputStream *stream,
GCancellable *cancellable,
GError **error)
@@ -1449,7 +1464,7 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
/* what do we do with the message content info?? */
//((CamelMessageInfoBase *) minfo)->content = imapx_parse_body (stream);
- camel_message_info_unref (minfo);
+ g_clear_object (&minfo);
minfo = NULL;
}
@@ -1673,11 +1688,10 @@ imapx_free_fetch (struct _fetch_info *finfo)
g_bytes_unref (finfo->text);
if (finfo->header)
g_bytes_unref (finfo->header);
- if (finfo->minfo)
- camel_message_info_unref (finfo->minfo);
if (finfo->cinfo)
imapx_free_body (finfo->cinfo);
- camel_flag_list_free (&finfo->user_flags);
+ camel_named_flags_free (finfo->user_flags);
+ g_clear_object (&finfo->minfo);
g_free (finfo->date);
g_free (finfo->section);
g_free (finfo->uid);
@@ -1853,7 +1867,7 @@ imapx_parse_fetch_flags (CamelIMAPXInputStream *stream,
gboolean success;
success = imapx_parse_flags (
- stream, &finfo->flags, &finfo->user_flags,
+ stream, &finfo->flags, finfo->user_flags,
cancellable, error);
if (success)
@@ -2003,6 +2017,7 @@ imapx_parse_fetch (CamelIMAPXInputStream *stream,
struct _fetch_info *finfo;
finfo = g_malloc0 (sizeof (*finfo));
+ finfo->user_flags = camel_named_flags_new ();
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, error);
diff --git a/src/camel/providers/imapx/camel-imapx-utils.h b/src/camel/providers/imapx/camel-imapx-utils.h
index 7fc055b..d9d7e34 100644
--- a/src/camel/providers/imapx/camel-imapx-utils.h
+++ b/src/camel/providers/imapx/camel-imapx-utils.h
@@ -30,7 +30,6 @@ G_BEGIN_DECLS
* enum/struct definitions and helper macros, so we don't
* have these conflicting header dependencies. */
struct _CamelIMAPXCommand;
-struct _CamelFlag;
struct _CamelIMAPXStore;
/* list of strings we know about that can be *quickly* tokenised */
@@ -136,24 +135,24 @@ GArray * imapx_parse_uids (CamelIMAPXInputStream *stream,
GError **error);
gboolean imapx_parse_flags (CamelIMAPXInputStream *stream,
guint32 *flagsp,
- struct _CamelFlag **user_flagsp,
+ CamelNamedFlags *user_flags,
GCancellable *cancellable,
GError **error);
void imapx_write_flags (GString *string,
guint32 flags,
- struct _CamelFlag *user_flags);
+ const CamelNamedFlags *user_flags);
gboolean imapx_update_message_info_flags (CamelMessageInfo *info,
guint32 server_flags,
- CamelFlag *server_user_flags,
+ const CamelNamedFlags *server_user_flags,
guint32 permanent_flags,
CamelFolder *folder,
gboolean unsolicited);
void imapx_set_message_info_flags_for_new_message
(CamelMessageInfo *info,
guint32 server_flags,
- CamelFlag *server_user_flags,
+ const CamelNamedFlags *server_user_flags,
gboolean force_user_flags,
- CamelTag *user_tags,
+ const CamelNameValueArray *user_tags,
guint32 permanent_flags);
void imapx_update_store_summary (CamelFolder *folder);
@@ -218,11 +217,11 @@ CamelHeaderAddress *
imapx_parse_address_list (CamelIMAPXInputStream *stream,
GCancellable *cancellable,
GError **error);
-struct _CamelMessageInfo *
+CamelMessageInfo *
imapx_parse_envelope (CamelIMAPXInputStream *stream,
GCancellable *cancellable,
GError **error);
-struct _CamelMessageContentInfo *
+CamelMessageContentInfo *
imapx_parse_body (CamelIMAPXInputStream *stream,
GCancellable *cancellable,
GError **error);
@@ -245,7 +244,7 @@ struct _fetch_info {
guint32 offset; /* start offset of a BODY[]<offset.length> request */
guint32 flags; /* FLAGS */
guint64 modseq; /* MODSEQ */
- CamelFlag *user_flags;
+ CamelNamedFlags *user_flags;
gchar *date; /* INTERNALDATE */
gchar *section; /* section for a BODY[section] request */
gchar *uid; /* UID */
diff --git a/src/camel/providers/local/CMakeLists.txt b/src/camel/providers/local/CMakeLists.txt
index 169e489..24afeb4 100644
--- a/src/camel/providers/local/CMakeLists.txt
+++ b/src/camel/providers/local/CMakeLists.txt
@@ -10,12 +10,16 @@ set(SOURCES
camel-local-provider.c
camel-maildir-folder.c
camel-maildir-folder.h
+ camel-maildir-message-info.c
+ camel-maildir-message-info.h
camel-maildir-store.c
camel-maildir-store.h
camel-maildir-summary.c
camel-maildir-summary.h
camel-mbox-folder.c
camel-mbox-folder.h
+ camel-mbox-message-info.c
+ camel-mbox-message-info.h
camel-mbox-store.c
camel-mbox-store.h
camel-mbox-summary.c
diff --git a/src/camel/providers/local/camel-local-summary.c b/src/camel/providers/local/camel-local-summary.c
index 9fee506..8b86dfd 100644
--- a/src/camel/providers/local/camel-local-summary.c
+++ b/src/camel/providers/local/camel-local-summary.c
@@ -37,8 +37,6 @@
#define CAMEL_LOCAL_SUMMARY_VERSION (1)
-#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
-
static CamelFIRecord *
summary_header_to_db (CamelFolderSummary *,
GError **error);
@@ -47,15 +45,15 @@ static gboolean summary_header_from_db (CamelFolderSummary *,
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *,
- struct _camel_header_raw *);
+ CamelHeaderRaw *);
static gint local_summary_decode_x_evolution
(CamelLocalSummary *cls,
const gchar *xev,
- CamelLocalMessageInfo *mi);
+ CamelMessageInfo *mi);
static gchar * local_summary_encode_x_evolution
(CamelLocalSummary *cls,
- const CamelLocalMessageInfo *mi);
+ const CamelMessageInfo *mi);
static gint local_summary_load (CamelLocalSummary *cls,
gint forceindex,
@@ -119,8 +117,6 @@ camel_local_summary_class_init (CamelLocalSummaryClass *class)
object_class->finalize = local_summary_finalize;
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelLocalMessageInfo);
- folder_summary_class->content_info_size = sizeof (CamelMessageContentInfo);
folder_summary_class->summary_header_from_db = summary_header_from_db;
folder_summary_class->summary_header_to_db = summary_header_to_db;
folder_summary_class->message_info_new_from_header = message_info_new_from_header;
@@ -150,7 +146,6 @@ camel_local_summary_construct (CamelLocalSummary *new,
const gchar *local_name,
CamelIndex *index)
{
- camel_folder_summary_set_build_content (CAMEL_FOLDER_SUMMARY (new), FALSE);
new->folder_path = g_strdup (local_name);
new->index = index;
if (index)
@@ -195,7 +190,7 @@ void camel_local_summary_check_force (CamelLocalSummary *cls)
gchar *
camel_local_summary_encode_x_evolution (CamelLocalSummary *cls,
- const CamelLocalMessageInfo *info)
+ const CamelMessageInfo *info)
{
return CAMEL_LOCAL_SUMMARY_GET_CLASS (cls)->encode_x_evolution (cls, info);
}
@@ -203,7 +198,7 @@ camel_local_summary_encode_x_evolution (CamelLocalSummary *cls,
gint
camel_local_summary_decode_x_evolution (CamelLocalSummary *cls,
const gchar *xev,
- CamelLocalMessageInfo *info)
+ CamelMessageInfo *info)
{
return CAMEL_LOCAL_SUMMARY_GET_CLASS (cls)->decode_x_evolution (cls, xev, info);
}
@@ -315,7 +310,7 @@ camel_local_summary_check (CamelLocalSummary *cls,
for (i = 0; i < camel_folder_summary_count (s); i++) {
CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids,
i));
do_stat_mi (cls, &stats, info);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_folder_summary_free_array (known_uids);
@@ -392,7 +387,7 @@ camel_local_summary_add (CamelLocalSummary *cls,
**/
gint
camel_local_summary_write_headers (gint fd,
- struct _camel_header_raw *header,
+ CamelHeaderRaw *header,
const gchar *xevline,
const gchar *status,
const gchar *xstatus)
@@ -516,34 +511,20 @@ local_summary_add (CamelLocalSummary *cls,
{
CamelFolderSummary *summary;
CamelMessageInfo *mi;
- CamelMessageInfoBase *mi_base;
gchar *xev;
d (printf ("Adding message to summary\n"));
summary = CAMEL_FOLDER_SUMMARY (cls);
- mi = camel_folder_summary_info_new_from_message (summary, msg, NULL);
- camel_folder_summary_add (summary, mi);
-
- mi_base = (CamelMessageInfoBase *) mi;
+ mi = camel_folder_summary_info_new_from_message (summary, msg);
+ camel_message_info_set_abort_notifications (mi, TRUE);
if (info) {
- const CamelTag *tag = camel_message_info_get_user_tags (info);
- const CamelFlag *flag = camel_message_info_get_user_flags (info);
-
- while (flag) {
- camel_message_info_set_user_flag (mi, flag->name, TRUE);
- flag = flag->next;
- }
-
- while (tag) {
- camel_message_info_set_user_tag (mi, tag->name, tag->value);
- tag = tag->next;
- }
-
- camel_message_info_set_flags (mi, 0xffff, camel_message_info_get_flags (info));
- mi_base->size = camel_message_info_get_size (info);
+ camel_message_info_take_user_flags (mi, camel_message_info_dup_user_flags (info));
+ camel_message_info_take_user_tags (mi, camel_message_info_dup_user_tags (info));
+ camel_message_info_set_flags (mi, ~0, camel_message_info_get_flags (info));
+ camel_message_info_set_size (mi, camel_message_info_get_size (info));
}
/* we need to calculate the size ourselves */
@@ -553,15 +534,17 @@ local_summary_add (CamelLocalSummary *cls,
camel_data_wrapper_write_to_stream_sync (
(CamelDataWrapper *) msg,
(CamelStream *) sn, NULL, NULL);
- mi_base->size = sn->written;
+ camel_message_info_set_size (mi, sn->written);
g_object_unref (sn);
}
- mi_base->flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV);
- xev = camel_local_summary_encode_x_evolution (
- cls, (CamelLocalMessageInfo *) mi);
+ camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_NOXEV, 0);
+ xev = camel_local_summary_encode_x_evolution (cls, mi);
camel_medium_set_header ((CamelMedium *) msg, "X-Evolution", xev);
g_free (xev);
+
+ camel_message_info_set_abort_notifications (mi, FALSE);
+ camel_folder_summary_add (summary, mi, FALSE);
camel_folder_change_info_add_uid (ci, camel_message_info_get_uid (mi));
return mi;
@@ -569,65 +552,86 @@ local_summary_add (CamelLocalSummary *cls,
static gchar *
local_summary_encode_x_evolution (CamelLocalSummary *cls,
- const CamelLocalMessageInfo *mi)
+ const CamelMessageInfo *mi)
{
GString *out = g_string_new ("");
struct _camel_header_param *params = NULL;
- CamelFlag *flag = mi->info.user_flags;
- CamelTag *tag = mi->info.user_tags;
+ guint32 flags;
+ const CamelNamedFlags *user_flags;
+ const CamelNameValueArray *user_tags;
gchar *ret;
const gchar *p, *uidstr;
guint32 uid;
+ camel_message_info_property_lock (mi);
+
/* FIXME: work out what to do with uid's that aren't stored here? */
/* FIXME: perhaps make that a mbox folder only issue?? */
p = uidstr = camel_message_info_get_uid (mi);
+ flags = camel_message_info_get_flags (mi);
while (*p && isdigit (*p))
p++;
if (*p == 0 && sscanf (uidstr, "%u", &uid) == 1) {
- g_string_printf (out, "%08x-%04x", uid, mi->info.flags & 0xffff);
+ g_string_printf (out, "%08x-%04x", uid, flags & 0xffff);
} else {
- g_string_printf (out, "%s-%04x", uidstr, mi->info.flags & 0xffff);
+ g_string_printf (out, "%s-%04x", uidstr, flags & 0xffff);
}
- if (flag || tag) {
+ user_flags = camel_message_info_get_user_flags (mi);
+ user_tags = camel_message_info_get_user_tags (mi);
+
+ if (user_flags || user_tags) {
GString *val = g_string_new ("");
+ const gchar *name, *value;
+ guint ii, len;
+
+ len = camel_named_flags_get_length (user_flags);
+ if (len) {
+ for (ii = 0; ii < len; ii++) {
+ name = camel_named_flags_get (user_flags, ii);
+ if (!name)
+ continue;
- if (flag) {
- while (flag) {
- g_string_append (val, flag->name);
- if (flag->next)
+ if (val->len)
g_string_append_c (val, ',');
- flag = flag->next;
+ g_string_append (val, name);
}
camel_header_set_param (¶ms, "flags", val->str);
g_string_truncate (val, 0);
}
- if (tag) {
- while (tag) {
- g_string_append (val, tag->name);
- g_string_append_c (val, '=');
- g_string_append (val, tag->value);
- if (tag->next)
+
+ len = camel_name_value_array_get_length (user_tags);
+ if (len) {
+ for (ii = 0; ii < len; ii++) {
+ if (!camel_name_value_array_get (user_tags, ii, &name, &value))
+ continue;
+
+ if (val->len)
g_string_append_c (val, ',');
- tag = tag->next;
+
+ g_string_append (val, name);
+ g_string_append_c (val, '=');
+ g_string_append (val, value);
}
camel_header_set_param (¶ms, "tags", val->str);
}
g_string_free (val, TRUE);
+
camel_header_param_list_format_append (out, params);
camel_header_param_list_free (params);
}
ret = out->str;
g_string_free (out, FALSE);
+ camel_message_info_property_unlock (mi);
+
return ret;
}
static gint
local_summary_decode_x_evolution (CamelLocalSummary *cls,
const gchar *xev,
- CamelLocalMessageInfo *mi)
+ CamelMessageInfo *mi)
{
struct _camel_header_param *params, *scan;
guint32 uid, flags;
@@ -662,7 +666,7 @@ local_summary_decode_x_evolution (CamelLocalSummary *cls,
gchar **flagv = g_strsplit (scan->value, ",", 1000);
for (i = 0; flagv[i]; i++)
- camel_message_info_set_user_flag ((CamelMessageInfo *) mi, flagv[i],
TRUE);
+ camel_message_info_set_user_flag (mi, flagv[i], TRUE);
g_strfreev (flagv);
} else if (!g_ascii_strcasecmp (scan->name, "tags")) {
gchar **tagv = g_strsplit (scan->value, ",", 10000);
@@ -672,7 +676,7 @@ local_summary_decode_x_evolution (CamelLocalSummary *cls,
val = strchr (tagv[i], '=');
if (val) {
*val++ = 0;
- camel_message_info_set_user_tag ((CamelMessageInfo *) mi,
tagv[i], val);
+ camel_message_info_set_user_tag (mi, tagv[i], val);
val[-1]='=';
}
}
@@ -683,8 +687,8 @@ local_summary_decode_x_evolution (CamelLocalSummary *cls,
camel_header_param_list_free (params);
}
- mi->info.uid = camel_pstring_strdup (uidstr);
- mi->info.flags = flags;
+ camel_message_info_set_uid (mi, uidstr);
+ camel_message_info_set_flags (mi, ~0, flags);
return 0;
}
@@ -703,7 +707,7 @@ summary_header_from_db (CamelFolderSummary *s,
part = fir->bdata;
if (part) {
- EXTRACT_FIRST_DIGIT (cls->version)
+ cls->version = camel_util_bdata_get_number (&part, 0);
}
/* keep only the rest of the bdata there (strip our version digit) */
@@ -732,23 +736,27 @@ summary_header_to_db (CamelFolderSummary *s,
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *s,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
- CamelLocalMessageInfo *mi;
+ CamelMessageInfo *mi;
CamelLocalSummary *cls = (CamelLocalSummary *) s;
- mi = (CamelLocalMessageInfo *) CAMEL_FOLDER_SUMMARY_CLASS
(camel_local_summary_parent_class)->message_info_new_from_header (s, h);
+ mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_local_summary_parent_class)->message_info_new_from_header (s,
h);
if (mi) {
const gchar *xev;
gint doindex = FALSE;
xev = camel_header_raw_find (&h, "X-Evolution", NULL);
if (xev == NULL || camel_local_summary_decode_x_evolution (cls, xev, mi) == -1) {
+ gchar *uid;
+
+ uid = camel_folder_summary_next_uid_string (s);
+
/* to indicate it has no xev header */
- mi->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
- mi->info.dirty = TRUE;
- camel_pstring_free (mi->info.uid);
- mi->info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s), TRUE);
+ camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_FLAGGED |
CAMEL_MESSAGE_FOLDER_NOXEV, CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV);
+ camel_message_info_set_uid (mi, uid);
+
+ g_free (uid);
/* shortcut, no need to look it up in the index library */
doindex = TRUE;
@@ -766,5 +774,5 @@ message_info_new_from_header (CamelFolderSummary *s,
}
}
- return (CamelMessageInfo *) mi;
+ return mi;
}
diff --git a/src/camel/providers/local/camel-local-summary.h b/src/camel/providers/local/camel-local-summary.h
index 496b787..cd230e5 100644
--- a/src/camel/providers/local/camel-local-summary.h
+++ b/src/camel/providers/local/camel-local-summary.h
@@ -52,12 +52,6 @@ enum {
CAMEL_MESSAGE_FOLDER_NOTSEEN = 1 << 19 /* have we seen this in processing this loop? */
};
-typedef struct _CamelLocalMessageInfo CamelLocalMessageInfo;
-
-struct _CamelLocalMessageInfo {
- CamelMessageInfoBase info;
-};
-
struct _CamelLocalSummary {
CamelFolderSummary parent;
@@ -78,8 +72,8 @@ struct _CamelLocalSummaryClass {
gint (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo,
GCancellable *cancellable, GError **error);
CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info,
CamelFolderChangeInfo *, GError **error);
- gchar *(*encode_x_evolution)(CamelLocalSummary *cls, const CamelLocalMessageInfo *info);
- gint (*decode_x_evolution)(CamelLocalSummary *cls, const gchar *xev, CamelLocalMessageInfo *info);
+ gchar *(*encode_x_evolution)(CamelLocalSummary *cls, const CamelMessageInfo *info);
+ gint (*decode_x_evolution)(CamelLocalSummary *cls, const gchar *xev, CamelMessageInfo *info);
gint (*need_index)(void);
};
@@ -99,11 +93,11 @@ CamelMessageInfo *camel_local_summary_add (CamelLocalSummary *cls, CamelMimeMess
void camel_local_summary_check_force (CamelLocalSummary *cls);
/* generate an X-Evolution header line */
-gchar *camel_local_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelLocalMessageInfo *info);
-gint camel_local_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev, CamelLocalMessageInfo
*info);
+gchar *camel_local_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelMessageInfo *info);
+gint camel_local_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev, CamelMessageInfo
*info);
/* utility functions - write headers to a file with optional X-Evolution header and/or status header */
-gint camel_local_summary_write_headers (gint fd, struct _camel_header_raw *header, const gchar *xevline,
const gchar *status, const gchar *xstatus);
+gint camel_local_summary_write_headers (gint fd, CamelHeaderRaw *header, const gchar *xevline, const gchar
*status, const gchar *xstatus);
G_END_DECLS
diff --git a/src/camel/providers/local/camel-maildir-folder.c
b/src/camel/providers/local/camel-maildir-folder.c
index 7ec56fd..cfc9656 100644
--- a/src/camel/providers/local/camel-maildir-folder.c
+++ b/src/camel/providers/local/camel-maildir-folder.c
@@ -56,9 +56,9 @@ maildir_folder_cmp_uids (CamelFolder *folder,
if (!a || !b) {
/* It's not a problem when one of the messages is not in the summary */
if (a)
- camel_message_info_unref (a);
+ g_object_unref (a);
if (b)
- camel_message_info_unref (b);
+ g_object_unref (b);
if (a == b)
return 0;
@@ -70,8 +70,8 @@ maildir_folder_cmp_uids (CamelFolder *folder,
tma = camel_message_info_get_date_received (a);
tmb = camel_message_info_get_date_received (b);
- camel_message_info_unref (a);
- camel_message_info_unref (b);
+ g_clear_object (&a);
+ g_clear_object (&b);
return tma < tmb ? -1 : tma == tmb ? 0 : 1;
}
@@ -108,13 +108,13 @@ maildir_folder_get_filename (CamelFolder *folder,
return NULL;
}
- mdi = (CamelMaildirMessageInfo *) info;
+ mdi = CAMEL_MAILDIR_MESSAGE_INFO (info);
/* If filename is NULL, it means folder_summary_check is not yet executed.
* Try to find the file in the folder and use it, otherwise construct its
* name based on actual flags.
*/
- if (!camel_maildir_info_filename (mdi)) {
+ if (!camel_maildir_message_info_get_filename (mdi)) {
const gchar *uid = camel_message_info_get_uid (info);
if (uid) {
@@ -131,7 +131,7 @@ maildir_folder_get_filename (CamelFolder *folder,
while (filename = g_dir_read_name (dir), filename) {
if (g_str_has_prefix (filename, uid) && (filename[uid_len] == '\0' ||
filename[uid_len] == CAMEL_MAILDIR_FLAG_SEP)) {
- camel_maildir_info_set_filename (mdi, g_strdup (filename));
+ camel_maildir_message_info_take_filename (mdi, g_strdup
(filename));
break;
}
}
@@ -140,14 +140,14 @@ maildir_folder_get_filename (CamelFolder *folder,
}
}
- if (!camel_maildir_info_filename (mdi)) {
- camel_maildir_info_set_filename (mdi, camel_maildir_summary_info_to_name (mdi));
+ if (!camel_maildir_message_info_get_filename (mdi)) {
+ camel_maildir_message_info_take_filename (mdi, camel_maildir_summary_info_to_name
(info));
}
}
- res = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi));
+ res = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_message_info_get_filename (mdi));
- camel_message_info_unref (info);
+ g_clear_object (&info);
return res;
}
@@ -203,7 +203,7 @@ maildir_folder_append_message_sync (CamelFolder *folder,
goto fail_write;
/* now move from tmp to cur (bypass new, does it matter?) */
- dest = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi));
+ dest = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_message_info_get_filename (mdi));
if (g_rename (name, dest) == -1) {
g_set_error (
error, G_IO_ERROR,
@@ -250,6 +250,8 @@ maildir_folder_append_message_sync (CamelFolder *folder,
camel_folder_change_info_clear (lf->changes);
}
+ g_clear_object (&mi);
+
return success;
}
@@ -344,10 +346,10 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
}
mdi = (CamelMaildirMessageInfo *) info;
- new_filename = camel_maildir_summary_info_to_name (mdi);
+ new_filename = camel_maildir_summary_info_to_name (info);
d_filename = g_strdup_printf ("%s/cur/%s", df->folder_path, new_filename);
- s_filename = g_strdup_printf ("%s/cur/%s", lf->folder_path,
camel_maildir_info_filename (mdi));
+ s_filename = g_strdup_printf ("%s/cur/%s", lf->folder_path,
camel_maildir_message_info_get_filename (mdi));
if (g_rename (s_filename, d_filename) != 0) {
if (errno == EXDEV) {
@@ -359,7 +361,7 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
g_io_error_from_errno (errno),
_("Cannot transfer message to destination folder: %s"),
g_strerror (errno));
- camel_message_info_unref (info);
+ g_clear_object (&info);
g_free (s_filename);
g_free (d_filename);
g_free (new_filename);
@@ -367,22 +369,17 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
}
} else {
CamelMessageInfo *clone;
- CamelMaildirMessageInfo *mclone;
- clone = camel_message_info_clone (info);
- clone->summary = dest->summary;
+ clone = camel_message_info_clone (info, dest->summary);
- mclone = (CamelMaildirMessageInfo *) clone;
- /* preserve also UID, as it matches the file name */
- mclone->info.info.uid = camel_pstring_strdup (camel_message_info_get_uid
(info));
- camel_maildir_info_set_filename (clone, g_strdup (new_filename));
+ camel_maildir_message_info_set_filename (CAMEL_MAILDIR_MESSAGE_INFO (clone),
new_filename);
/* unset deleted flag when transferring from trash folder */
if ((source->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0)
camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, 0);
/* unset junk flag when transferring from junk folder */
if ((source->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0)
camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK, 0);
- camel_folder_summary_add (dest->summary, clone);
+ camel_folder_summary_add (dest->summary, clone, FALSE);
camel_folder_change_info_add_uid (df->changes, camel_message_info_get_uid
(clone));
@@ -391,9 +388,10 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
CAMEL_MESSAGE_SEEN, ~0);
camel_folder_change_info_remove_uid (lf->changes, camel_message_info_get_uid
(info));
camel_folder_summary_remove (source->summary, info);
+ g_clear_object (&clone);
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
g_free (s_filename);
g_free (d_filename);
g_free (new_filename);
diff --git a/src/camel/providers/local/camel-maildir-message-info.c
b/src/camel/providers/local/camel-maildir-message-info.c
new file mode 100644
index 0000000..7d85cc9
--- /dev/null
+++ b/src/camel/providers/local/camel-maildir-message-info.c
@@ -0,0 +1,251 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "camel/camel.h"
+#include "camel-maildir-summary.h"
+
+#include "camel-maildir-message-info.h"
+
+struct _CamelMaildirMessageInfoPrivate {
+ gchar *filename;
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME
+};
+
+G_DEFINE_TYPE (CamelMaildirMessageInfo, camel_maildir_message_info, CAMEL_TYPE_MESSAGE_INFO_BASE)
+
+static CamelMessageInfo *
+maildir_message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfo *result;
+
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mi), NULL);
+
+ result = CAMEL_MESSAGE_INFO_CLASS (camel_maildir_message_info_parent_class)->clone (mi,
assign_summary);
+ if (!result)
+ return NULL;
+
+ if (CAMEL_IS_MAILDIR_MESSAGE_INFO (result)) {
+ CamelMaildirMessageInfo *mmi, *mmi_result;
+
+ mmi = CAMEL_MAILDIR_MESSAGE_INFO (mi);
+ mmi_result = CAMEL_MAILDIR_MESSAGE_INFO (result);
+
+ /* safe-guard that the mmi's filename doesn't change before it's copied to mmi_result */
+ camel_message_info_property_lock (mi);
+
+ camel_maildir_message_info_set_filename (mmi_result, camel_maildir_message_info_get_filename
(mmi));
+
+ camel_message_info_property_unlock (mi);
+ }
+
+ return result;
+}
+
+static gboolean
+maildir_message_info_load (CamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ CamelMaildirMessageInfo *mmi;
+
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!CAMEL_MESSAGE_INFO_CLASS (camel_maildir_message_info_parent_class)->load ||
+ !CAMEL_MESSAGE_INFO_CLASS (camel_maildir_message_info_parent_class)->load (mi, record, bdata_ptr))
+ return FALSE;
+
+ mmi = CAMEL_MAILDIR_MESSAGE_INFO (mi);
+
+ camel_maildir_message_info_take_filename (mmi, camel_maildir_summary_info_to_name (mi));
+
+ return TRUE;
+}
+
+static void
+maildir_message_info_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMaildirMessageInfo *mmi = CAMEL_MAILDIR_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_FILENAME:
+ camel_maildir_message_info_set_filename (mmi, g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+maildir_message_info_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMaildirMessageInfo *mmi = CAMEL_MAILDIR_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, camel_maildir_message_info_get_filename (mmi));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+maildir_message_info_dispose (GObject *object)
+{
+ CamelMaildirMessageInfo *mmi = CAMEL_MAILDIR_MESSAGE_INFO (object);
+
+ g_free (mmi->priv->filename);
+ mmi->priv->filename = NULL;
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_maildir_message_info_parent_class)->dispose (object);
+}
+
+static void
+camel_maildir_message_info_class_init (CamelMaildirMessageInfoClass *class)
+{
+ CamelMessageInfoClass *mi_class;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelMaildirMessageInfoPrivate));
+
+ mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
+ mi_class->clone = maildir_message_info_clone;
+ mi_class->load = maildir_message_info_load;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = maildir_message_info_set_property;
+ object_class->get_property = maildir_message_info_get_property;
+ object_class->dispose = maildir_message_info_dispose;
+
+ /**
+ * CamelMaildirMessageInfo:filename
+ *
+ * File name of the message on the disk.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_FILENAME,
+ g_param_spec_string (
+ "filename",
+ "Filename",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+camel_maildir_message_info_init (CamelMaildirMessageInfo *mmi)
+{
+ mmi->priv = G_TYPE_INSTANCE_GET_PRIVATE (mmi, CAMEL_TYPE_MAILDIR_MESSAGE_INFO,
CamelMaildirMessageInfoPrivate);
+}
+
+const gchar *
+camel_maildir_message_info_get_filename (const CamelMaildirMessageInfo *mmi)
+{
+ CamelMessageInfo *mi;
+ const gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mmi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (mmi);
+
+ camel_message_info_property_lock (mi);
+ result = mmi->priv->filename;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gchar *
+camel_maildir_message_info_dup_filename (const CamelMaildirMessageInfo *mmi)
+{
+ CamelMessageInfo *mi;
+ gchar *result;
+
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mmi), NULL);
+
+ mi = CAMEL_MESSAGE_INFO (mmi);
+
+ camel_message_info_property_lock (mi);
+ result = g_strdup (mmi->priv->filename);
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gboolean
+camel_maildir_message_info_set_filename (CamelMaildirMessageInfo *mmi,
+ const gchar *filename)
+{
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mmi), FALSE);
+
+ return camel_maildir_message_info_take_filename (mmi, g_strdup (filename));
+}
+
+gboolean
+camel_maildir_message_info_take_filename (CamelMaildirMessageInfo *mmi,
+ gchar *filename)
+{
+ CamelMessageInfo *mi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MAILDIR_MESSAGE_INFO (mmi), FALSE);
+
+ mi = CAMEL_MESSAGE_INFO (mmi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = g_strcmp0 (mmi->priv->filename, filename) != 0;
+
+ if (changed) {
+ g_free (mmi->priv->filename);
+ mmi->priv->filename = filename;
+ } else if (filename != mmi->priv->filename) {
+ g_free (filename);
+ }
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !camel_message_info_get_abort_notifications (mi)) {
+ g_object_notify (G_OBJECT (mmi), "filename");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
diff --git a/src/camel/providers/local/camel-maildir-message-info.h
b/src/camel/providers/local/camel-maildir-message-info.h
new file mode 100644
index 0000000..226bf50
--- /dev/null
+++ b/src/camel/providers/local/camel-maildir-message-info.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAMEL_MAILDIR_MESSAGE_INFO_H
+#define CAMEL_MAILDIR_MESSAGE_INFO_H
+
+#include <glib-object.h>
+
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_MAILDIR_MESSAGE_INFO \
+ (camel_maildir_message_info_get_type ())
+#define CAMEL_MAILDIR_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_MAILDIR_MESSAGE_INFO, CamelMaildirMessageInfo))
+#define CAMEL_MAILDIR_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_MAILDIR_MESSAGE_INFO, CamelMaildirMessageInfoClass))
+#define CAMEL_IS_MAILDIR_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_MAILDIR_MESSAGE_INFO))
+#define CAMEL_IS_MAILDIR_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_MAILDIR_MESSAGE_INFO))
+#define CAMEL_MAILDIR_MESSAGE_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_MAILDIR_MESSAGE_INFO, CamelMaildirMessageInfoClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelMaildirMessageInfo CamelMaildirMessageInfo;
+typedef struct _CamelMaildirMessageInfoClass CamelMaildirMessageInfoClass;
+typedef struct _CamelMaildirMessageInfoPrivate CamelMaildirMessageInfoPrivate;
+
+struct _CamelMaildirMessageInfo {
+ CamelMessageInfoBase parent;
+ CamelMaildirMessageInfoPrivate *priv;
+};
+
+struct _CamelMaildirMessageInfoClass {
+ CamelMessageInfoBaseClass parent_class;
+};
+
+GType camel_maildir_message_info_get_type (void);
+
+const gchar * camel_maildir_message_info_get_filename (const CamelMaildirMessageInfo *mmi);
+gchar * camel_maildir_message_info_dup_filename (const CamelMaildirMessageInfo *mmi);
+gboolean camel_maildir_message_info_set_filename (CamelMaildirMessageInfo *mmi,
+ const gchar *filename);
+gboolean camel_maildir_message_info_take_filename
+ (CamelMaildirMessageInfo *mmi,
+ gchar *filename);
+
+G_END_DECLS
+
+#endif /* CAMEL_MAILDIR_MESSAGE_INFO_H */
diff --git a/src/camel/providers/local/camel-maildir-summary.c
b/src/camel/providers/local/camel-maildir-summary.c
index 2c5a56b..9f7aa6a 100644
--- a/src/camel/providers/local/camel-maildir-summary.c
+++ b/src/camel/providers/local/camel-maildir-summary.c
@@ -36,6 +36,7 @@
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
+#include "camel-maildir-message-info.h"
#include "camel-maildir-summary.h"
#define CAMEL_MAILDIR_SUMMARY_GET_PRIVATE(obj) \
@@ -48,13 +49,7 @@
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *,
- struct _camel_header_raw *);
-static CamelMessageInfo *
- maildir_message_info_from_db (CamelFolderSummary *summary,
- CamelMIRecord *record);
-static void message_info_free (CamelFolderSummary *,
- CamelMessageInfo *mi);
-
+ CamelHeaderRaw *);
static gint maildir_summary_load (CamelLocalSummary *cls,
gint forceindex,
GError **error);
@@ -78,10 +73,10 @@ static gchar * maildir_summary_next_uid_string (CamelFolderSummary *s);
static gint maildir_summary_decode_x_evolution
(CamelLocalSummary *cls,
const gchar *xev,
- CamelLocalMessageInfo *mi);
+ CamelMessageInfo *mi);
static gchar * maildir_summary_encode_x_evolution
(CamelLocalSummary *cls,
- const CamelLocalMessageInfo *mi);
+ const CamelMessageInfo *mi);
typedef struct _CamelMaildirMessageContentInfo CamelMaildirMessageContentInfo;
@@ -129,11 +124,8 @@ camel_maildir_summary_class_init (CamelMaildirSummaryClass *class)
object_class->finalize = maildir_summary_finalize;
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelMaildirMessageInfo);
- folder_summary_class->content_info_size = sizeof (CamelMaildirMessageContentInfo);
+ folder_summary_class->message_info_type = CAMEL_TYPE_MAILDIR_MESSAGE_INFO;
folder_summary_class->message_info_new_from_header = message_info_new_from_header;
- folder_summary_class->message_info_from_db = maildir_message_info_from_db;
- folder_summary_class->message_info_free = message_info_free;
folder_summary_class->next_uid_string = maildir_summary_next_uid_string;
local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (class);
@@ -208,17 +200,20 @@ static struct {
};
/* convert the uid + flags into a unique:info maildir format */
-gchar *camel_maildir_summary_info_to_name (const CamelMaildirMessageInfo *info)
+gchar *
+camel_maildir_summary_info_to_name (const CamelMessageInfo *info)
{
const gchar *uid;
+ guint32 flags;
gchar *p, *buf;
gint i;
uid = camel_message_info_get_uid (info);
buf = g_alloca (strlen (uid) + strlen (CAMEL_MAILDIR_FLAG_SEP_S "2,") + G_N_ELEMENTS (flagbits) + 1);
p = buf + sprintf (buf, "%s" CAMEL_MAILDIR_FLAG_SEP_S "2,", uid);
+ flags = camel_message_info_get_flags (info);
for (i = 0; i < G_N_ELEMENTS (flagbits); i++) {
- if (info->info.info.flags & flagbits[i].flagbit)
+ if ((flags & flagbits[i].flagbit) != 0)
*p++ = flagbits[i].flag;
}
@@ -227,48 +222,48 @@ gchar *camel_maildir_summary_info_to_name (const CamelMaildirMessageInfo *info)
return g_strdup (buf);
}
-/* returns 0 if the info matches (or there was none), otherwise we changed it */
-gint camel_maildir_summary_name_to_info (CamelMaildirMessageInfo *info, const gchar *name)
+/* returns whether the @info changed */
+gboolean
+camel_maildir_summary_name_to_info (CamelMessageInfo *info,
+ const gchar *name)
{
gchar *p, c;
guint32 set = 0; /* what we set */
- /*guint32 all = 0;*/ /* all flags */
gint i;
p = strstr (name, CAMEL_MAILDIR_FLAG_SEP_S "2,");
if (p) {
- p+=3;
+ guint32 flags;
+
+ flags = camel_message_info_get_flags (info);
+
+ p += 3;
while ((c = *p++)) {
/* we could assume that the flags are in order, but its just as easy not to require */
for (i = 0; i < G_N_ELEMENTS (flagbits); i++) {
- if (flagbits[i].flag == c && (info->info.info.flags & flagbits[i].flagbit) ==
0) {
+ if (flagbits[i].flag == c && (flags & flagbits[i].flagbit) == 0) {
set |= flagbits[i].flagbit;
}
- /*all |= flagbits[i].flagbit;*/
}
}
/* changed? */
- /*if ((info->flags & all) != set) {*/
- if ((info->info.info.flags & set) != set) {
- /* ok, they did change, only add the new flags ('merge flags'?) */
- /*info->flags &= all; if we wanted to set only the new flags, which we probably dont
*/
- info->info.info.flags |= set;
- return 1;
+ if ((flags & set) != set) {
+ return camel_message_info_set_flags (info, set, set);
}
}
- return 0;
+ return FALSE;
}
/* for maildir, x-evolution isn't used, so dont try and get anything out of it */
-static gint maildir_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev,
CamelLocalMessageInfo *mi)
+static gint maildir_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev, CamelMessageInfo
*mi)
{
return -1;
}
-static gchar *maildir_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelLocalMessageInfo *mi)
+static gchar *maildir_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelMessageInfo *mi)
{
return NULL;
}
@@ -284,16 +279,17 @@ maildir_summary_add (CamelLocalSummary *cls,
GError **error)
{
CamelLocalSummaryClass *local_summary_class;
- CamelMaildirMessageInfo *mi;
+ CamelMessageInfo *mi;
/* Chain up to parent's add() method. */
local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (camel_maildir_summary_parent_class);
- mi = (CamelMaildirMessageInfo *) local_summary_class->add (
- cls, msg, info, changes, error);
+ mi = local_summary_class->add (cls, msg, info, changes, error);
if (mi) {
if (info) {
- camel_maildir_info_set_filename (mi, camel_maildir_summary_info_to_name (mi));
- d (printf ("Setting filename to %s\n", camel_maildir_info_filename (mi)));
+ CamelMaildirMessageInfo *mdi = CAMEL_MAILDIR_MESSAGE_INFO (mi);
+
+ camel_maildir_message_info_take_filename (mdi, camel_maildir_summary_info_to_name
(mi));
+ d (printf ("Setting filename to %s\n", camel_maildir_message_info_get_filename
(mdi)));
/* Inherit the Received date from the passed-in info only if it is set and
the new message info doesn't have it set or it's set to the default
@@ -302,42 +298,43 @@ maildir_summary_add (CamelLocalSummary *cls,
(camel_message_info_get_date_received (mi) <= 0 ||
(camel_message_info_get_uid (mi) &&
camel_message_info_get_date_received (mi) == strtoul (camel_message_info_get_uid
(mi), NULL, 10))))
- mi->info.info.date_received = camel_message_info_get_date_received (info);
+ camel_message_info_set_date_received (mi,
camel_message_info_get_date_received (info));
}
}
- return (CamelMessageInfo *) mi;
+ return mi;
}
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *s,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
CamelMessageInfo *mi, *info;
CamelMaildirSummary *mds = (CamelMaildirSummary *) s;
- CamelMaildirMessageInfo *mdi;
const gchar *uid;
mi = ((CamelFolderSummaryClass *) camel_maildir_summary_parent_class)->message_info_new_from_header
(s, h);
/* assign the uid and new filename */
if (mi) {
- mdi = (CamelMaildirMessageInfo *) mi;
-
uid = camel_message_info_get_uid (mi);
- if (uid == NULL || uid[0] == 0)
- mdi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s),
TRUE);
+ if (uid == NULL || uid[0] == 0) {
+ gchar *new_uid = camel_folder_summary_next_uid_string (s);
+
+ camel_message_info_set_uid (mi, new_uid);
+ g_free (new_uid);
+ }
/* handle 'duplicates' */
- info = camel_folder_summary_peek_loaded (s, uid);
+ info = (uid && *uid) ? camel_folder_summary_peek_loaded (s, uid) : NULL;
if (info) {
d (printf ("already seen uid '%s', just summarising instead\n", uid));
- camel_message_info_unref (mi);
- mdi = (CamelMaildirMessageInfo *)(mi = info);
+ g_clear_object (&mi);
+ mi = info;
}
- if (mdi->info.info.date_received <= 0) {
+ if (camel_message_info_get_date_received (mi) <= 0) {
/* with maildir we know the real received date, from the filename */
- mdi->info.info.date_received = strtoul (camel_message_info_get_uid (mi), NULL, 10);
+ camel_message_info_set_date_received (mi, strtoul (camel_message_info_get_uid (mi),
NULL, 10));
}
if (mds->priv->current_file) {
@@ -346,8 +343,8 @@ message_info_new_from_header (CamelFolderSummary *s,
gulong uid;
#endif
/* if setting from a file, grab the flags from it */
- camel_maildir_info_set_filename (mi, g_strdup (mds->priv->current_file));
- camel_maildir_summary_name_to_info (mdi, mds->priv->current_file);
+ camel_maildir_message_info_take_filename (CAMEL_MAILDIR_MESSAGE_INFO (mi), g_strdup
(mds->priv->current_file));
+ camel_maildir_summary_name_to_info (mi, mds->priv->current_file);
#if 0
/* Actually, I dont think all this effort is worth it at all ... */
@@ -367,42 +364,16 @@ message_info_new_from_header (CamelFolderSummary *s,
#endif
} else {
/* if creating a file, set its name from the flags we have */
- camel_maildir_info_set_filename (mdi, camel_maildir_summary_info_to_name (mdi));
- d (printf ("Setting filename to %s\n", camel_maildir_info_filename (mi)));
+ camel_maildir_message_info_take_filename (CAMEL_MAILDIR_MESSAGE_INFO (mi),
camel_maildir_summary_info_to_name (mi));
+ d (printf ("Setting filename to %s\n", camel_maildir_message_info_get_filename
(CAMEL_MAILDIR_MESSAGE_INFO (mi))));
}
}
return mi;
}
-static CamelMessageInfo *
-maildir_message_info_from_db (CamelFolderSummary *summary,
- CamelMIRecord *record)
-{
- CamelMessageInfo *mi;
-
- mi = ((CamelFolderSummaryClass *) camel_maildir_summary_parent_class)->message_info_from_db (summary,
record);
- if (mi) {
- CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *) mi;
-
- camel_maildir_info_set_filename (mdi, camel_maildir_summary_info_to_name (mdi));
- }
-
- return mi;
-}
-
-static void
-message_info_free (CamelFolderSummary *s,
- CamelMessageInfo *mi)
-{
- CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *) mi;
-
- g_free (mdi->filename);
-
- ((CamelFolderSummaryClass *) camel_maildir_summary_parent_class)->message_info_free (s, mi);
-}
-
-static gchar *maildir_summary_next_uid_string (CamelFolderSummary *s)
+static gchar *
+maildir_summary_next_uid_string (CamelFolderSummary *s)
{
CamelMaildirSummary *mds = (CamelMaildirSummary *) s;
@@ -546,7 +517,8 @@ camel_maildir_summary_add (CamelLocalSummary *cls,
maildirs->priv->current_file = (gchar *) name;
info = camel_folder_summary_info_new_from_parser (summary, mp);
- camel_folder_summary_add (summary, info);
+ camel_folder_summary_add (summary, info, FALSE);
+ g_clear_object (&info);
g_object_unref (mp);
maildirs->priv->current_file = NULL;
@@ -571,7 +543,7 @@ remove_summary (gchar *key,
if (rd->changes)
camel_folder_change_info_remove_uid (rd->changes, key);
camel_folder_summary_remove ((CamelFolderSummary *) rd->cls, info);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
static gint
@@ -667,7 +639,7 @@ maildir_summary_check (CamelLocalSummary *cls,
info = g_hash_table_lookup (left, uid);
if (info) {
g_hash_table_remove (left, uid);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
info = camel_folder_summary_get ((CamelFolderSummary *) cls, uid);
@@ -685,13 +657,12 @@ maildir_summary_check (CamelLocalSummary *cls,
}
mdi = (CamelMaildirMessageInfo *) info;
- filename = camel_maildir_info_filename (mdi);
+ filename = camel_maildir_message_info_get_filename (mdi);
/* TODO: only store the extension in the mdi->filename struct, not the whole lot */
if (filename == NULL || strcmp (filename, d->d_name) != 0) {
- g_free (mdi->filename);
- mdi->filename = g_strdup (d->d_name);
+ camel_maildir_message_info_set_filename (mdi, d->d_name);
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
g_free (uid);
}
@@ -734,7 +705,7 @@ maildir_summary_check (CamelLocalSummary *cls,
/* already in summary? shouldn't happen, but just incase ... */
if ((info = camel_folder_summary_get ((CamelFolderSummary *) cls, name))) {
- camel_message_info_unref (info);
+ g_clear_object (&info);
newname = destname = camel_folder_summary_next_uid_string (s);
} else {
gchar *nm;
@@ -813,9 +784,9 @@ maildir_summary_sync (CamelLocalSummary *cls,
camel_operation_progress (cancellable, (known_uids->len - i) * 100 / known_uids->len);
info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids,
i));
- mdi = (CamelMaildirMessageInfo *) info;
- if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_DELETED) && expunge) {
- name = g_strdup_printf ("%s/cur/%s", cls->folder_path, camel_maildir_info_filename
(mdi));
+ mdi = CAMEL_MAILDIR_MESSAGE_INFO (info);
+ if (mdi && (camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED) != 0 && expunge) {
+ name = g_strdup_printf ("%s/cur/%s", cls->folder_path,
camel_maildir_message_info_get_filename (mdi));
d (printf ("deleting %s\n", name));
if (unlink (name) == 0 || errno == ENOENT) {
@@ -827,16 +798,16 @@ maildir_summary_sync (CamelLocalSummary *cls,
removed_uids = g_list_prepend (removed_uids, (gpointer) camel_pstring_strdup
(camel_message_info_get_uid (info)));
}
g_free (name);
- } else if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- gchar *newname = camel_maildir_summary_info_to_name (mdi);
+ } else if (mdi && camel_message_info_get_folder_flagged (info)) {
+ gchar *newname = camel_maildir_summary_info_to_name (info);
gchar *dest;
/* do we care about additional metainfo stored inside the message? */
/* probably should all go in the filename? */
/* have our flags/ i.e. name changed? */
- if (strcmp (newname, camel_maildir_info_filename (mdi))) {
- name = g_strdup_printf ("%s/cur/%s", cls->folder_path,
camel_maildir_info_filename (mdi));
+ if (strcmp (newname, camel_maildir_message_info_get_filename (mdi))) {
+ name = g_strdup_printf ("%s/cur/%s", cls->folder_path,
camel_maildir_message_info_get_filename (mdi));
dest = g_strdup_printf ("%s/cur/%s", cls->folder_path, newname);
if (g_rename (name, dest) == -1) {
g_warning ("%s: Failed to rename '%s' to '%s': %s", G_STRFUNC, name,
dest, g_strerror (errno));
@@ -848,19 +819,18 @@ maildir_summary_sync (CamelLocalSummary *cls,
/* TODO: If this is made mt-safe, then this code could be a problem,
since
* the estrv is being modified.
* Sigh, this may mean the maildir name has to be cached another way
*/
- g_free (mdi->filename);
- mdi->filename = newname;
+ camel_maildir_message_info_set_filename (mdi, newname);
}
g_free (name);
g_free (dest);
- } else {
- g_free (newname);
}
+ g_free (newname);
+
/* strip FOLDER_MESSAGE_FLAGED, etc */
- mdi->info.info.flags &= 0xffff;
+ camel_message_info_set_flags (info, 0xffff, camel_message_info_get_flags (info));
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
if (removed_uids) {
@@ -875,4 +845,3 @@ maildir_summary_sync (CamelLocalSummary *cls,
local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (camel_maildir_summary_parent_class);
return local_summary_class->sync (cls, expunge, changes, cancellable, error);
}
-
diff --git a/src/camel/providers/local/camel-maildir-summary.h
b/src/camel/providers/local/camel-maildir-summary.h
index 77cbdd3..61040d4 100644
--- a/src/camel/providers/local/camel-maildir-summary.h
+++ b/src/camel/providers/local/camel-maildir-summary.h
@@ -19,6 +19,7 @@
#ifndef CAMEL_MAILDIR_SUMMARY_H
#define CAMEL_MAILDIR_SUMMARY_H
+#include "camel-maildir-message-info.h"
#include "camel-local-summary.h"
/* Standard GObject macros */
@@ -54,12 +55,6 @@ typedef struct _CamelMaildirSummary CamelMaildirSummary;
typedef struct _CamelMaildirSummaryClass CamelMaildirSummaryClass;
typedef struct _CamelMaildirSummaryPrivate CamelMaildirSummaryPrivate;
-typedef struct _CamelMaildirMessageInfo {
- CamelLocalMessageInfo info;
-
- gchar *filename; /* maildir has this annoying status on the end of the filename, use
this to get the real message id */
-} CamelMaildirMessageInfo;
-
struct _CamelMaildirSummary {
CamelLocalSummary parent;
CamelMaildirSummaryPrivate *priv;
@@ -73,12 +68,8 @@ GType camel_maildir_summary_get_type (void);
CamelMaildirSummary *camel_maildir_summary_new (struct _CamelFolder *folder, const gchar
*maildirdir, CamelIndex *index);
/* convert some info->flags to/from the messageinfo */
-gchar *camel_maildir_summary_info_to_name (const CamelMaildirMessageInfo *info);
-gint camel_maildir_summary_name_to_info (CamelMaildirMessageInfo *info, const gchar *name);
-
-/* TODO: could proably use get_string stuff */
-#define camel_maildir_info_filename(x) (((CamelMaildirMessageInfo *)x)->filename)
-#define camel_maildir_info_set_filename(x, s) (g_free(((CamelMaildirMessageInfo
*)x)->filename),((CamelMaildirMessageInfo *)x)->filename = s)
+gchar *camel_maildir_summary_info_to_name (const CamelMessageInfo *info);
+gboolean camel_maildir_summary_name_to_info (CamelMessageInfo *info, const gchar *name);
G_END_DECLS
diff --git a/src/camel/providers/local/camel-mbox-folder.c b/src/camel/providers/local/camel-mbox-folder.c
index 56ca428..f222a13 100644
--- a/src/camel/providers/local/camel-mbox-folder.c
+++ b/src/camel/providers/local/camel-mbox-folder.c
@@ -33,6 +33,7 @@
#include <glib/gstdio.h>
#include "camel-mbox-folder.h"
+#include "camel-mbox-message-info.h"
#include "camel-mbox-store.h"
#include "camel-mbox-summary.h"
@@ -50,6 +51,7 @@ mbox_folder_cmp_uids (CamelFolder *folder,
const gchar *uid2)
{
CamelMboxMessageInfo *a, *b;
+ goffset aoffset, boffset;
gint res;
g_return_val_if_fail (folder != NULL, 0);
@@ -61,9 +63,9 @@ mbox_folder_cmp_uids (CamelFolder *folder,
if (!a || !b) {
/* It's not a problem when one of the messages is not in the summary */
if (a)
- camel_message_info_unref (a);
+ g_object_unref (a);
if (b)
- camel_message_info_unref (b);
+ g_object_unref (b);
if (a == b)
return 0;
@@ -72,10 +74,13 @@ mbox_folder_cmp_uids (CamelFolder *folder,
return 1;
}
- res = a->frompos < b->frompos ? -1 : a->frompos == b->frompos ? 0 : 1;
+ aoffset = camel_mbox_message_info_get_offset (a);
+ boffset = camel_mbox_message_info_get_offset (b);
- camel_message_info_unref (a);
- camel_message_info_unref (b);
+ res = aoffset < boffset ? -1 : aoffset == boffset ? 0 : 1;
+
+ g_clear_object (&a);
+ g_clear_object (&b);
return res;
}
@@ -100,7 +105,6 @@ mbox_folder_get_filename (CamelFolder *folder,
{
CamelLocalFolder *lf = (CamelLocalFolder *) folder;
CamelMboxMessageInfo *info;
- goffset frompos;
gchar *filename = NULL;
d (printf ("Getting message %s\n", uid));
@@ -122,20 +126,16 @@ mbox_folder_get_filename (CamelFolder *folder,
set_cannot_get_message_ex (
error, CAMEL_FOLDER_ERROR_INVALID_UID,
uid, lf->folder_path, _("No such message"));
- goto fail;
- }
+ } else {
+ goffset frompos;
- if (info->frompos == -1) {
- camel_message_info_unref (info);
- goto fail;
- }
+ frompos = camel_mbox_message_info_get_offset (info);
+ g_clear_object (&info);
- frompos = info->frompos;
- camel_message_info_unref (info);
-
- filename = g_strdup_printf ("%s%s!%" PRId64, lf->folder_path, G_DIR_SEPARATOR_S, (gint64) frompos);
+ if (frompos != -1)
+ filename = g_strdup_printf ("%s%s!%" G_GINT64_FORMAT, lf->folder_path,
G_DIR_SEPARATOR_S, (gint64) frompos);
+ }
-fail:
/* and unlock now we're finished with it */
camel_local_folder_unlock (lf);
@@ -154,7 +154,7 @@ mbox_folder_append_message_sync (CamelFolder *folder,
CamelStream *output_stream = NULL, *filter_stream = NULL;
CamelMimeFilter *filter_from;
CamelMboxSummary *mbs = (CamelMboxSummary *) folder->summary;
- CamelMessageInfo *mi;
+ CamelMessageInfo *mi = NULL;
gchar *fromline = NULL;
struct stat st;
gint retval;
@@ -197,13 +197,13 @@ mbox_folder_append_message_sync (CamelFolder *folder,
}
/* and we need to set the frompos/XEV explicitly */
- ((CamelMboxMessageInfo *) mi)->frompos = mbs->folder_size;
+ camel_mbox_message_info_set_offset (CAMEL_MBOX_MESSAGE_INFO (mi), mbs->folder_size);
#if 0
xev = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) folder->summary, mi);
if (xev) {
/* the x-ev header should match the 'current' flags, no problem, so store as much */
camel_medium_set_header ((CamelMedium *) message, "X-Evolution", xev);
- mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED;
+ camel_mesage_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED,
0);
g_free (xev);
}
#endif
@@ -230,11 +230,6 @@ mbox_folder_append_message_sync (CamelFolder *folder,
g_object_unref (output_stream);
g_free (fromline);
- if (!((CamelMessageInfoBase *) mi)->preview && camel_folder_summary_get_need_preview
(folder->summary)) {
- if (camel_mime_message_build_preview ((CamelMimePart *) message, mi) &&
((CamelMessageInfoBase *) mi)->preview)
- camel_folder_summary_add_preview (folder->summary, mi);
- }
-
/* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed
*/
/* the stat really shouldn't fail, we just wrote to it */
if (g_stat (lf->folder_path, &st) == 0) {
@@ -253,6 +248,8 @@ mbox_folder_append_message_sync (CamelFolder *folder,
if (appended_uid)
*appended_uid = g_strdup(camel_message_info_get_uid(mi));
+ g_clear_object (&mi);
+
return TRUE;
fail_write:
@@ -298,6 +295,8 @@ fail:
camel_folder_change_info_clear (lf->changes);
}
+ g_clear_object (&mi);
+
return FALSE;
}
@@ -338,13 +337,11 @@ retry:
goto fail;
}
- if (info->frompos == -1) {
- camel_message_info_unref (info);
- goto fail;
- }
+ frompos = camel_mbox_message_info_get_offset (CAMEL_MBOX_MESSAGE_INFO (info));
+ g_clear_object (&info);
- frompos = info->frompos;
- camel_message_info_unref (info);
+ if (frompos == -1)
+ goto fail;
/* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache
* the whole message in memory if the stream is non-seekable (which it is when built from a parser
diff --git a/src/camel/providers/local/camel-mbox-message-info.c
b/src/camel/providers/local/camel-mbox-message-info.c
new file mode 100644
index 0000000..9a278e4
--- /dev/null
+++ b/src/camel/providers/local/camel-mbox-message-info.c
@@ -0,0 +1,255 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "camel/camel.h"
+#include "camel-mbox-summary.h"
+
+#include "camel-mbox-message-info.h"
+
+struct _CamelMboxMessageInfoPrivate {
+ goffset offset;
+};
+
+enum {
+ PROP_0,
+ PROP_OFFSET
+};
+
+G_DEFINE_TYPE (CamelMboxMessageInfo, camel_mbox_message_info, CAMEL_TYPE_MESSAGE_INFO_BASE)
+
+static CamelMessageInfo *
+mbox_message_info_clone (const CamelMessageInfo *mi,
+ CamelFolderSummary *assign_summary)
+{
+ CamelMessageInfo *result;
+
+ g_return_val_if_fail (CAMEL_IS_MBOX_MESSAGE_INFO (mi), NULL);
+
+ result = CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->clone (mi, assign_summary);
+ if (!result)
+ return NULL;
+
+ if (CAMEL_IS_MBOX_MESSAGE_INFO (result)) {
+ CamelMboxMessageInfo *mmi, *mmi_result;
+
+ mmi = CAMEL_MBOX_MESSAGE_INFO (mi);
+ mmi_result = CAMEL_MBOX_MESSAGE_INFO (result);
+
+ camel_mbox_message_info_set_offset (mmi_result, camel_mbox_message_info_get_offset (mmi));
+ }
+
+ return result;
+}
+
+static gboolean
+mbox_message_info_load (CamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ CamelMboxMessageInfo *mmi;
+ gint64 offset;
+
+ g_return_val_if_fail (CAMEL_IS_MBOX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->load ||
+ !CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->load (mi, record, bdata_ptr))
+ return FALSE;
+
+ mmi = CAMEL_MBOX_MESSAGE_INFO (mi);
+
+ offset = camel_util_bdata_get_number (bdata_ptr, -1);
+ if (offset < 0)
+ return FALSE;
+
+ camel_mbox_message_info_set_offset (mmi, offset);
+
+ return TRUE;
+}
+
+static gboolean
+mbox_message_info_save (const CamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ CamelMboxMessageInfo *mmi;
+
+ g_return_val_if_fail (CAMEL_IS_MBOX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ if (!CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->save ||
+ !CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->save (mi, record, bdata_str))
+ return FALSE;
+
+ mmi = CAMEL_MBOX_MESSAGE_INFO (mi);
+
+ camel_util_bdata_put_number (bdata_str, camel_mbox_message_info_get_offset (mmi));
+
+ return TRUE;
+}
+
+static gboolean
+mbox_message_info_set_flags (CamelMessageInfo *mi,
+ guint32 mask,
+ guint32 set)
+{
+ CamelFolderSummary *summary;
+ CamelMboxSummary *mbox_summary;
+
+ summary = camel_message_info_ref_summary (mi);
+ mbox_summary = summary ? CAMEL_MBOX_SUMMARY (summary) : NULL;
+
+ /* Basically, if anything could change the Status line, presume it does */
+ if (mbox_summary && mbox_summary->xstatus
+ && (mask & (CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED))) {
+ mask |= CAMEL_MESSAGE_FOLDER_XEVCHANGE | CAMEL_MESSAGE_FOLDER_FLAGGED;
+ set |= CAMEL_MESSAGE_FOLDER_XEVCHANGE | CAMEL_MESSAGE_FOLDER_FLAGGED;
+ }
+
+ g_clear_object (&summary);
+
+ return CAMEL_MESSAGE_INFO_CLASS (camel_mbox_message_info_parent_class)->set_flags (mi, mask, set);
+}
+
+static void
+mbox_message_info_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMboxMessageInfo *mmi = CAMEL_MBOX_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_OFFSET:
+ camel_mbox_message_info_set_offset (mmi, g_value_get_int64 (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mbox_message_info_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CamelMboxMessageInfo *mmi = CAMEL_MBOX_MESSAGE_INFO (object);
+
+ switch (property_id) {
+ case PROP_OFFSET:
+ g_value_set_int64 (value, camel_mbox_message_info_get_offset (mmi));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+camel_mbox_message_info_class_init (CamelMboxMessageInfoClass *class)
+{
+ CamelMessageInfoClass *mi_class;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelMboxMessageInfoPrivate));
+
+ mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
+ mi_class->clone = mbox_message_info_clone;
+ mi_class->load = mbox_message_info_load;
+ mi_class->save = mbox_message_info_save;
+ mi_class->set_flags = mbox_message_info_set_flags;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mbox_message_info_set_property;
+ object_class->get_property = mbox_message_info_get_property;
+
+ /**
+ * CamelMboxMessageInfo:offset
+ *
+ * Offset in the file to the related message.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_OFFSET,
+ g_param_spec_int64 (
+ "offset",
+ "Offset",
+ NULL,
+ 0, G_MAXINT64, 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+camel_mbox_message_info_init (CamelMboxMessageInfo *mmi)
+{
+ mmi->priv = G_TYPE_INSTANCE_GET_PRIVATE (mmi, CAMEL_TYPE_MBOX_MESSAGE_INFO,
CamelMboxMessageInfoPrivate);
+}
+
+goffset
+camel_mbox_message_info_get_offset (const CamelMboxMessageInfo *mmi)
+{
+ CamelMessageInfo *mi;
+ goffset result;
+
+ g_return_val_if_fail (CAMEL_IS_MBOX_MESSAGE_INFO (mmi), 0);
+
+ mi = CAMEL_MESSAGE_INFO (mmi);
+
+ camel_message_info_property_lock (mi);
+ result = mmi->priv->offset;
+ camel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+gboolean
+camel_mbox_message_info_set_offset (CamelMboxMessageInfo *mmi,
+ goffset offset)
+{
+ CamelMessageInfo *mi;
+ gboolean changed;
+
+ g_return_val_if_fail (CAMEL_IS_MBOX_MESSAGE_INFO (mmi), FALSE);
+
+ mi = CAMEL_MESSAGE_INFO (mmi);
+
+ camel_message_info_property_lock (mi);
+
+ changed = mmi->priv->offset != offset;
+
+ if (changed)
+ mmi->priv->offset = offset;
+
+ camel_message_info_property_unlock (mi);
+
+ if (changed && !camel_message_info_get_abort_notifications (mi)) {
+ g_object_notify (G_OBJECT (mmi), "offset");
+ camel_message_info_set_dirty (mi, TRUE);
+ }
+
+ return changed;
+}
diff --git a/src/camel/providers/local/camel-mbox-message-info.h
b/src/camel/providers/local/camel-mbox-message-info.h
new file mode 100644
index 0000000..89d894d
--- /dev/null
+++ b/src/camel/providers/local/camel-mbox-message-info.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAMEL_MBOX_MESSAGE_INFO_H
+#define CAMEL_MBOX_MESSAGE_INFO_H
+
+#include <glib-object.h>
+
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_MBOX_MESSAGE_INFO \
+ (camel_mbox_message_info_get_type ())
+#define CAMEL_MBOX_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_MBOX_MESSAGE_INFO, CamelMboxMessageInfo))
+#define CAMEL_MBOX_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_MBOX_MESSAGE_INFO, CamelMboxMessageInfoClass))
+#define CAMEL_IS_MBOX_MESSAGE_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_MBOX_MESSAGE_INFO))
+#define CAMEL_IS_MBOX_MESSAGE_INFO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_MBOX_MESSAGE_INFO))
+#define CAMEL_MBOX_MESSAGE_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_MBOX_MESSAGE_INFO, CamelMboxMessageInfoClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelMboxMessageInfo CamelMboxMessageInfo;
+typedef struct _CamelMboxMessageInfoClass CamelMboxMessageInfoClass;
+typedef struct _CamelMboxMessageInfoPrivate CamelMboxMessageInfoPrivate;
+
+struct _CamelMboxMessageInfo {
+ CamelMessageInfoBase parent;
+ CamelMboxMessageInfoPrivate *priv;
+};
+
+struct _CamelMboxMessageInfoClass {
+ CamelMessageInfoBaseClass parent_class;
+};
+
+GType camel_mbox_message_info_get_type (void);
+
+goffset camel_mbox_message_info_get_offset (const CamelMboxMessageInfo *mmi);
+gboolean camel_mbox_message_info_set_offset (CamelMboxMessageInfo *mmi,
+ goffset offset);
+
+G_END_DECLS
+
+#endif /* CAMEL_MBOX_MESSAGE_INFO_H */
diff --git a/src/camel/providers/local/camel-mbox-summary.c b/src/camel/providers/local/camel-mbox-summary.c
index 4e82fdc..a5e683f 100644
--- a/src/camel/providers/local/camel-mbox-summary.c
+++ b/src/camel/providers/local/camel-mbox-summary.c
@@ -31,14 +31,14 @@
#include <glib/gi18n-lib.h>
#include <glib/gstdio.h>
+#include "camel-mbox-message-info.h"
#include "camel-mbox-summary.h"
#include "camel-local-private.h"
#define io(x)
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
-/* Enable the use of elm/pine style "Status" & "X-Status" headers */
-#define STATUS_PINE
+/* This uses elm/pine style "Status" & "X-Status" headers */
#define CAMEL_MBOX_SUMMARY_VERSION (1)
@@ -60,21 +60,14 @@ static CamelFIRecord *
static gboolean summary_header_from_db (CamelFolderSummary *,
CamelFIRecord *);
static CamelMessageInfo *
- message_info_from_db (CamelFolderSummary *s,
- CamelMIRecord *record);
-static CamelMIRecord *
- message_info_to_db (CamelFolderSummary *s,
- CamelMessageInfo *info);
-
-static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *,
- struct _camel_header_raw *);
+ CamelHeaderRaw *);
static CamelMessageInfo *
message_info_new_from_parser (CamelFolderSummary *,
CamelMimeParser *);
static gchar * mbox_summary_encode_x_evolution (CamelLocalSummary *cls,
- const CamelLocalMessageInfo *mi);
+ const CamelMessageInfo *mi);
static gint mbox_summary_check (CamelLocalSummary *cls,
CamelFolderChangeInfo *changeinfo,
@@ -85,15 +78,12 @@ static gint mbox_summary_sync (CamelLocalSummary *cls,
CamelFolderChangeInfo *changeinfo,
GCancellable *cancellable,
GError **error);
-#ifdef STATUS_PINE
static CamelMessageInfo *
mbox_summary_add (CamelLocalSummary *cls,
CamelMimeMessage *msg,
const CamelMessageInfo *info,
CamelFolderChangeInfo *ci,
GError **error);
-#endif
-
static gint mbox_summary_sync_quick (CamelMboxSummary *cls,
gboolean expunge,
CamelFolderChangeInfo *changeinfo,
@@ -105,7 +95,6 @@ static gint mbox_summary_sync_full (CamelMboxSummary *cls,
GCancellable *cancellable,
GError **error);
-#ifdef STATUS_PINE
/* Which status flags are stored in each separate header */
#define STATUS_XSTATUS \
(CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED)
@@ -113,59 +102,12 @@ static gint mbox_summary_sync_full (CamelMboxSummary *cls,
static void encode_status (guint32 flags, gchar status[8]);
static guint32 decode_status (const gchar *status);
-#endif
G_DEFINE_TYPE (
CamelMboxSummary,
camel_mbox_summary,
CAMEL_TYPE_LOCAL_SUMMARY)
-static gboolean
-mbox_info_set_user_flag (CamelMessageInfo *mi,
- const gchar *name,
- gboolean value)
-{
- gint res;
-
- res = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->info_set_user_flag (mi, name,
value);
- if (res)
- ((CamelLocalMessageInfo *) mi)->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-
- return res;
-}
-
-static gboolean
-mbox_info_set_user_tag (CamelMessageInfo *mi,
- const gchar *name,
- const gchar *value)
-{
- gint res;
-
- res = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->info_set_user_tag (mi, name,
value);
- if (res)
- ((CamelLocalMessageInfo *) mi)->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-
- return res;
-}
-
-#ifdef STATUS_PINE
-static gboolean
-mbox_info_set_flags (CamelMessageInfo *mi,
- guint32 flags,
- guint32 set)
-{
- /* Basically, if anything could change the Status line, presume it does */
- if (((CamelMboxSummary *) mi->summary)->xstatus
- && (flags & (CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED))) {
- flags |= CAMEL_MESSAGE_FOLDER_XEVCHANGE | CAMEL_MESSAGE_FOLDER_FLAGGED;
- set |= CAMEL_MESSAGE_FOLDER_XEVCHANGE | CAMEL_MESSAGE_FOLDER_FLAGGED;
- }
-
- return CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->
- info_set_flags (mi, flags, set);
-}
-#endif
-
static void
camel_mbox_summary_class_init (CamelMboxSummaryClass *class)
{
@@ -173,27 +115,17 @@ camel_mbox_summary_class_init (CamelMboxSummaryClass *class)
CamelLocalSummaryClass *local_summary_class;
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelMboxMessageInfo);
- folder_summary_class->content_info_size = sizeof (CamelMboxMessageContentInfo);
+ folder_summary_class->message_info_type = CAMEL_TYPE_MBOX_MESSAGE_INFO;
folder_summary_class->summary_header_from_db = summary_header_from_db;
folder_summary_class->summary_header_to_db = summary_header_to_db;
- folder_summary_class->message_info_from_db = message_info_from_db;
- folder_summary_class->message_info_to_db = message_info_to_db;
folder_summary_class->message_info_new_from_header = message_info_new_from_header;
folder_summary_class->message_info_new_from_parser = message_info_new_from_parser;
- folder_summary_class->info_set_user_flag = mbox_info_set_user_flag;
- folder_summary_class->info_set_user_tag = mbox_info_set_user_tag;
-#ifdef STATUS_PINE
- folder_summary_class->info_set_flags = mbox_info_set_flags;
-#endif
local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (class);
local_summary_class->encode_x_evolution = mbox_summary_encode_x_evolution;
local_summary_class->check = mbox_summary_check;
local_summary_class->sync = mbox_summary_sync;
-#ifdef STATUS_PINE
local_summary_class->add = mbox_summary_add;
-#endif
class->sync_quick = mbox_summary_sync_quick;
class->sync_full = mbox_summary_sync_full;
@@ -248,20 +180,22 @@ void camel_mbox_summary_xstatus (CamelMboxSummary *mbs, gint state)
static gchar *
mbox_summary_encode_x_evolution (CamelLocalSummary *cls,
- const CamelLocalMessageInfo *mi)
+ const CamelMessageInfo *mi)
{
const gchar *p, *uidstr;
- guint32 uid;
+ guint32 uid, flags;
/* This is busted, it is supposed to encode ALL DATA */
p = uidstr = camel_message_info_get_uid (mi);
while (*p && isdigit (*p))
p++;
+ flags = camel_message_info_get_flags (mi);
+
if (*p == 0 && sscanf (uidstr, "%u", &uid) == 1) {
- return g_strdup_printf ("%08x-%04x", uid, mi->info.flags & 0xffff);
+ return g_strdup_printf ("%08x-%04x", uid, flags & 0xffff);
} else {
- return g_strdup_printf ("%s-%04x", uidstr, mi->info.flags & 0xffff);
+ return g_strdup_printf ("%s-%04x", uidstr, flags & 0xffff);
}
}
@@ -277,8 +211,8 @@ summary_header_from_db (CamelFolderSummary *s,
part = fir->bdata;
if (part) {
- mbs->version = bdata_extract_digit (&part);
- mbs->folder_size = bdata_extract_digit (&part);
+ mbs->version = camel_util_bdata_get_number (&part, 0);
+ mbs->folder_size = camel_util_bdata_get_number (&part, 0);
}
return TRUE;
@@ -307,17 +241,16 @@ summary_header_to_db (CamelFolderSummary *s,
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *s,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
- CamelMboxMessageInfo *mi;
+ CamelMessageInfo *mi;
CamelMboxSummary *mbs = (CamelMboxSummary *) s;
- mi = (CamelMboxMessageInfo *) CAMEL_FOLDER_SUMMARY_CLASS
(camel_mbox_summary_parent_class)->message_info_new_from_header (s, h);
+ mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->message_info_new_from_header (s,
h);
if (mi) {
const gchar *xev, *uid;
- CamelMboxMessageInfo *info = NULL;
+ CamelMessageInfo *info = NULL;
gint add = 0; /* bitmask of things to add, 1 assign uid, 2, just add as new, 4 = recent */
-#ifdef STATUS_PINE
const gchar *status = NULL, *xstatus = NULL;
guint32 flags = 0;
@@ -330,24 +263,24 @@ message_info_new_from_header (CamelFolderSummary *s,
if (xstatus)
flags |= decode_status (xstatus);
}
-#endif
+
/* if we have an xev header, use it, else assign a new one */
xev = camel_header_raw_find (&h, "X-Evolution", NULL);
if (xev != NULL
- && camel_local_summary_decode_x_evolution ((CamelLocalSummary *) s, xev, &mi->info) == 0)
{
+ && camel_local_summary_decode_x_evolution ((CamelLocalSummary *) s, xev, mi) == 0) {
uid = camel_message_info_get_uid (mi);
d (printf ("found valid x-evolution: %s\n", uid));
/* If one is there, it should be there already */
- info = (CamelMboxMessageInfo *) camel_folder_summary_peek_loaded (s, uid);
+ info = camel_folder_summary_peek_loaded (s, uid);
if (info) {
- if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) {
- info->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
- camel_message_info_unref (mi);
+ if ((camel_message_info_get_flags (info) & CAMEL_MESSAGE_FOLDER_NOTSEEN)) {
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_FOLDER_NOTSEEN, 0);
+ g_clear_object (&mi);
mi = info;
} else {
add = 7;
d (printf ("seen '%s' before, adding anew\n", uid));
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
} else {
add = 2;
@@ -358,22 +291,25 @@ message_info_new_from_header (CamelFolderSummary *s,
add = 7;
}
- if (add&1) {
- mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
- camel_pstring_free (mi->info.info.uid);
- mi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s),
TRUE);
+ if ((add & 1) != 0) {
+ gchar *new_uid = camel_folder_summary_next_uid_string (s);
+
+ camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_FLAGGED |
CAMEL_MESSAGE_FOLDER_NOXEV, CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV);
+ camel_message_info_set_uid (mi, new_uid);
+
+ g_free (new_uid);
} else {
camel_folder_summary_set_next_uid (s, strtoul (camel_message_info_get_uid (mi), NULL,
10));
}
-#ifdef STATUS_PINE
- if (mbs->xstatus && add&2) {
+
+ if (mbs->xstatus && (add & 2) != 0) {
/* use the status as the flags when we read it the first time */
if (status)
- mi->info.info.flags = (mi->info.info.flags & ~(STATUS_STATUS)) | (flags &
STATUS_STATUS);
+ camel_message_info_set_flags (mi, STATUS_STATUS, flags);
if (xstatus)
- mi->info.info.flags = (mi->info.info.flags & ~(STATUS_XSTATUS)) | (flags &
STATUS_XSTATUS);
+ camel_message_info_set_flags (mi, STATUS_XSTATUS, flags);
}
-#endif
+
if (mbs->changes) {
if (add&2)
camel_folder_change_info_add_uid (mbs->changes, camel_message_info_get_uid
(mi));
@@ -381,7 +317,7 @@ message_info_new_from_header (CamelFolderSummary *s,
camel_folder_change_info_recent_uid (mbs->changes, camel_message_info_get_uid
(mi));
}
- mi->frompos = -1;
+ camel_mbox_message_info_set_offset (CAMEL_MBOX_MESSAGE_INFO (mi), -1);
}
return (CamelMessageInfo *) mi;
@@ -395,46 +331,12 @@ message_info_new_from_parser (CamelFolderSummary *s,
mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->message_info_new_from_parser (s,
mp);
if (mi) {
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *) mi;
-
- mbi->frompos = camel_mime_parser_tell_start_from (mp);
+ camel_mbox_message_info_set_offset (CAMEL_MBOX_MESSAGE_INFO (mi),
camel_mime_parser_tell_start_from (mp));
}
return mi;
}
-static CamelMessageInfo *
-message_info_from_db (CamelFolderSummary *s,
- struct _CamelMIRecord *mir)
-{
- CamelMessageInfo *mi;
-
- mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->message_info_from_db (s, mir);
-
- if (mi) {
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *) mi;
- gchar *part = mir->bdata;
- if (part) {
- mbi->frompos = bdata_extract_digit (&part);
- }
- }
-
- return mi;
-}
-
-static struct _CamelMIRecord *
-message_info_to_db (CamelFolderSummary *s,
- CamelMessageInfo *info)
-{
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *) info;
- struct _CamelMIRecord *mir;
-
- mir = CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->message_info_to_db (s, info);
- mir->bdata = g_strdup_printf ("%" G_GOFFSET_FORMAT, mbi->frompos);
-
- return mir;
-}
-
/* like summary_rebuild, but also do changeinfo stuff (if supplied) */
static gint
summary_update (CamelLocalSummary *cls,
@@ -447,7 +349,7 @@ summary_update (CamelLocalSummary *cls,
CamelFolderSummary *s = (CamelFolderSummary *) cls;
CamelMboxSummary *mbs = (CamelMboxSummary *) cls;
CamelMimeParser *mp;
- CamelMboxMessageInfo *mi;
+ CamelMessageInfo *mi;
CamelStore *parent_store;
const gchar *full_name;
gint fd;
@@ -503,12 +405,9 @@ summary_update (CamelLocalSummary *cls,
camel_folder_summary_prepare_fetch_all (s, NULL);
known_uids = camel_folder_summary_get_array (s);
for (i = 0; known_uids && i < known_uids->len; i++) {
- mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
- if (offset == 0)
- mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_NOTSEEN;
- else
- mi->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
- camel_message_info_unref (mi);
+ mi = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
+ camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_NOTSEEN, offset == 0 ?
CAMEL_MESSAGE_FOLDER_NOTSEEN : 0);
+ g_clear_object (&mi);
}
camel_folder_summary_free_array (known_uids);
mbs->changes = changeinfo;
@@ -526,7 +425,8 @@ summary_update (CamelLocalSummary *cls,
camel_operation_progress (cancellable, progress);
info = camel_folder_summary_info_new_from_parser (s, mp);
- camel_folder_summary_add (s, info);
+ camel_folder_summary_add (s, info, FALSE);
+ g_clear_object (&info);
g_warn_if_fail (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM_END);
}
@@ -541,19 +441,18 @@ summary_update (CamelLocalSummary *cls,
if (!uid)
continue;
- mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, uid);
+ mi = camel_folder_summary_get (s, uid);
/* must've dissapeared from the file? */
- if (!mi || mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) {
+ if (!mi || (camel_message_info_get_flags (mi) & CAMEL_MESSAGE_FOLDER_NOTSEEN) != 0) {
d (printf ("uid '%s' vanished, removing", uid));
if (changeinfo)
camel_folder_change_info_remove_uid (changeinfo, uid);
del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid));
if (mi)
- camel_folder_summary_remove (s, (CamelMessageInfo *) mi);
+ camel_folder_summary_remove (s, mi);
}
- if (mi)
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
}
if (known_uids)
@@ -627,7 +526,7 @@ mbox_summary_check (CamelLocalSummary *cls,
if (info) {
camel_folder_change_info_remove_uid (changes, camel_message_info_get_uid
(info));
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
camel_folder_summary_free_array (known_uids);
@@ -790,20 +689,25 @@ cms_sort_frompos (gconstpointer a,
{
CamelFolderSummary *summary = (CamelFolderSummary *) data;
CamelMboxMessageInfo *info1, *info2;
+ goffset afrompos, bfrompos;
gint ret = 0;
/* Things are in memory already. Sorting speeds up syncing, if things are sorted by from pos. */
info1 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) a);
info2 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) b);
- if (info1->frompos > info2->frompos)
+ afrompos = camel_mbox_message_info_get_offset (info1);
+ bfrompos = camel_mbox_message_info_get_offset (info2);
+
+ if (afrompos > bfrompos)
ret = 1;
- else if (info1->frompos < info2->frompos)
+ else if (afrompos < bfrompos)
ret = -1;
else
ret = 0;
- camel_message_info_unref (info1);
- camel_message_info_unref (info2);
+
+ g_clear_object (&info1);
+ g_clear_object (&info2);
return ret;
@@ -821,7 +725,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
CamelFolderSummary *s = (CamelFolderSummary *) mbs;
CamelMimeParser *mp = NULL;
gint i;
- CamelMboxMessageInfo *info = NULL;
+ CamelMessageInfo *info = NULL;
gint fd = -1, pfd;
gchar *xevnew, *xevtmp;
const gchar *xev;
@@ -871,24 +775,26 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
g_ptr_array_sort_with_data (summary, cms_sort_frompos, mbs);
for (i = 0; i < summary->len; i++) {
+ goffset frompos;
gint xevoffset;
gint pc = (i + 1) * 100 / summary->len;
camel_operation_progress (cancellable, pc);
- info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, summary->pdata[i]);
+ info = camel_folder_summary_get (s, summary->pdata[i]);
- d (printf ("Checking message %s %08x\n", camel_message_info_get_uid (info),
((CamelMessageInfoBase *) info)->flags));
+ d (printf ("Checking message %s %08x\n", camel_message_info_get_uid (info),
camel_message_info_get_flags (info)));
- if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) {
- camel_message_info_unref (info);
- info = NULL;
+ if (!camel_message_info_get_folder_flagged (info)) {
+ g_clear_object (&info);
continue;
}
- d (printf ("Updating message %s: %d\n", camel_message_info_get_uid (info), (gint)
info->frompos));
+ frompos = camel_mbox_message_info_get_offset (CAMEL_MBOX_MESSAGE_INFO (info));
- camel_mime_parser_seek (mp, info->frompos, SEEK_SET);
+ d (printf ("Updating message %s: %d\n", camel_message_info_get_uid (info), (gint) frompos));
+
+ camel_mime_parser_seek (mp, frompos, SEEK_SET);
if (camel_mime_parser_step (mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_FROM) {
g_set_error (
@@ -897,10 +803,10 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
goto error;
}
- if (camel_mime_parser_tell_start_from (mp) != info->frompos) {
+ if (camel_mime_parser_tell_start_from (mp) != frompos) {
g_warning (
"Didn't get the next message where I expected (%d) got %d instead",
- (gint) info->frompos, (gint) camel_mime_parser_tell_start_from (mp));
+ (gint) frompos, (gint) camel_mime_parser_tell_start_from (mp));
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Summary and folder mismatch, even after a sync"));
@@ -917,7 +823,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
g_warning ("We're supposed to have a valid x-ev header, but we dont");
goto error;
}
- xevnew = camel_local_summary_encode_x_evolution (cls, &info->info);
+ xevnew = camel_local_summary_encode_x_evolution (cls, info);
/* SIGH: encode_param_list is about the only function which folds headers by itself.
* This should be fixed somehow differently (either parser doesn't fold headers,
* or param_list doesn't, or something */
@@ -949,10 +855,8 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
camel_mime_parser_drop_step (mp);
camel_mime_parser_drop_step (mp);
- info->info.info.flags &= 0xffff;
- info->info.info.dirty = TRUE;
- camel_message_info_unref (info);
- info = NULL;
+ camel_message_info_set_flags (info, 0xffff, camel_message_info_get_flags (info));
+ g_clear_object (&info);
}
d (printf ("Closing folders\n"));
@@ -983,7 +887,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
if (fd != -1)
close (fd);
if (info)
- camel_message_info_unref (info);
+ g_clear_object (&info);
camel_operation_pop_message (cancellable);
camel_folder_summary_unlock (s);
@@ -1023,14 +927,14 @@ mbox_summary_sync (CamelLocalSummary *cls,
summary = camel_folder_summary_get_changed ((CamelFolderSummary *) mbs);
for (i = 0; i < summary->len; i++) {
- CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s,
summary->pdata[i]);
+ CamelMessageInfo *info = camel_folder_summary_get (s, summary->pdata[i]);
- if ((expunge && (info->info.info.flags & CAMEL_MESSAGE_DELETED)) ||
- (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_XEVCHANGE)))
+ if ((expunge && (camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED) != 0) ||
+ (camel_message_info_get_flags (info) & (CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_XEVCHANGE)) != 0)
quick = FALSE;
else
- work |= (info->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
- camel_message_info_unref (info);
+ work |= camel_message_info_get_folder_flagged (info);
+ g_clear_object (&info);
}
g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
@@ -1104,7 +1008,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
CamelStore *parent_store;
const gchar *full_name;
gint i;
- CamelMboxMessageInfo *info = NULL;
+ CamelMessageInfo *info = NULL;
gchar *buffer, *xevnew = NULL;
gsize len;
const gchar *fromline;
@@ -1112,9 +1016,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
gboolean touched = FALSE;
GList *del = NULL;
GPtrArray *known_uids = NULL;
-#ifdef STATUS_PINE
gchar statnew[8], xstatnew[8];
-#endif
d (printf ("performing full summary/sync\n"));
@@ -1144,10 +1046,11 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
g_ptr_array_sort_with_data (known_uids, cms_sort_frompos, mbs);
for (i = 0; known_uids && i < known_uids->len; i++) {
gint pc = (i + 1) * 100 / known_uids->len;
+ goffset frompos;
camel_operation_progress (cancellable, pc);
- info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids,
i));
+ info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
if (!info)
continue;
@@ -1156,13 +1059,15 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
"Looking at message %s\n",
camel_message_info_get_uid (info)));
+ frompos = camel_mbox_message_info_get_offset (CAMEL_MBOX_MESSAGE_INFO (info));
+
d (printf (
"seeking (%s) to %d\n",
- ((CamelMessageInfo *) info)->uid,
- (gint) info->frompos));
+ camel_message_info_get_uid (info),
+ (gint) frompos));
if (lastdel)
- camel_mime_parser_seek (mp, info->frompos, SEEK_SET);
+ camel_mime_parser_seek (mp, frompos, SEEK_SET);
if (camel_mime_parser_step (mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM) {
g_set_error (
@@ -1172,10 +1077,10 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
goto error;
}
- if (camel_mime_parser_tell_start_from (mp) != info->frompos) {
+ if (camel_mime_parser_tell_start_from (mp) != frompos) {
g_warning (
"Didn't get the next message where I expected (%d) got %d instead",
- (gint) info->frompos,
+ (gint) frompos,
(gint) camel_mime_parser_tell_start_from (mp));
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
@@ -1184,7 +1089,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
}
lastdel = FALSE;
- if ((flags&1) && info->info.info.flags & CAMEL_MESSAGE_DELETED) {
+ if ((flags & 1) && (camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED) != 0) {
const gchar *uid = camel_message_info_get_uid (info);
d (printf ("Deleting %s\n", uid));
@@ -1195,8 +1100,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
camel_folder_change_info_remove_uid (changeinfo, uid);
camel_folder_summary_remove (s, (CamelMessageInfo *) info);
del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid));
- camel_message_info_unref (info);
- info = NULL;
+ g_clear_object (&info);
lastdel = TRUE;
touched = TRUE;
} else {
@@ -1205,33 +1109,33 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
if (i > 0)
write (fdout, "\n", 1);
#endif
- info->frompos = lseek (fdout, 0, SEEK_CUR);
- ((CamelMessageInfo *) info)->dirty = TRUE;
+ frompos = lseek (fdout, 0, SEEK_CUR);
+ camel_mbox_message_info_set_offset (CAMEL_MBOX_MESSAGE_INFO (info), frompos);
+ camel_message_info_set_dirty (info, TRUE);
fromline = camel_mime_parser_from_line (mp);
- d (printf ("Saving %s:%d\n", camel_message_info_get_uid (info), info->frompos));
+ d (printf ("Saving %s:%d\n", camel_message_info_get_uid (info), frompos));
g_warn_if_fail (write (fdout, fromline, strlen (fromline)) != -1);
}
- if (info && info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- d (printf ("Updating header for %s flags = %08x\n", camel_message_info_get_uid
(info), info->info.flags));
+ if (info && (camel_message_info_get_flags (info) & (CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_FLAGGED)) != 0) {
+ d (printf ("Updating header for %s flags = %08x\n", camel_message_info_get_uid
(info), camel_message_info_get_flags (info)));
if (camel_mime_parser_step (mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM_END) {
g_warning ("camel_mime_parser_step failed (2)");
goto error;
}
- xevnew = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) cls,
&info->info);
-#ifdef STATUS_PINE
+ xevnew = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) cls, info);
if (mbs->xstatus) {
- encode_status (info->info.info.flags & STATUS_STATUS, statnew);
- encode_status (info->info.info.flags & STATUS_XSTATUS, xstatnew);
+ guint32 flags = camel_message_info_get_flags (info);
+
+ encode_status (flags & STATUS_STATUS, statnew);
+ encode_status (flags & STATUS_XSTATUS, xstatnew);
len = camel_local_summary_write_headers (fdout, camel_mime_parser_headers_raw
(mp), xevnew, statnew, xstatnew);
} else {
-#endif
len = camel_local_summary_write_headers (fdout, camel_mime_parser_headers_raw
(mp), xevnew, NULL, NULL);
-#ifdef STATUS_PINE
}
-#endif
+
if (len == -1) {
d (printf ("Error writing to temporary mailbox\n"));
g_set_error (
@@ -1241,7 +1145,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
g_strerror (errno));
goto error;
}
- info->info.info.flags &= 0xffff;
+ camel_message_info_set_flags (info, 0xffff, camel_message_info_get_flags (info));
g_free (xevnew);
xevnew = NULL;
camel_mime_parser_drop_step (mp);
@@ -1277,8 +1181,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
(gint) camel_mime_parser_tell (mp),
(gint) camel_mime_parser_tell_start_from (mp)));
camel_mime_parser_unstep (mp);
- camel_message_info_unref (info);
- info = NULL;
+ g_clear_object (&info);
}
}
@@ -1298,17 +1201,10 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
/* clear working flags */
for (i = 0; known_uids && i < known_uids->len; i++) {
- info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids,
i));
+ info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
if (info) {
- if (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_XEVCHANGE)) {
- info->info.info.flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV
- |CAMEL_MESSAGE_FOLDER_FLAGGED
- |CAMEL_MESSAGE_FOLDER_XEVCHANGE);
- ((CamelMessageInfo *) info)->dirty = TRUE;
- camel_folder_summary_touch (s);
- }
- camel_message_info_unref (info);
- info = NULL;
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_XEVCHANGE, 0);
+ g_clear_object (&info);
}
}
@@ -1323,9 +1219,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
error:
g_free (xevnew);
g_object_unref (mp);
-
- if (info)
- camel_message_info_unref (info);
+ g_clear_object (&info);
camel_folder_summary_free_array (known_uids);
camel_folder_summary_unlock (s);
@@ -1333,7 +1227,6 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls,
return -1;
}
-#ifdef STATUS_PINE
static CamelMessageInfo *
mbox_summary_add (CamelLocalSummary *cls,
CamelMimeMessage *msg,
@@ -1342,23 +1235,23 @@ mbox_summary_add (CamelLocalSummary *cls,
GError **error)
{
CamelLocalSummaryClass *local_summary_class;
- CamelMboxMessageInfo *mi;
+ CamelMessageInfo *mi;
/* Chain up to parent's add() method. */
local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (camel_mbox_summary_parent_class);
- mi = (CamelMboxMessageInfo *) local_summary_class->add (
- cls, msg, info, ci, error);
+ mi = local_summary_class->add (cls, msg, info, ci, error);
if (mi && ((CamelMboxSummary *) cls)->xstatus) {
gchar status[8];
+ guint32 flags = camel_message_info_get_flags (mi);
/* we snoop and add status/x-status headers to suit */
- encode_status (mi->info.info.flags & STATUS_STATUS, status);
+ encode_status (flags & STATUS_STATUS, status);
camel_medium_set_header ((CamelMedium *) msg, "Status", status);
- encode_status (mi->info.info.flags & STATUS_XSTATUS, status);
+ encode_status (flags & STATUS_XSTATUS, status);
camel_medium_set_header ((CamelMedium *) msg, "X-Status", status);
}
- return (CamelMessageInfo *) mi;
+ return mi;
}
static struct {
@@ -1403,5 +1296,3 @@ decode_status (const gchar *status)
return flags;
}
-
-#endif /* STATUS_PINE */
diff --git a/src/camel/providers/local/camel-mbox-summary.h b/src/camel/providers/local/camel-mbox-summary.h
index 37f6bad..594cca4 100644
--- a/src/camel/providers/local/camel-mbox-summary.h
+++ b/src/camel/providers/local/camel-mbox-summary.h
@@ -45,12 +45,6 @@ G_BEGIN_DECLS
typedef struct _CamelMboxSummary CamelMboxSummary;
typedef struct _CamelMboxSummaryClass CamelMboxSummaryClass;
-typedef struct _CamelMboxMessageInfo {
- CamelLocalMessageInfo info;
-
- goffset frompos;
-} CamelMboxMessageInfo;
-
struct _CamelMboxSummary {
CamelLocalSummary parent;
diff --git a/src/camel/providers/local/camel-mh-folder.c b/src/camel/providers/local/camel-mh-folder.c
index 7eaafe9..fa56572 100644
--- a/src/camel/providers/local/camel-mh-folder.c
+++ b/src/camel/providers/local/camel-mh-folder.c
@@ -128,6 +128,8 @@ mh_folder_append_message_sync (CamelFolder *folder,
camel_folder_change_info_clear (lf->changes);
}
+ g_clear_object (&mi);
+
return TRUE;
}
@@ -157,7 +159,7 @@ mh_folder_get_message_sync (CamelFolder *folder,
}
/* we only need it to check the message exists */
- camel_message_info_unref (info);
+ g_clear_object (&info);
name = g_strdup_printf ("%s/%s", lf->folder_path, uid);
message_stream = camel_stream_fs_new_with_name (
diff --git a/src/camel/providers/local/camel-mh-summary.c b/src/camel/providers/local/camel-mh-summary.c
index b653192..b471eea 100644
--- a/src/camel/providers/local/camel-mh-summary.c
+++ b/src/camel/providers/local/camel-mh-summary.c
@@ -43,7 +43,7 @@
static gint mh_summary_check (CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, GCancellable
*cancellable, GError **error);
static gint mh_summary_sync (CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo,
GCancellable *cancellable, GError **error);
-static gint mh_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev, CamelLocalMessageInfo
*info);
+static gint mh_summary_decode_x_evolution (CamelLocalSummary *cls, const gchar *xev, CamelMessageInfo *info);
/*static gint mh_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info,
CamelFolderChangeInfo *, GError **error);*/
static gchar *mh_summary_next_uid_string (CamelFolderSummary *s);
@@ -183,7 +183,8 @@ camel_mh_summary_add (CamelLocalSummary *cls,
mhs->priv->current_uid = (gchar *) name;
info = camel_folder_summary_info_new_from_parser (summary, mp);
- camel_folder_summary_add (summary, info);
+ camel_folder_summary_add (summary, info, FALSE);
+ g_clear_object (&info);
g_object_unref (mp);
mhs->priv->current_uid = NULL;
@@ -202,7 +203,7 @@ remove_summary (gchar *key,
if (cls->index)
camel_index_delete_name (cls->index, camel_message_info_get_uid (info));
camel_folder_summary_remove ((CamelFolderSummary *) cls, info);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
static gint
@@ -265,11 +266,11 @@ mh_summary_check (CamelLocalSummary *cls,
if (old) {
g_hash_table_remove (left, camel_message_info_get_uid (info));
- camel_message_info_unref (old);
+ g_clear_object (&old);
}
camel_folder_summary_remove ((CamelFolderSummary *) cls, info);
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_mh_summary_add (cls, d->d_name, forceindex, cancellable);
} else {
@@ -278,9 +279,9 @@ mh_summary_check (CamelLocalSummary *cls,
if (old) {
g_hash_table_remove (left, uid);
- camel_message_info_unref (old);
+ g_clear_object (&old);
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
}
}
@@ -302,7 +303,7 @@ mh_summary_sync (CamelLocalSummary *cls,
CamelLocalSummaryClass *local_summary_class;
gint i;
GPtrArray *known_uids;
- CamelLocalMessageInfo *info;
+ CamelMessageInfo *info;
gchar *name;
const gchar *uid;
@@ -318,9 +319,9 @@ mh_summary_sync (CamelLocalSummary *cls,
camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error);
known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls);
for (i = (known_uids ? known_uids->len : 0) - 1; i >= 0; i--) {
- info = (CamelLocalMessageInfo *) camel_folder_summary_get ((CamelFolderSummary *) cls,
g_ptr_array_index (known_uids, i));
+ info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids,
i));
g_return_val_if_fail (info, -1);
- if (expunge && (info->info.flags & CAMEL_MESSAGE_DELETED)) {
+ if (expunge && (camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED) != 0) {
uid = camel_message_info_get_uid (info);
name = g_strdup_printf ("%s/%s", cls->folder_path, uid);
d (printf ("deleting %s\n", name));
@@ -334,10 +335,10 @@ mh_summary_sync (CamelLocalSummary *cls,
camel_folder_summary_remove ((CamelFolderSummary *) cls, (CamelMessageInfo *)
info);
}
g_free (name);
- } else if (info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- info->info.flags &= 0xffff;
+ } else if ((camel_message_info_get_flags (info) & (CAMEL_MESSAGE_FOLDER_NOXEV |
CAMEL_MESSAGE_FOLDER_FLAGGED)) != 0) {
+ camel_message_info_set_flags (info, 0xffff, camel_message_info_get_flags (info));
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_folder_summary_free_array (known_uids);
@@ -350,7 +351,7 @@ mh_summary_sync (CamelLocalSummary *cls,
static gint
mh_summary_decode_x_evolution (CamelLocalSummary *cls,
const gchar *xev,
- CamelLocalMessageInfo *info)
+ CamelMessageInfo *info)
{
CamelLocalSummaryClass *local_summary_class;
CamelMhSummary *mh_summary;
@@ -365,8 +366,7 @@ mh_summary_decode_x_evolution (CamelLocalSummary *cls,
/* do not use UID from the header, rather use the one provided, if any */
mh_summary = CAMEL_MH_SUMMARY (cls);
if (mh_summary->priv->current_uid) {
- camel_pstring_free (info->info.uid);
- info->info.uid = camel_pstring_strdup (mh_summary->priv->current_uid);
+ camel_message_info_set_uid (info, mh_summary->priv->current_uid);
}
return ret;
diff --git a/src/camel/providers/local/camel-spool-summary.c b/src/camel/providers/local/camel-spool-summary.c
index 44e3719..e78cfc9 100644
--- a/src/camel/providers/local/camel-spool-summary.c
+++ b/src/camel/providers/local/camel-spool-summary.c
@@ -31,10 +31,11 @@
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
-#include "camel-spool-summary.h"
#include "camel-local-private.h"
#include "camel-win32.h"
+#include "camel-spool-summary.h"
+
#define io(x)
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
@@ -332,10 +333,10 @@ spool_summary_check (CamelLocalSummary *cls,
camel_folder_summary_prepare_fetch_all (s, error);
known_uids = camel_folder_summary_get_array (s);
for (i = 0; !work && known_uids && i < known_uids->len; i++) {
- CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s,
g_ptr_array_index (known_uids, i));
+ CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i));
g_return_val_if_fail (info, -1);
- work = (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0;
- camel_message_info_unref (info);
+ work = (camel_message_info_get_flags (info) & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0;
+ g_clear_object (&info);
}
camel_folder_summary_free_array (known_uids);
diff --git a/src/camel/providers/local/camel-spool-summary.h b/src/camel/providers/local/camel-spool-summary.h
index b08adfb..fdd4f91 100644
--- a/src/camel/providers/local/camel-spool-summary.h
+++ b/src/camel/providers/local/camel-spool-summary.h
@@ -76,7 +76,7 @@ gchar *camel_spool_summary_encode_x_evolution (CamelSpoolSummary *cls, const Cam
gint camel_spool_summary_decode_x_evolution (CamelSpoolSummary *cls, const gchar *xev, CamelMessageInfo
*info);
/* utility functions - write headers to a file with optional X-Evolution header */
-gint camel_spool_summary_write_headers (gint fd, struct _camel_header_raw *header, gchar *xevline);
+gint camel_spool_summary_write_headers (gint fd, CamelHeaderRaw *header, gchar *xevline);
G_END_DECLS
diff --git a/src/camel/providers/nntp/camel-nntp-folder.c b/src/camel/providers/nntp/camel-nntp-folder.c
index 8e45b11..868ad45 100644
--- a/src/camel/providers/nntp/camel-nntp-folder.c
+++ b/src/camel/providers/nntp/camel-nntp-folder.c
@@ -189,14 +189,8 @@ unset_flagged_flag (const gchar *uid,
info = camel_folder_summary_get (summary, uid);
if (info) {
- CamelMessageInfoBase *base = (CamelMessageInfoBase *) info;
-
- if ((base->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0) {
- base->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
- base->dirty = TRUE;
- }
-
- camel_message_info_unref (info);
+ camel_message_info_set_folder_flagged (info, FALSE);
+ g_clear_object (&info);
}
}
@@ -411,7 +405,7 @@ nntp_folder_append_message_sync (CamelFolder *folder,
CamelMimeFilter *crlffilter;
gint ret;
guint u;
- struct _camel_header_raw *header, *savedhdrs, *n, *tail;
+ CamelHeaderRaw *header, *savedhdrs, *n, *tail;
const gchar *full_name;
gchar *group, *line;
gboolean success = TRUE;
@@ -447,9 +441,9 @@ nntp_folder_append_message_sync (CamelFolder *folder,
/* remove mail 'To', 'CC', and 'BCC' headers */
savedhdrs = NULL;
- tail = (struct _camel_header_raw *) &savedhdrs;
+ tail = (CamelHeaderRaw *) &savedhdrs;
- header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
+ header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers;
n = header->next;
while (n != NULL) {
if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") ||
!g_ascii_strcasecmp (n->name, "Bcc")) {
@@ -549,7 +543,7 @@ nntp_folder_expunge_sync (CamelFolder *folder,
camel_folder_summary_remove (summary, info);
}
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_folder_summary_save_to_db (summary, NULL);
diff --git a/src/camel/providers/nntp/camel-nntp-summary.c b/src/camel/providers/nntp/camel-nntp-summary.c
index d4c47aa..bc0646e 100644
--- a/src/camel/providers/nntp/camel-nntp-summary.c
+++ b/src/camel/providers/nntp/camel-nntp-summary.c
@@ -51,7 +51,7 @@ struct _CamelNNTPSummaryPrivate {
gint xover_setup;
};
-static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *);
+static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, CamelHeaderRaw *);
static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir);
static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error);
@@ -65,8 +65,6 @@ camel_nntp_summary_class_init (CamelNNTPSummaryClass *class)
g_type_class_add_private (class, sizeof (CamelNNTPSummaryPrivate));
folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
- folder_summary_class->message_info_size = sizeof (CamelMessageInfoBase);
- folder_summary_class->content_info_size = sizeof (CamelMessageContentInfo);
folder_summary_class->message_info_new_from_header = message_info_new_from_header;
folder_summary_class->summary_header_from_db = summary_header_from_db;
folder_summary_class->summary_header_to_db = summary_header_to_db;
@@ -90,31 +88,28 @@ camel_nntp_summary_new (CamelFolder *folder)
cns = g_object_new (CAMEL_TYPE_NNTP_SUMMARY, "folder", folder, NULL);
- camel_folder_summary_set_build_content ((CamelFolderSummary *) cns, FALSE);
-
return cns;
}
static CamelMessageInfo *
message_info_new_from_header (CamelFolderSummary *s,
- struct _camel_header_raw *h)
+ CamelHeaderRaw *h)
{
- CamelMessageInfoBase *mi;
+ CamelMessageInfo *mi;
CamelNNTPSummary *cns = (CamelNNTPSummary *) s;
/* error to call without this setup */
if (cns->priv->uid == NULL)
return NULL;
- mi = (CamelMessageInfoBase *) CAMEL_FOLDER_SUMMARY_CLASS
(camel_nntp_summary_parent_class)->message_info_new_from_header (s, h);
+ mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_parent_class)->message_info_new_from_header (s,
h);
if (mi) {
- camel_pstring_free (mi->uid);
- mi->uid = camel_pstring_strdup (cns->priv->uid);
+ camel_message_info_set_uid (mi, cns->priv->uid);
g_free (cns->priv->uid);
cns->priv->uid = NULL;
}
- return (CamelMessageInfo *) mi;
+ return mi;
}
static gboolean
@@ -129,9 +124,9 @@ summary_header_from_db (CamelFolderSummary *s,
part = mir->bdata;
- cns->version = bdata_extract_digit (&part);
- cns->high = bdata_extract_digit (&part);
- cns->low = bdata_extract_digit (&part);
+ cns->version = camel_util_bdata_get_number (&part, 0);
+ cns->high = camel_util_bdata_get_number (&part, 0);
+ cns->low = camel_util_bdata_get_number (&part, 0);
return TRUE;
}
@@ -169,7 +164,7 @@ add_range_xover (CamelNNTPSummary *cns,
CamelSettings *settings;
CamelService *service;
CamelFolderSummary *s;
- struct _camel_header_raw *headers = NULL;
+ CamelHeaderRaw *headers = NULL;
gchar *line, *tab;
gchar *host;
guint len;
@@ -268,13 +263,14 @@ add_range_xover (CamelNNTPSummary *cns,
CamelMessageInfo *mi;
mi = camel_folder_summary_info_new_from_header (s, headers);
- ((CamelMessageInfoBase *) mi)->size = size;
- camel_folder_summary_add (s, mi);
+ camel_message_info_set_size (mi, size);
+ camel_folder_summary_add (s, mi, FALSE);
cns->high = n;
camel_folder_change_info_add_uid (changes, camel_message_info_get_uid (mi));
if (folder_filter_recent)
camel_folder_change_info_recent_uid (changes,
camel_message_info_get_uid (mi));
+ g_clear_object (&mi);
}
}
@@ -370,7 +366,7 @@ add_range_head (CamelNNTPSummary *cns,
if (camel_mime_parser_init_with_stream (mp, CAMEL_STREAM (nntp_stream),
error) == -1)
goto error;
mi = camel_folder_summary_info_new_from_parser (s, mp);
- camel_folder_summary_add (s, mi);
+ camel_folder_summary_add (s, mi, FALSE);
while (camel_mime_parser_step (mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_EOF)
;
if (mi == NULL) {
@@ -380,6 +376,7 @@ add_range_head (CamelNNTPSummary *cns,
camel_folder_change_info_add_uid (changes, camel_message_info_get_uid (mi));
if (folder_filter_recent)
camel_folder_change_info_recent_uid (changes,
camel_message_info_get_uid (mi));
+ g_clear_object (&mi);
}
if (cns->priv->uid) {
g_free (cns->priv->uid);
@@ -504,7 +501,7 @@ camel_nntp_summary_check (CamelNNTPSummary *cns,
mi = camel_folder_summary_peek_loaded (s, uid);
if (mi) {
camel_folder_summary_remove (s, mi);
- camel_message_info_unref (mi);
+ g_clear_object (&mi);
} else {
camel_folder_summary_remove_uid (s, uid);
}
diff --git a/src/camel/providers/pop3/camel-pop3-folder.c b/src/camel/providers/pop3/camel-pop3-folder.c
index bb7042e..65ffef5 100644
--- a/src/camel/providers/pop3/camel-pop3-folder.c
+++ b/src/camel/providers/pop3/camel-pop3-folder.c
@@ -90,7 +90,7 @@ cmd_builduid (CamelPOP3Engine *pe,
{
GChecksum *checksum;
CamelPOP3FolderInfo *fi = data;
- struct _camel_header_raw *h;
+ CamelHeaderRaw *h;
CamelMimeParser *mp;
guint8 *digest;
gsize length;
@@ -372,8 +372,8 @@ pop3_folder_get_filename (CamelFolder *folder,
static gboolean
pop3_folder_set_message_flags (CamelFolder *folder,
const gchar *uid,
- CamelMessageFlags flags,
- CamelMessageFlags set)
+ guint32 flags,
+ guint32 set)
{
CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder);
CamelPOP3FolderInfo *fi;
diff --git a/src/camel/providers/sendmail/camel-sendmail-provider.c
b/src/camel/providers/sendmail/camel-sendmail-provider.c
index 7a8124a..a79afc7 100644
--- a/src/camel/providers/sendmail/camel-sendmail-provider.c
+++ b/src/camel/providers/sendmail/camel-sendmail-provider.c
@@ -52,8 +52,8 @@ camel_provider_module_init (void)
sendmail_provider.object_types[CAMEL_PROVIDER_TRANSPORT] =
CAMEL_TYPE_SENDMAIL_TRANSPORT;
- sendmail_provider.url_hash = camel_url_hash;
- sendmail_provider.url_equal = camel_url_equal;
+ sendmail_provider.url_hash = (GHashFunc) camel_url_hash;
+ sendmail_provider.url_equal = (GEqualFunc) camel_url_equal;
sendmail_provider.translation_domain = GETTEXT_PACKAGE;
camel_provider_register (&sendmail_provider);
diff --git a/src/camel/providers/sendmail/camel-sendmail-transport.c
b/src/camel/providers/sendmail/camel-sendmail-transport.c
index 7767945..0e069d5 100644
--- a/src/camel/providers/sendmail/camel-sendmail-transport.c
+++ b/src/camel/providers/sendmail/camel-sendmail-transport.c
@@ -112,7 +112,7 @@ sendmail_send_to_sync (CamelTransport *transport,
GCancellable *cancellable,
GError **error)
{
- struct _camel_header_raw *header, *savedbcc, *n, *tail;
+ CamelHeaderRaw *header, *savedbcc, *n, *tail;
const gchar *from_addr, *addr;
GPtrArray *argv_arr;
gint i, len, fd[2], nullfd, wstat;
@@ -204,9 +204,9 @@ sendmail_send_to_sync (CamelTransport *transport,
/* unlink the bcc headers */
savedbcc = NULL;
- tail = (struct _camel_header_raw *) &savedbcc;
+ tail = (CamelHeaderRaw *) &savedbcc;
- header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
+ header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers;
n = header->next;
while (n != NULL) {
if (!g_ascii_strcasecmp (n->name, "Bcc")) {
diff --git a/src/camel/providers/smtp/camel-smtp-transport.c b/src/camel/providers/smtp/camel-smtp-transport.c
index 44e96bf..1a555c3 100644
--- a/src/camel/providers/smtp/camel-smtp-transport.c
+++ b/src/camel/providers/smtp/camel-smtp-transport.c
@@ -1639,7 +1639,7 @@ smtp_data (CamelSmtpTransport *transport,
GCancellable *cancellable,
GError **error)
{
- struct _camel_header_raw *header, *savedbcc, *n, *tail;
+ CamelHeaderRaw *header, *savedbcc, *n, *tail;
CamelBestencEncoding enctype = CAMEL_BESTENC_8BIT;
CamelStream *filtered_stream;
gchar *cmdbuf, *respbuf = NULL;
@@ -1696,9 +1696,9 @@ smtp_data (CamelSmtpTransport *transport,
/* unlink the bcc headers */
savedbcc = NULL;
- tail = (struct _camel_header_raw *) &savedbcc;
+ tail = (CamelHeaderRaw *) &savedbcc;
- header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
+ header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers;
n = header->next;
while (n != NULL) {
if (!g_ascii_strcasecmp (n->name, "Bcc")) {
diff --git a/src/camel/tests/lib/folders.c b/src/camel/tests/lib/folders.c
index 4db8c89..a2edadb 100644
--- a/src/camel/tests/lib/folders.c
+++ b/src/camel/tests/lib/folders.c
@@ -52,7 +52,7 @@ test_folder_counts (CamelFolder *folder,
info = camel_folder_get_message_info (folder, s->pdata[i]);
if (camel_message_info_get_flags (info) & CAMEL_MESSAGE_SEEN)
myunread--;
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
check (unread == myunread);
camel_folder_free_uids (folder, s);
@@ -109,7 +109,7 @@ test_folder_message (CamelFolder *folder,
info = camel_folder_get_message_info (folder, uid);
check (info != NULL);
check (strcmp (camel_message_info_get_uid (info), uid) == 0);
- camel_message_info_unref (info);
+ g_clear_object (&info);
/* then, getting message */
msg = camel_folder_get_message_sync (folder, uid, NULL, &error);
@@ -462,7 +462,7 @@ test_folder_message_ops (CamelSession *session,
check_msg (
strcmp (camel_message_info_get_subject (info), subject) == 0,
"info->subject %s", camel_message_info_get_subject (info));
- camel_message_info_unref (info);
+ g_clear_object (&info);
}
camel_folder_free_uids (folder, uids);
pull ();
@@ -515,7 +515,7 @@ test_folder_message_ops (CamelSession *session,
strcmp (camel_message_info_get_subject (info), subject) == 0,
"info->subject %s", camel_message_info_get_subject (info));
test_free (subject);
- camel_message_info_unref (info);
+ g_clear_object (&info);
pull ();
}
@@ -544,7 +544,7 @@ test_folder_message_ops (CamelSession *session,
strcmp (camel_message_info_get_subject (info), subject) == 0,
"info->subject %s", camel_message_info_get_subject (info));
test_free (subject);
- camel_message_info_unref (info);
+ g_clear_object (&info);
pull ();
}
pull ();
@@ -575,7 +575,7 @@ test_folder_message_ops (CamelSession *session,
strcmp (camel_message_info_get_subject (info), subject) == 0,
"info->subject %s", camel_message_info_get_subject (info));
test_free (subject);
- camel_message_info_unref (info);
+ g_clear_object (&info);
pull ();
}
pull ();
diff --git a/src/vala/Camel-1.2.metadata b/src/vala/Camel-1.2.metadata
index eb66385..74aded7 100644
--- a/src/vala/Camel-1.2.metadata
+++ b/src/vala/Camel-1.2.metadata
@@ -6,7 +6,9 @@ FilterDriver.set* skip=false
// We need to skip the methods because the signals and virtual methods have the same name
Object.state_read#method skip
+Object.state_read.fp type="GLib.FileStream"
Object.state_write#method skip
+Object.state_write.fp type="GLib.FileStream"
Operation.pop_message skip
Operation.progress skip
@@ -23,3 +25,13 @@ localtime_with_offset.tm type="Posix.tm"
mktime_utc.tm type="Posix.tm"
HeaderAddress.new_name#constructor name="with_name"
+
+// FILE* are supported by Vala
+StoreSummary.store_info_save.file type="GLib.FileStream"
+StoreSummary.summary_header_load.file type="GLib.FileStream"
+StoreSummary.summary_header_save.file type="GLib.FileStream"
+CertDB.cert_load.istream type="GLib.FileStream"
+CertDB.cert_save.ostream type="GLib.FileStream"
+CertDB.header_load.istream type="GLib.FileStream"
+CertDB.header_save.ostream type="GLib.FileStream"
+FilterDriver.set_logfile.logfile type="GLib.FileStream"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]