1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
4 *
5 * This library is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "evolution-data-server-config.h"
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "camel-db.h"
24 #include "camel-enumtypes.h"
25 #include "camel-folder.h"
26 #include "camel-folder-summary.h"
27 #include "camel-message-info-base.h"
28 #include "camel-string-utils.h"
29 #include "camel-weak-ref-group.h"
30
31 #include "camel-message-info.h"
32
33 struct _CamelMessageInfoPrivate {
34 GRecMutex property_lock;
35
36 CamelWeakRefGroup *summary_wrg; /* CamelFolderSummary * */
37 gboolean dirty; /* whether requires save to local disk/summary */
38 const gchar *uid; /* allocated in the string pool */
39 gboolean abort_notifications;
40 gboolean thaw_notify_folder;
41 gboolean thaw_notify_folder_with_counts;
42 guint freeze_notifications;
43 guint folder_flagged_stamp;
44 };
45
46 enum {
47 PROP_0,
48 PROP_SUMMARY,
49 PROP_DIRTY,
50 PROP_FOLDER_FLAGGED,
51 PROP_FOLDER_FLAGGED_STAMP,
52 PROP_ABORT_NOTIFICATIONS,
53 PROP_UID,
54 PROP_FLAGS,
55 PROP_USER_FLAGS,
56 PROP_USER_TAGS,
57 PROP_SUBJECT,
58 PROP_FROM,
59 PROP_TO,
60 PROP_CC,
61 PROP_MLIST,
62 PROP_SIZE,
63 PROP_DATE_SENT,
64 PROP_DATE_RECEIVED,
65 PROP_MESSAGE_ID,
66 PROP_REFERENCES,
67 PROP_HEADERS,
68 PROP_USER_HEADERS,
69 PROP_PREVIEW
70 };
71
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(CamelMessageInfo,camel_message_info,G_TYPE_OBJECT)72 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (CamelMessageInfo, camel_message_info, G_TYPE_OBJECT)
73
74 static CamelMessageInfo *
75 message_info_clone (const CamelMessageInfo *mi,
76 CamelFolderSummary *assign_summary)
77 {
78 CamelMessageInfo *result;
79 const gchar *uid;
80 const GArray *references;
81 const CamelNameValueArray *headers;
82
83 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
84 if (assign_summary)
85 g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (assign_summary), NULL);
86
87 /* Make sure the 'mi' doesn't change while copying the values. */
88 camel_message_info_property_lock (mi);
89
90 if (!assign_summary) {
91 CamelFolderSummary *mi_summary;
92
93 mi_summary = camel_message_info_ref_summary (mi);
94 result = camel_message_info_new (mi_summary);
95 g_clear_object (&mi_summary);
96 } else {
97 result = camel_message_info_new (assign_summary);
98 }
99
100 g_object_freeze_notify (G_OBJECT (result));
101 camel_message_info_set_abort_notifications (result, TRUE);
102
103 uid = camel_message_info_pooldup_uid (mi);
104 camel_message_info_set_uid (result, uid);
105 camel_pstring_free (uid);
106
107 camel_message_info_take_user_flags (result, camel_message_info_dup_user_flags (mi));
108 camel_message_info_take_user_tags (result, camel_message_info_dup_user_tags (mi));
109 camel_message_info_set_subject (result, camel_message_info_get_subject (mi));
110 camel_message_info_set_from (result, camel_message_info_get_from (mi));
111 camel_message_info_set_to (result, camel_message_info_get_to (mi));
112 camel_message_info_set_cc (result, camel_message_info_get_cc (mi));
113 camel_message_info_set_mlist (result, camel_message_info_get_mlist (mi));
114 camel_message_info_set_preview (result, camel_message_info_get_preview (mi));
115 camel_message_info_set_size (result, camel_message_info_get_size (mi));
116 camel_message_info_set_date_sent (result, camel_message_info_get_date_sent (mi));
117 camel_message_info_set_date_received (result, camel_message_info_get_date_received (mi));
118 camel_message_info_set_message_id (result, camel_message_info_get_message_id (mi));
119
120 references = camel_message_info_get_references (mi);
121 if (references && references->len) {
122 GArray *copy;
123 guint ii;
124
125 copy = g_array_sized_new (FALSE, FALSE, sizeof (guint64), references->len);
126
127 for (ii = 0; ii < references->len; ii++) {
128 guint64 refr = g_array_index (references, guint64, ii);
129
130 g_array_append_val (copy, refr);
131 }
132
133 camel_message_info_take_references (result, copy);
134 }
135
136 headers = camel_message_info_get_headers (mi);
137 if (headers) {
138 camel_message_info_take_headers (result,
139 camel_name_value_array_copy (headers));
140 }
141
142 headers = camel_message_info_get_user_headers (mi);
143 if (headers) {
144 camel_message_info_take_user_headers (result,
145 camel_name_value_array_copy (headers));
146 }
147
148 /* Set flags as the last, to not overwrite 'folder-flagged' flag by
149 the "changes" when copying fields. */
150 camel_message_info_set_flags (result, ~0, camel_message_info_get_flags (mi));
151
152 camel_message_info_property_unlock (mi);
153
154 /* Also ensure 'dirty' flag, thus it can be eventually saved. */
155 camel_message_info_set_dirty (result, TRUE);
156
157 camel_message_info_set_abort_notifications (result, FALSE);
158 g_object_thaw_notify (G_OBJECT (result));
159
160 return result;
161 }
162
163 static gboolean
message_info_load(CamelMessageInfo * mi,const CamelMIRecord * record,gchar ** bdata_ptr)164 message_info_load (CamelMessageInfo *mi,
165 const CamelMIRecord *record,
166 /* const */ gchar **bdata_ptr)
167 {
168 gint ii, count;
169 gchar *part, *label;
170
171 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
172 g_return_val_if_fail (record != NULL, FALSE);
173 g_return_val_if_fail (bdata_ptr != NULL, FALSE);
174
175 camel_message_info_set_uid (mi, record->uid);
176 camel_message_info_set_flags (mi, ~0, record->flags);
177 camel_message_info_set_size (mi, record->size);
178 camel_message_info_set_date_sent (mi, record->dsent);
179 camel_message_info_set_date_received (mi, record->dreceived);
180
181 camel_message_info_set_subject (mi, record->subject);
182 camel_message_info_set_from (mi, record->from);
183 camel_message_info_set_to (mi, record->to);
184 camel_message_info_set_cc (mi, record->cc);
185 camel_message_info_set_mlist (mi, record->mlist);
186 camel_message_info_set_preview (mi, record->preview);
187
188 /* Extract Message id & References */
189 part = record->part;
190 if (part) {
191 CamelSummaryMessageID message_id;
192
193 message_id.id.part.hi = camel_util_bdata_get_number (&part, 0);
194 message_id.id.part.lo = camel_util_bdata_get_number (&part, 0);
195
196 camel_message_info_set_message_id (mi, message_id.id.id);
197
198 count = camel_util_bdata_get_number (&part, 0);
199
200 if (count > 0) {
201 GArray *references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), count);
202
203 for (ii = 0; ii < count; ii++) {
204 message_id.id.part.hi = camel_util_bdata_get_number (&part, 0);
205 message_id.id.part.lo = camel_util_bdata_get_number (&part, 0);
206
207 g_array_append_val (references, message_id.id.id);
208 }
209
210 camel_message_info_take_references (mi, references);
211 }
212 }
213
214 /* Extract User flags/labels */
215 part = record->labels;
216 if (part) {
217 CamelNamedFlags *user_flags;
218
219 user_flags = camel_named_flags_new ();
220
221 label = part;
222 for (ii = 0; part[ii]; ii++) {
223 if (part[ii] == ' ') {
224 part[ii] = 0;
225 if (label && *label)
226 camel_named_flags_insert (user_flags, label);
227 label = &(part[ii + 1]);
228 part[ii] = ' ';
229 }
230 }
231 if (label && *label)
232 camel_named_flags_insert (user_flags, label);
233
234 if (camel_named_flags_get_length (user_flags) == 0) {
235 camel_named_flags_free (user_flags);
236 user_flags = NULL;
237 }
238
239 camel_message_info_take_user_flags (mi, user_flags);
240 }
241
242 /* Extract User tags */
243 part = record->usertags;
244 if (part) {
245 CamelNameValueArray *user_tags;
246
247 count = camel_util_bdata_get_number (&part, 0);
248
249 user_tags = camel_name_value_array_new_sized (count);
250
251 for (ii = 0; ii < count; ii++) {
252 gchar *name, *value;
253
254 name = camel_util_bdata_get_string (&part, NULL);
255 value = camel_util_bdata_get_string (&part, NULL);
256
257 if (name)
258 camel_name_value_array_set_named (user_tags, CAMEL_COMPARE_CASE_SENSITIVE, name, value ? value : "");
259
260 g_free (name);
261 g_free (value);
262 }
263
264 if (camel_name_value_array_get_length (user_tags) == 0) {
265 camel_name_value_array_free (user_tags);
266 user_tags = NULL;
267 }
268
269 camel_message_info_take_user_tags (mi, user_tags);
270 }
271
272 /* Extract User headers */
273 part = record->userheaders;
274 if (part) {
275 CamelNameValueArray *user_headers;
276
277 count = camel_util_bdata_get_number (&part, 0);
278
279 user_headers = camel_name_value_array_new_sized (count);
280
281 for (ii = 0; ii < count; ii++) {
282 gchar *name, *value;
283
284 name = camel_util_bdata_get_string (&part, NULL);
285 value = camel_util_bdata_get_string (&part, NULL);
286
287 if (name)
288 camel_name_value_array_set_named (user_headers, CAMEL_COMPARE_CASE_SENSITIVE, name, value ? value : "");
289
290 g_free (name);
291 g_free (value);
292 }
293
294 if (camel_name_value_array_get_length (user_headers) == 0) {
295 camel_name_value_array_free (user_headers);
296 user_headers = NULL;
297 }
298
299 camel_message_info_take_user_headers (mi, user_headers);
300 }
301
302 return TRUE;
303 }
304
305 static gboolean
message_info_save(const CamelMessageInfo * mi,CamelMIRecord * record,GString * bdata_str)306 message_info_save (const CamelMessageInfo *mi,
307 CamelMIRecord *record,
308 GString *bdata_str)
309 {
310 GString *tmp;
311 CamelSummaryMessageID message_id;
312 const CamelNamedFlags *user_flags;
313 const CamelNameValueArray *user_tags;
314 const GArray *references;
315 guint32 read_or_flags = CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_JUNK;
316
317 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
318 g_return_val_if_fail (record != NULL, FALSE);
319 g_return_val_if_fail (bdata_str != NULL, FALSE);
320
321 record->uid = camel_pstring_strdup (camel_message_info_get_uid (mi));
322 record->flags = camel_message_info_get_flags (mi);
323
324 if ((record->flags & CAMEL_MESSAGE_JUNK) != 0) {
325 CamelFolderSummary *folder_summary;
326
327 folder_summary = camel_message_info_ref_summary (mi);
328 if (folder_summary) {
329 CamelFolder *folder;
330
331 folder = camel_folder_summary_get_folder (folder_summary);
332 if (folder) {
333 guint32 folder_flags = camel_folder_get_flags (folder);
334
335 /* Do not consider Junk flag as message being read when it's a Junk folder */
336 if ((folder_flags & CAMEL_FOLDER_IS_JUNK) != 0)
337 read_or_flags = read_or_flags & (~CAMEL_MESSAGE_JUNK);
338 }
339
340 g_object_unref (folder_summary);
341 }
342 }
343
344 record->read = ((record->flags & (CAMEL_MESSAGE_SEEN | read_or_flags))) ? 1 : 0;
345 record->deleted = (record->flags & CAMEL_MESSAGE_DELETED) != 0 ? 1 : 0;
346 record->replied = (record->flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 1 : 0;
347 record->important = (record->flags & CAMEL_MESSAGE_FLAGGED) != 0 ? 1 : 0;
348 record->junk = (record->flags & CAMEL_MESSAGE_JUNK) != 0 ? 1 : 0;
349 record->dirty = (record->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 ? 1 : 0;
350 record->attachment = (record->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0 ? 1 : 0;
351
352 record->size = camel_message_info_get_size (mi);
353 record->dsent = camel_message_info_get_date_sent (mi);
354 record->dreceived = camel_message_info_get_date_received (mi);
355
356 record->subject = camel_pstring_strdup (camel_message_info_get_subject (mi));
357 record->from = camel_pstring_strdup (camel_message_info_get_from (mi));
358 record->to = camel_pstring_strdup (camel_message_info_get_to (mi));
359 record->cc = camel_pstring_strdup (camel_message_info_get_cc (mi));
360 record->mlist = camel_pstring_strdup (camel_message_info_get_mlist (mi));
361 record->preview = g_strdup (camel_message_info_get_preview (mi));
362
363 record->followup_flag = g_strdup (camel_message_info_get_user_tag (mi, "follow-up"));
364 record->followup_completed_on = g_strdup (camel_message_info_get_user_tag (mi, "completed-on"));
365 record->followup_due_by = g_strdup (camel_message_info_get_user_tag (mi, "due-by"));
366
367 tmp = g_string_new (NULL);
368 message_id.id.id = camel_message_info_get_message_id (mi);
369 g_string_append_printf (tmp, "%lu %lu ", (gulong) message_id.id.part.hi, (gulong) message_id.id.part.lo);
370 references = camel_message_info_get_references (mi);
371 if (references) {
372 guint ii;
373
374 g_string_append_printf (tmp, "%lu", (gulong) references->len);
375 for (ii = 0; ii < references->len; ii++) {
376 message_id.id.id = g_array_index (references, guint64, ii);
377
378 g_string_append_printf (tmp, " %lu %lu", (gulong) message_id.id.part.hi, (gulong) message_id.id.part.lo);
379 }
380 } else {
381 g_string_append_c (tmp, '0');
382 }
383 record->part = g_string_free (tmp, FALSE);
384
385 tmp = g_string_new (NULL);
386 user_flags = camel_message_info_get_user_flags (mi);
387 if (user_flags) {
388 guint ii, count;
389
390 count = camel_named_flags_get_length (user_flags);
391 for (ii = 0; ii < count; ii++) {
392 const gchar *name = camel_named_flags_get (user_flags, ii);
393
394 if (name && *name) {
395 if (tmp->len)
396 g_string_append_c (tmp, ' ');
397 g_string_append (tmp, name);
398 }
399 }
400 }
401 record->labels = g_string_free (tmp, FALSE);
402
403 tmp = g_string_new (NULL);
404 user_tags = camel_message_info_get_user_tags (mi);
405 if (user_tags) {
406 guint ii, count;
407
408 count = camel_name_value_array_get_length (user_tags);
409 g_string_append_printf (tmp, "%lu", (gulong) count);
410
411 for (ii = 0; ii < count; ii++) {
412 const gchar *name = NULL, *value = NULL;
413
414 if (camel_name_value_array_get (user_tags, ii, &name, &value)) {
415 if (!name)
416 name = "";
417 if (!value)
418 value = "";
419
420 g_string_append_printf (tmp, " %lu-%s %lu-%s", (gulong) strlen (name), name, (gulong) strlen (value), value);
421 }
422 }
423 } else {
424 g_string_append_c (tmp, '0');
425 }
426 record->usertags = g_string_free (tmp, FALSE);
427
428 tmp = g_string_new (NULL);
429 user_tags = camel_message_info_get_user_headers (mi);
430 if (user_tags) {
431 guint32 ii, count;
432
433 count = camel_name_value_array_get_length (user_tags);
434 g_string_append_printf (tmp, "%" G_GUINT32_FORMAT, count);
435
436 for (ii = 0; ii < count; ii++) {
437 const gchar *name = NULL, *value = NULL;
438
439 if (camel_name_value_array_get (user_tags, ii, &name, &value) && name && value) {
440 g_string_append_printf (tmp, " %" G_GUINT32_FORMAT "-%s %" G_GUINT32_FORMAT "-%s",
441 (guint32) strlen (name), name,
442 (guint32) strlen (value), value);
443 }
444 }
445 } else {
446 g_string_append_c (tmp, '0');
447 }
448 record->userheaders = g_string_free (tmp, FALSE);
449
450 return TRUE;
451 }
452
453 static void
message_info_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)454 message_info_set_property (GObject *object,
455 guint property_id,
456 const GValue *value,
457 GParamSpec *pspec)
458 {
459 CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
460
461 switch (property_id) {
462 case PROP_SUMMARY:
463 camel_weak_ref_group_set (mi->priv->summary_wrg, g_value_get_object (value));
464 return;
465
466 case PROP_DIRTY:
467 camel_message_info_set_dirty (mi, g_value_get_boolean (value));
468 return;
469
470 case PROP_FOLDER_FLAGGED:
471 camel_message_info_set_folder_flagged (mi, g_value_get_boolean (value));
472 return;
473
474 case PROP_ABORT_NOTIFICATIONS:
475 camel_message_info_set_abort_notifications (mi, g_value_get_boolean (value));
476 return;
477
478 case PROP_UID:
479 camel_message_info_set_uid (mi, g_value_get_string (value));
480 return;
481
482 case PROP_FLAGS:
483 camel_message_info_set_flags (mi, ~0, g_value_get_flags (value));
484 return;
485
486 case PROP_USER_FLAGS:
487 camel_message_info_take_user_flags (mi, g_value_dup_boxed (value));
488 return;
489
490 case PROP_USER_TAGS:
491 camel_message_info_take_user_tags (mi, g_value_dup_boxed (value));
492 return;
493
494 case PROP_SUBJECT:
495 camel_message_info_set_subject (mi, g_value_get_string (value));
496 return;
497
498 case PROP_FROM:
499 camel_message_info_set_from (mi, g_value_get_string (value));
500 return;
501
502 case PROP_TO:
503 camel_message_info_set_to (mi, g_value_get_string (value));
504 return;
505
506 case PROP_CC:
507 camel_message_info_set_cc (mi, g_value_get_string (value));
508 return;
509
510 case PROP_MLIST:
511 camel_message_info_set_mlist (mi, g_value_get_string (value));
512 return;
513
514 case PROP_SIZE:
515 camel_message_info_set_size (mi, g_value_get_uint (value));
516 return;
517
518 case PROP_DATE_SENT:
519 camel_message_info_set_date_sent (mi, g_value_get_int64 (value));
520 return;
521
522 case PROP_DATE_RECEIVED:
523 camel_message_info_set_date_received (mi, g_value_get_int64 (value));
524 return;
525
526 case PROP_MESSAGE_ID:
527 camel_message_info_set_message_id (mi, g_value_get_uint64 (value));
528 return;
529
530 case PROP_REFERENCES:
531 camel_message_info_take_references (mi, g_value_dup_boxed (value));
532 return;
533
534 case PROP_HEADERS:
535 camel_message_info_take_headers (mi, g_value_dup_boxed (value));
536 return;
537
538 case PROP_USER_HEADERS:
539 camel_message_info_take_user_headers (mi, g_value_dup_boxed (value));
540 return;
541
542 case PROP_PREVIEW:
543 camel_message_info_set_preview (mi, g_value_get_string (value));
544 return;
545 }
546
547 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
548 }
549
550 static void
message_info_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)551 message_info_get_property (GObject *object,
552 guint property_id,
553 GValue *value,
554 GParamSpec *pspec)
555 {
556 CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
557
558 switch (property_id) {
559 case PROP_SUMMARY:
560 g_value_take_object (value, camel_message_info_ref_summary (mi));
561 return;
562
563 case PROP_DIRTY:
564 g_value_set_boolean (value, camel_message_info_get_dirty (mi));
565 return;
566
567 case PROP_FOLDER_FLAGGED:
568 g_value_set_boolean (value, camel_message_info_get_folder_flagged (mi));
569 return;
570
571 case PROP_FOLDER_FLAGGED_STAMP:
572 g_value_set_uint (value, camel_message_info_get_folder_flagged_stamp (mi));
573 return;
574
575 case PROP_ABORT_NOTIFICATIONS:
576 g_value_set_boolean (value, camel_message_info_get_abort_notifications (mi));
577 return;
578
579 case PROP_UID:
580 g_value_set_string (value, camel_message_info_get_uid (mi));
581 return;
582
583 case PROP_FLAGS:
584 g_value_set_flags (value, camel_message_info_get_flags (mi));
585 return;
586
587 case PROP_USER_FLAGS:
588 g_value_take_boxed (value, camel_message_info_dup_user_flags (mi));
589 return;
590
591 case PROP_USER_TAGS:
592 g_value_take_boxed (value, camel_message_info_dup_user_tags (mi));
593 return;
594
595 case PROP_SUBJECT:
596 g_value_set_string (value, camel_message_info_get_subject (mi));
597 return;
598
599 case PROP_FROM:
600 g_value_set_string (value, camel_message_info_get_from (mi));
601 return;
602
603 case PROP_TO:
604 g_value_set_string (value, camel_message_info_get_to (mi));
605 return;
606
607 case PROP_CC:
608 g_value_set_string (value, camel_message_info_get_cc (mi));
609 return;
610
611 case PROP_MLIST:
612 g_value_set_string (value, camel_message_info_get_mlist (mi));
613 return;
614
615 case PROP_SIZE:
616 g_value_set_uint (value, camel_message_info_get_size (mi));
617 return;
618
619 case PROP_DATE_SENT:
620 g_value_set_int64 (value, camel_message_info_get_date_sent (mi));
621 return;
622
623 case PROP_DATE_RECEIVED:
624 g_value_set_int64 (value, camel_message_info_get_date_received (mi));
625 return;
626
627 case PROP_MESSAGE_ID:
628 g_value_set_uint64 (value, camel_message_info_get_message_id (mi));
629 return;
630
631 case PROP_REFERENCES:
632 g_value_take_boxed (value, camel_message_info_dup_references (mi));
633 return;
634
635 case PROP_HEADERS:
636 g_value_take_boxed (value, camel_message_info_dup_headers (mi));
637 return;
638
639 case PROP_USER_HEADERS:
640 g_value_take_boxed (value, camel_message_info_dup_user_headers (mi));
641 return;
642
643 case PROP_PREVIEW:
644 g_value_take_string (value, camel_message_info_dup_preview (mi));
645 return;
646 }
647
648 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
649 }
650
651 static void
message_info_dispose(GObject * object)652 message_info_dispose (GObject *object)
653 {
654 CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
655
656 camel_weak_ref_group_set (mi->priv->summary_wrg, NULL);
657 camel_pstring_free (mi->priv->uid);
658 mi->priv->uid = NULL;
659
660 /* Chain up to parent's method. */
661 G_OBJECT_CLASS (camel_message_info_parent_class)->dispose (object);
662 }
663
664 static void
message_info_finalize(GObject * object)665 message_info_finalize (GObject *object)
666 {
667 CamelMessageInfo *mi = CAMEL_MESSAGE_INFO (object);
668
669 camel_weak_ref_group_unref (mi->priv->summary_wrg);
670 g_rec_mutex_clear (&mi->priv->property_lock);
671
672 /* Chain up to parent's method. */
673 G_OBJECT_CLASS (camel_message_info_parent_class)->finalize (object);
674 }
675
676 static void
camel_message_info_class_init(CamelMessageInfoClass * class)677 camel_message_info_class_init (CamelMessageInfoClass *class)
678 {
679 GObjectClass *object_class;
680
681 class->clone = message_info_clone;
682 class->load = message_info_load;
683 class->save = message_info_save;
684
685 object_class = G_OBJECT_CLASS (class);
686 object_class->set_property = message_info_set_property;
687 object_class->get_property = message_info_get_property;
688 object_class->dispose = message_info_dispose;
689 object_class->finalize = message_info_finalize;
690
691 /**
692 * CamelMessageInfo:summary
693 *
694 * The #CamelFolderSummary to which the message info belongs, or %NULL.
695 * It can be set only during construction of the object.
696 *
697 * Since: 3.24
698 **/
699 g_object_class_install_property (
700 object_class,
701 PROP_SUMMARY,
702 g_param_spec_object (
703 "summary",
704 "Summary",
705 NULL,
706 CAMEL_TYPE_FOLDER_SUMMARY,
707 G_PARAM_READWRITE |
708 G_PARAM_CONSTRUCT_ONLY |
709 G_PARAM_STATIC_STRINGS));
710
711 /**
712 * CamelMessageInfo:uid
713 *
714 * A unique ID of the message in its folder.
715 *
716 * Since: 3.24
717 **/
718 g_object_class_install_property (
719 object_class,
720 PROP_UID,
721 g_param_spec_string (
722 "uid",
723 "UID",
724 NULL,
725 NULL,
726 G_PARAM_READWRITE |
727 G_PARAM_EXPLICIT_NOTIFY |
728 G_PARAM_STATIC_STRINGS));
729
730 /**
731 * CamelMessageInfo:dirty
732 *
733 * Flag, whether the info is changed and requires save to disk.
734 * Compare with CamelMessageInfo:folder-flagged
735 *
736 * Since: 3.24
737 **/
738 g_object_class_install_property (
739 object_class,
740 PROP_DIRTY,
741 g_param_spec_boolean (
742 "dirty",
743 "Dirty",
744 NULL,
745 FALSE,
746 G_PARAM_READWRITE |
747 G_PARAM_EXPLICIT_NOTIFY |
748 G_PARAM_STATIC_STRINGS));
749
750 /**
751 * CamelMessageInfo:folder-flagged
752 *
753 * Flag, whether the info is changed and requires save to
754 * the destination store/server. This is different from
755 * the CamelMessageInfo:dirty, which takes care of the local
756 * information only.
757 *
758 * Since: 3.24
759 **/
760 g_object_class_install_property (
761 object_class,
762 PROP_FOLDER_FLAGGED,
763 g_param_spec_boolean (
764 "folder-flagged",
765 "Folder Flagged",
766 NULL,
767 FALSE,
768 G_PARAM_READWRITE |
769 G_PARAM_EXPLICIT_NOTIFY |
770 G_PARAM_STATIC_STRINGS));
771
772 /**
773 * CamelMessageInfo:folder-flagged-stamp
774 *
775 * The 'folder-flagged-stamp' is a stamp of the 'folder-flagged' flag. This stamp
776 * changes whenever anything would mark the @mi 'folder-flagged', regardless the @mi
777 * being already 'folder-flagged'. It can be used to recognize changes
778 * on the 'folder-flagged' flag during the time.
779 *
780 * Since: 3.24
781 **/
782 g_object_class_install_property (
783 object_class,
784 PROP_FOLDER_FLAGGED_STAMP,
785 g_param_spec_uint (
786 "folder-flagged-stamp",
787 "Folder Flagged Stamp",
788 NULL,
789 0, G_MAXUINT, 0,
790 G_PARAM_READABLE |
791 G_PARAM_STATIC_STRINGS));
792
793 /**
794 * CamelMessageInfo:abort-notifications
795 *
796 * Flag, whether the info is currently aborting notifications. It is used to avoid
797 * unnecessary 'folder-flagged' and 'dirty' flags changes and also to avoid
798 * associated folder's "changed" signal.
799 *f
800 * Since: 3.24
801 **/
802 g_object_class_install_property (
803 object_class,
804 PROP_ABORT_NOTIFICATIONS,
805 g_param_spec_boolean (
806 "abort-notifications",
807 "Abort Notifications",
808 NULL,
809 FALSE,
810 G_PARAM_READWRITE |
811 G_PARAM_EXPLICIT_NOTIFY |
812 G_PARAM_STATIC_STRINGS));
813
814 /**
815 * CamelMessageInfo:flags
816 *
817 * Bit-or of #CamelMessageFlags.
818 *
819 * Since: 3.24
820 **/
821 g_object_class_install_property (
822 object_class,
823 PROP_FLAGS,
824 g_param_spec_flags (
825 "flags",
826 "Flags",
827 NULL,
828 CAMEL_TYPE_MESSAGE_FLAGS,
829 0,
830 G_PARAM_READWRITE |
831 G_PARAM_EXPLICIT_NOTIFY |
832 G_PARAM_STATIC_STRINGS));
833
834 /**
835 * CamelMessageInfo:user-flags
836 *
837 * User flags for the associated message. Can be %NULL.
838 * Unlike user-tags, which can contain various values, the user-flags
839 * can only be set or not.
840 *
841 * Since: 3.24
842 **/
843 g_object_class_install_property (
844 object_class,
845 PROP_USER_FLAGS,
846 g_param_spec_boxed (
847 "user-flags",
848 "User Flags",
849 NULL,
850 CAMEL_TYPE_NAMED_FLAGS,
851 G_PARAM_READWRITE |
852 G_PARAM_EXPLICIT_NOTIFY |
853 G_PARAM_STATIC_STRINGS));
854
855 /**
856 * CamelMessageInfo:user-tags
857 *
858 * User tags for the associated message. Can be %NULL.
859 * Unlike user-flags, which can be set or not, the user-tags
860 * can contain various values.
861 *
862 * Since: 3.24
863 **/
864 g_object_class_install_property (
865 object_class,
866 PROP_USER_TAGS,
867 g_param_spec_boxed (
868 "user-tags",
869 "User tags",
870 NULL,
871 CAMEL_TYPE_NAME_VALUE_ARRAY,
872 G_PARAM_READWRITE |
873 G_PARAM_EXPLICIT_NOTIFY |
874 G_PARAM_STATIC_STRINGS));
875
876 /**
877 * CamelMessageInfo:subject
878 *
879 * Subject of the associated message.
880 *
881 * Since: 3.24
882 **/
883 g_object_class_install_property (
884 object_class,
885 PROP_SUBJECT,
886 g_param_spec_string (
887 "subject",
888 "Subject",
889 NULL,
890 NULL,
891 G_PARAM_READWRITE |
892 G_PARAM_EXPLICIT_NOTIFY |
893 G_PARAM_STATIC_STRINGS));
894
895 /**
896 * CamelMessageInfo:from
897 *
898 * From address of the associated message.
899 *
900 * Since: 3.24
901 **/
902 g_object_class_install_property (
903 object_class,
904 PROP_FROM,
905 g_param_spec_string (
906 "from",
907 "From",
908 NULL,
909 NULL,
910 G_PARAM_READWRITE |
911 G_PARAM_EXPLICIT_NOTIFY |
912 G_PARAM_STATIC_STRINGS));
913
914 /**
915 * CamelMessageInfo:to
916 *
917 * To address of the associated message.
918 *
919 * Since: 3.24
920 **/
921 g_object_class_install_property (
922 object_class,
923 PROP_TO,
924 g_param_spec_string (
925 "to",
926 "To",
927 NULL,
928 NULL,
929 G_PARAM_READWRITE |
930 G_PARAM_EXPLICIT_NOTIFY |
931 G_PARAM_STATIC_STRINGS));
932
933 /**
934 * CamelMessageInfo:cc
935 *
936 * CC address of the associated message.
937 *
938 * Since: 3.24
939 **/
940 g_object_class_install_property (
941 object_class,
942 PROP_CC,
943 g_param_spec_string (
944 "cc",
945 "CC",
946 NULL,
947 NULL,
948 G_PARAM_READWRITE |
949 G_PARAM_EXPLICIT_NOTIFY |
950 G_PARAM_STATIC_STRINGS));
951
952 /**
953 * CamelMessageInfo:mlist
954 *
955 * Mailing list address of the associated message.
956 *
957 * Since: 3.24
958 **/
959 g_object_class_install_property (
960 object_class,
961 PROP_MLIST,
962 g_param_spec_string (
963 "mlist",
964 "mlist",
965 NULL,
966 NULL,
967 G_PARAM_READWRITE |
968 G_PARAM_EXPLICIT_NOTIFY |
969 G_PARAM_STATIC_STRINGS));
970
971 /**
972 * CamelMessageInfo:size
973 *
974 * Size of the associated message.
975 *
976 * Since: 3.24
977 **/
978 g_object_class_install_property (
979 object_class,
980 PROP_SIZE,
981 g_param_spec_uint (
982 "size",
983 "Size",
984 NULL,
985 0, G_MAXUINT32, 0,
986 G_PARAM_READWRITE |
987 G_PARAM_EXPLICIT_NOTIFY |
988 G_PARAM_STATIC_STRINGS));
989
990 /**
991 * CamelMessageInfo:date-sent
992 *
993 * Sent Date of the associated message.
994 *
995 * Since: 3.24
996 **/
997 g_object_class_install_property (
998 object_class,
999 PROP_DATE_SENT,
1000 g_param_spec_int64 (
1001 "date-sent",
1002 "Date Sent",
1003 NULL,
1004 G_MININT64, G_MAXINT64, 0,
1005 G_PARAM_READWRITE |
1006 G_PARAM_EXPLICIT_NOTIFY |
1007 G_PARAM_STATIC_STRINGS));
1008
1009 /**
1010 * CamelMessageInfo:date-received
1011 *
1012 * Received date of the associated message.
1013 *
1014 * Since: 3.24
1015 **/
1016 g_object_class_install_property (
1017 object_class,
1018 PROP_DATE_RECEIVED,
1019 g_param_spec_int64 (
1020 "date-received",
1021 "Date Received",
1022 NULL,
1023 G_MININT64, G_MAXINT64, 0,
1024 G_PARAM_READWRITE |
1025 G_PARAM_EXPLICIT_NOTIFY |
1026 G_PARAM_STATIC_STRINGS));
1027
1028 /**
1029 * CamelMessageInfo:message-id
1030 *
1031 * Encoded Message-ID of the associated message as a guint64 number,
1032 * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
1033 *
1034 * Since: 3.24
1035 **/
1036 g_object_class_install_property (
1037 object_class,
1038 PROP_MESSAGE_ID,
1039 g_param_spec_uint64 (
1040 "message-id",
1041 "Message ID",
1042 NULL,
1043 0, G_MAXUINT64, 0,
1044 G_PARAM_READWRITE |
1045 G_PARAM_EXPLICIT_NOTIFY |
1046 G_PARAM_STATIC_STRINGS));
1047
1048 /**
1049 * CamelMessageInfo:references
1050 *
1051 * Encoded In-Reply-To and References headers of the associated message
1052 * as an array of guint64 numbers, partial MD5 sums. Each value can be
1053 * cast to #CamelSummaryMessageID.
1054 *
1055 * Since: 3.24
1056 **/
1057 g_object_class_install_property (
1058 object_class,
1059 PROP_REFERENCES,
1060 g_param_spec_boxed (
1061 "references",
1062 "References",
1063 NULL,
1064 G_TYPE_ARRAY,
1065 G_PARAM_READWRITE |
1066 G_PARAM_EXPLICIT_NOTIFY |
1067 G_PARAM_STATIC_STRINGS));
1068
1069 /**
1070 * CamelMessageInfo:headers
1071 *
1072 * Headers of the associated message. Can be %NULL.
1073 *
1074 * Since: 3.24
1075 **/
1076 g_object_class_install_property (
1077 object_class,
1078 PROP_HEADERS,
1079 g_param_spec_boxed (
1080 "headers",
1081 "Headers",
1082 NULL,
1083 CAMEL_TYPE_NAME_VALUE_ARRAY,
1084 G_PARAM_READWRITE |
1085 G_PARAM_EXPLICIT_NOTIFY |
1086 G_PARAM_STATIC_STRINGS));
1087
1088 /**
1089 * CamelMessageInfo:user-headers
1090 *
1091 * User-defined headers of the associated message. Can be %NULL.
1092 *
1093 * Since: 3.42
1094 **/
1095 g_object_class_install_property (
1096 object_class,
1097 PROP_USER_HEADERS,
1098 g_param_spec_boxed (
1099 "user-headers",
1100 "User Headers",
1101 NULL,
1102 CAMEL_TYPE_NAME_VALUE_ARRAY,
1103 G_PARAM_READWRITE |
1104 G_PARAM_EXPLICIT_NOTIFY |
1105 G_PARAM_STATIC_STRINGS));
1106
1107 /**
1108 * CamelMessageInfo:preview
1109 *
1110 * Body preview of the associated message. Can be %NULL.
1111 *
1112 * Since: 3.42
1113 **/
1114 g_object_class_install_property (
1115 object_class,
1116 PROP_PREVIEW,
1117 g_param_spec_string (
1118 "preview",
1119 "Preview",
1120 NULL,
1121 NULL,
1122 G_PARAM_READWRITE |
1123 G_PARAM_EXPLICIT_NOTIFY |
1124 G_PARAM_STATIC_STRINGS));
1125 }
1126
1127 static void
camel_message_info_init(CamelMessageInfo * mi)1128 camel_message_info_init (CamelMessageInfo *mi)
1129 {
1130 mi->priv = camel_message_info_get_instance_private (mi);
1131 mi->priv->summary_wrg = camel_weak_ref_group_new ();
1132
1133 g_rec_mutex_init (&mi->priv->property_lock);
1134 }
1135
1136 /* Private function */
1137 void _camel_message_info_unset_summary (CamelMessageInfo *mi);
1138
1139 void
_camel_message_info_unset_summary(CamelMessageInfo * mi)1140 _camel_message_info_unset_summary (CamelMessageInfo *mi)
1141 {
1142 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1143
1144 camel_weak_ref_group_set (mi->priv->summary_wrg, NULL);
1145 }
1146
1147 /**
1148 * camel_message_info_new:
1149 * @summary: (nullable) (type CamelFolderSummary): parent #CamelFolderSummary object, or %NULL
1150 *
1151 * Create a new #CamelMessageInfo object, optionally for given @summary.
1152 *
1153 * Returns: (transfer full): a new #CamelMessageInfo object
1154 *
1155 * Since: 3.24
1156 **/
1157 CamelMessageInfo *
camel_message_info_new(CamelFolderSummary * summary)1158 camel_message_info_new (CamelFolderSummary *summary)
1159 {
1160 GType type = CAMEL_TYPE_MESSAGE_INFO_BASE;
1161
1162 if (summary) {
1163 CamelFolderSummaryClass *klass;
1164
1165 g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL);
1166
1167 klass = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary);
1168 g_return_val_if_fail (klass != NULL, NULL);
1169
1170 type = klass->message_info_type;
1171 }
1172
1173 return g_object_new (type, "summary", summary, NULL);
1174 }
1175
1176 /**
1177 * camel_message_info_clone:
1178 * @mi: a #CamelMessageInfo to clone
1179 * @assign_summary: (nullable) (type CamelFolderSummary): parent #CamelFolderSummary object, or %NULL, to set on the clone
1180 *
1181 * Clones the @mi as a new #CamelMessageInfo and eventually assigns
1182 * a new #CamelFolderSummary to it. If it's not set, then the same
1183 * summary as the one with @mi is used.
1184 *
1185 * Returns: (transfer full): a new #CamelMessageInfo object, clone of the @mi
1186 *
1187 * Since: 3.24
1188 **/
1189 CamelMessageInfo *
camel_message_info_clone(const CamelMessageInfo * mi,CamelFolderSummary * assign_summary)1190 camel_message_info_clone (const CamelMessageInfo *mi,
1191 CamelFolderSummary *assign_summary)
1192 {
1193 CamelMessageInfoClass *klass;
1194
1195 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1196 if (assign_summary)
1197 g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (assign_summary), NULL);
1198
1199 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1200 g_return_val_if_fail (klass != NULL, NULL);
1201 g_return_val_if_fail (klass->clone != NULL, NULL);
1202
1203 return klass->clone (mi, assign_summary);
1204 }
1205
1206 /**
1207 * camel_message_info_load:
1208 * @mi: a #CamelMessageInfo to load
1209 * @record: (type CamelMIRecord): a #CamelMIRecord to load the @mi from
1210 * @bdata_ptr: a backend specific data (bdata) pointer
1211 *
1212 * Load content of @mi from the data stored in @record. The @bdata_ptr points
1213 * to the current position of the record->bdata, where the read can continue.
1214 * Use helper functions camel_util_bdata_get_number() and camel_util_bdata_get_string()
1215 * to read data from it and also move forward the *bdata_ptr.
1216 *
1217 * After successful load of the @mi, the 'dirty' flag is unset.
1218 *
1219 * Returns: Whether the load was successful.
1220 *
1221 * Since: 3.24
1222 **/
1223 gboolean
camel_message_info_load(CamelMessageInfo * mi,const CamelMIRecord * record,gchar ** bdata_ptr)1224 camel_message_info_load (CamelMessageInfo *mi,
1225 const CamelMIRecord *record,
1226 /* const */ gchar **bdata_ptr)
1227 {
1228 CamelMessageInfoClass *klass;
1229 gboolean success;
1230
1231 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1232 g_return_val_if_fail (record != NULL, FALSE);
1233 g_return_val_if_fail (bdata_ptr != NULL, FALSE);
1234
1235 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1236 g_return_val_if_fail (klass != NULL, FALSE);
1237 g_return_val_if_fail (klass->load != NULL, FALSE);
1238
1239 g_object_freeze_notify (G_OBJECT (mi));
1240 camel_message_info_property_lock (mi);
1241 camel_message_info_set_abort_notifications (mi, TRUE);
1242
1243 success = klass->load (mi, record, bdata_ptr);
1244
1245 if (success)
1246 camel_message_info_set_dirty (mi, FALSE);
1247
1248 camel_message_info_set_abort_notifications (mi, FALSE);
1249 camel_message_info_property_unlock (mi);
1250 g_object_thaw_notify (G_OBJECT (mi));
1251
1252 return success;
1253 }
1254
1255 /**
1256 * camel_message_info_save:
1257 * @mi: a #CamelMessageInfo
1258 * @record: (type CamelMIRecord): a #CamelMIRecord to populate
1259 * @bdata_str: a #GString with a string to save as backend specific data (bdata)
1260 *
1261 * Save the @mi content to the message info record @record. It can populate all
1262 * but the record->bdata value, which is set fro mthe @bdata_str. Use helper functions
1263 * camel_util_bdata_put_number() and camel_util_bdata_put_string() to put data into the @bdata_str.
1264 *
1265 * Returns: Whether the save succeeded.
1266 *
1267 * Since: 3.24
1268 **/
1269 gboolean
camel_message_info_save(const CamelMessageInfo * mi,CamelMIRecord * record,GString * bdata_str)1270 camel_message_info_save (const CamelMessageInfo *mi,
1271 CamelMIRecord *record,
1272 GString *bdata_str)
1273 {
1274 CamelMessageInfoClass *klass;
1275 gboolean success;
1276
1277 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1278 g_return_val_if_fail (record != NULL, FALSE);
1279 g_return_val_if_fail (bdata_str != NULL, FALSE);
1280
1281 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1282 g_return_val_if_fail (klass != NULL, FALSE);
1283 g_return_val_if_fail (klass->save != NULL, FALSE);
1284
1285 camel_message_info_property_lock (mi);
1286
1287 success = klass->save (mi, record, bdata_str);
1288
1289 camel_message_info_property_unlock (mi);
1290
1291 return success;
1292 }
1293
1294 /**
1295 * camel_message_info_ref_summary:
1296 * @mi: a #CamelMessageInfo
1297 *
1298 * Returns: (transfer full): Referenced #CamelFolderSummary to which the @mi belongs, or %NULL,
1299 * if there is none. Use g_object_unref() for non-NULL returned values when done with it.
1300 *
1301 * Since: 3.24
1302 **/
1303 CamelFolderSummary *
camel_message_info_ref_summary(const CamelMessageInfo * mi)1304 camel_message_info_ref_summary (const CamelMessageInfo *mi)
1305 {
1306 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1307
1308 return camel_weak_ref_group_get (mi->priv->summary_wrg);
1309 }
1310
1311 /**
1312 * camel_message_info_property_lock:
1313 * @mi: a #CamelMessageInfo
1314 *
1315 * Acquires a property lock, which is used to ensure thread safety
1316 * when properties are changing. Release the lock with
1317 * camel_message_info_property_unlock().
1318 *
1319 * Note: Make sure the CamelFolderSummary lock is held before this lock,
1320 * if there will be called any 'set' function on the @mi, to avoid deadlock
1321 * when the summary would be set as dirty while another thread might try
1322 * to read values from the @mi, waiting for the property lock and holding
1323 * the summary lock at the same time.
1324 *
1325 * Since: 3.24
1326 **/
1327 void
camel_message_info_property_lock(const CamelMessageInfo * mi)1328 camel_message_info_property_lock (const CamelMessageInfo *mi)
1329 {
1330 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1331
1332 g_rec_mutex_lock (&mi->priv->property_lock);
1333 }
1334
1335 /**
1336 * camel_message_info_property_unlock:
1337 * @mi: a #CamelMessageInfo
1338 *
1339 * Releases a property lock, previously acquired with
1340 * camel_message_info_property_lock().
1341 *
1342 * Since: 3.24
1343 **/
1344 void
camel_message_info_property_unlock(const CamelMessageInfo * mi)1345 camel_message_info_property_unlock (const CamelMessageInfo *mi)
1346 {
1347 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1348
1349 g_rec_mutex_unlock (&mi->priv->property_lock);
1350 }
1351
1352 static void
camel_message_info_update_summary_and_folder(CamelMessageInfo * mi,gboolean update_counts)1353 camel_message_info_update_summary_and_folder (CamelMessageInfo *mi,
1354 gboolean update_counts)
1355 {
1356 CamelFolderSummary *summary;
1357
1358 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1359
1360 camel_message_info_property_lock (mi);
1361 if (camel_message_info_get_notifications_frozen (mi)) {
1362 mi->priv->thaw_notify_folder = TRUE;
1363 mi->priv->thaw_notify_folder_with_counts |= update_counts;
1364 camel_message_info_property_unlock (mi);
1365
1366 return;
1367 }
1368 camel_message_info_property_unlock (mi);
1369
1370 summary = camel_message_info_ref_summary (mi);
1371 if (summary) {
1372 CamelFolder *folder;
1373 CamelMessageInfo *in_summary_mi = NULL;
1374 const gchar *uid;
1375
1376 uid = camel_message_info_pooldup_uid (mi);
1377
1378 /* This is for cases when a new message info had been created,
1379 but not added into the summary yet. */
1380 if (uid && camel_folder_summary_check_uid (summary, uid) &&
1381 (in_summary_mi = camel_folder_summary_peek_loaded (summary, uid)) == mi) {
1382 if (update_counts) {
1383 camel_folder_summary_lock (summary);
1384 g_object_freeze_notify (G_OBJECT (summary));
1385
1386 camel_folder_summary_replace_flags (summary, mi);
1387
1388 g_object_thaw_notify (G_OBJECT (summary));
1389 camel_folder_summary_unlock (summary);
1390 }
1391
1392 folder = camel_folder_summary_get_folder (summary);
1393 if (folder) {
1394 CamelFolderChangeInfo *changes = camel_folder_change_info_new ();
1395
1396 camel_folder_change_info_change_uid (changes, uid);
1397 camel_folder_changed (folder, changes);
1398 camel_folder_change_info_free (changes);
1399 }
1400 }
1401
1402 g_clear_object (&in_summary_mi);
1403 g_clear_object (&summary);
1404 camel_pstring_free (uid);
1405 }
1406 }
1407
1408 /**
1409 * camel_message_info_get_dirty:
1410 * @mi: a #CamelMessageInfo
1411 *
1412 * Returns: Whether the @mi is dirty, which means that it had been
1413 * changed and a save to the local summary is required.
1414 *
1415 * Since: 3.24
1416 **/
1417 gboolean
camel_message_info_get_dirty(const CamelMessageInfo * mi)1418 camel_message_info_get_dirty (const CamelMessageInfo *mi)
1419 {
1420 gboolean result;
1421
1422 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1423
1424 camel_message_info_property_lock (mi);
1425 result = mi->priv->dirty;
1426 camel_message_info_property_unlock (mi);
1427
1428 return result;
1429 }
1430
1431 /**
1432 * camel_message_info_set_dirty:
1433 * @mi: a #CamelMessageInfo
1434 * @dirty: a dirty state to set
1435 *
1436 * Marks the @mi as dirty, which means a save to the local summary
1437 * is required.
1438 *
1439 * Since: 3.24
1440 **/
1441 void
camel_message_info_set_dirty(CamelMessageInfo * mi,gboolean dirty)1442 camel_message_info_set_dirty (CamelMessageInfo *mi,
1443 gboolean dirty)
1444 {
1445 gboolean changed, abort_notifications;
1446
1447 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1448
1449 camel_message_info_property_lock (mi);
1450
1451 changed = (!mi->priv->dirty) != (!dirty);
1452 if (changed)
1453 mi->priv->dirty = dirty;
1454 abort_notifications = mi->priv->abort_notifications;
1455
1456 camel_message_info_property_unlock (mi);
1457
1458 if (changed && !abort_notifications) {
1459 g_object_notify (G_OBJECT (mi), "dirty");
1460
1461 if (dirty) {
1462 CamelFolderSummary *summary;
1463
1464 summary = camel_message_info_ref_summary (mi);
1465 if (summary)
1466 camel_folder_summary_touch (summary);
1467
1468 g_clear_object (&summary);
1469 }
1470 }
1471 }
1472
1473 /**
1474 * camel_message_info_get_folder_flagged:
1475 * @mi: a #CamelMessageInfo
1476 *
1477 * The folder flagged flag is used to mark the message infor as being changed
1478 * and this change should be propagated to the remote store (server). This is
1479 * different from the 'dirty' flag, which is set for local changes only. It
1480 * can happen that the 'folder-flagged' flag is set, but the 'dirty' flag not.
1481 *
1482 * This is only a convenient wrapper around CAMEL_MESSAGE_FOLDER_FLAGGED flag,
1483 * for better readiness of the code.
1484 *
1485 * Returns: Whether requires save of the local changes into the remote store.
1486 *
1487 * Since: 3.24
1488 **/
1489 gboolean
camel_message_info_get_folder_flagged(const CamelMessageInfo * mi)1490 camel_message_info_get_folder_flagged (const CamelMessageInfo *mi)
1491 {
1492 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1493
1494 return (camel_message_info_get_flags (mi) & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
1495 }
1496
1497 /**
1498 * camel_message_info_set_folder_flagged:
1499 * @mi: a #CamelMessageInfo
1500 * @folder_flagged: a value to set to
1501 *
1502 * Changes the folder-flagged flag to the @folder_flagged value. See
1503 * camel_message_info_get_folder_flagged() for more information about
1504 * the use of this flag.
1505 *
1506 * This is only a convenient wrapper around CAMEL_MESSAGE_FOLDER_FLAGGED flag,
1507 * for better readiness of the code.
1508 *
1509 * Returns: Whether the flag had been changed.
1510 *
1511 * Since: 3.24
1512 **/
1513 gboolean
camel_message_info_set_folder_flagged(CamelMessageInfo * mi,gboolean folder_flagged)1514 camel_message_info_set_folder_flagged (CamelMessageInfo *mi,
1515 gboolean folder_flagged)
1516 {
1517 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1518
1519 /* g_object_notify (G_OBJECT (mi), "folder-flagged");
1520 is called as part of the set_flags function */
1521
1522 return camel_message_info_set_flags (mi, CAMEL_MESSAGE_FOLDER_FLAGGED,
1523 folder_flagged ? CAMEL_MESSAGE_FOLDER_FLAGGED : 0);
1524 }
1525
1526 /**
1527 * camel_message_info_get_folder_flagged_stamp:
1528 * @mi: a #CamelMessageInfo
1529 *
1530 * The 'folder-flagged-stamp' is a stamp of the 'folder-flagged' flag. This stamp
1531 * changes whenever anything would mark the @mi as 'folder-flagged', regardless
1532 * the @mi being already 'folder-flagged'. It can be used to recognize changes
1533 * on the 'folder-flagged' flag during the time.
1534 *
1535 * Returns: Stamp of the 'folder-flagged' flag.
1536 *
1537 * Since: 3.24
1538 **/
1539 guint
camel_message_info_get_folder_flagged_stamp(const CamelMessageInfo * mi)1540 camel_message_info_get_folder_flagged_stamp (const CamelMessageInfo *mi)
1541 {
1542 guint result;
1543
1544 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), ~0);
1545
1546 camel_message_info_property_lock (mi);
1547 result = mi->priv->folder_flagged_stamp;
1548 camel_message_info_property_unlock (mi);
1549
1550 return result;
1551 }
1552
1553 /**
1554 * camel_message_info_get_abort_notifications:
1555 * @mi: a #CamelMessageInfo
1556 *
1557 * Returns: Whether the @mi is aborting notifications, which means
1558 * that it will not influence 'dirty' and 'folder-flagged' flags
1559 * in the set/take functions, neither it will emit any GObject::notify
1560 * signals on change, nor associated folder's "changed" signal.
1561 *
1562 * Since: 3.24
1563 **/
1564 gboolean
camel_message_info_get_abort_notifications(const CamelMessageInfo * mi)1565 camel_message_info_get_abort_notifications (const CamelMessageInfo *mi)
1566 {
1567 gboolean result;
1568
1569 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1570
1571 camel_message_info_property_lock (mi);
1572 result = mi->priv->abort_notifications;
1573 camel_message_info_property_unlock (mi);
1574
1575 return result;
1576 }
1577
1578 /**
1579 * camel_message_info_set_abort_notifications:
1580 * @mi: a #CamelMessageInfo
1581 * @abort_notifications: a state to set
1582 *
1583 * Marks the @mi to abort any notifications, which means that it
1584 * will not influence 'dirty' and 'folder-flagged' flags in
1585 * the set/take functions, neither it will emit any GObject::notify
1586 * signals on change, nor associated folder's "changed" signal.
1587 *
1588 * Since: 3.24
1589 **/
1590 void
camel_message_info_set_abort_notifications(CamelMessageInfo * mi,gboolean abort_notifications)1591 camel_message_info_set_abort_notifications (CamelMessageInfo *mi,
1592 gboolean abort_notifications)
1593 {
1594 gboolean changed;
1595 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1596
1597 camel_message_info_property_lock (mi);
1598 changed = (!mi->priv->abort_notifications) != (!abort_notifications);
1599 if (changed)
1600 mi->priv->abort_notifications = abort_notifications;
1601 camel_message_info_property_unlock (mi);
1602
1603 if (changed)
1604 g_object_notify (G_OBJECT (mi), "abort-notifications");
1605 }
1606
1607 /**
1608 * camel_message_info_freeze_notifications:
1609 * @mi: a #CamelMessageInfo
1610 *
1611 * Freezes all the notifications until the camel_message_info_thaw_notifications() is called.
1612 * This function can be called multiple times, where the last thaw will do the notifications.
1613 *
1614 * Since: 3.24
1615 **/
1616 void
camel_message_info_freeze_notifications(CamelMessageInfo * mi)1617 camel_message_info_freeze_notifications (CamelMessageInfo *mi)
1618 {
1619 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1620
1621 camel_message_info_property_lock (mi);
1622 mi->priv->freeze_notifications++;
1623 if (mi->priv->freeze_notifications == 1) {
1624 mi->priv->thaw_notify_folder = FALSE;
1625 mi->priv->thaw_notify_folder_with_counts = FALSE;
1626 g_object_freeze_notify (G_OBJECT (mi));
1627 }
1628 camel_message_info_property_unlock (mi);
1629 }
1630
1631 /**
1632 * camel_message_info_thaw_notifications:
1633 * @mi: a #CamelMessageInfo
1634 *
1635 * Reverses the call of the camel_message_info_freeze_notifications().
1636 * If this is the last freeze, then the associated folder is also notified
1637 * about the change, if any happened during the freeze.
1638 *
1639 * Since: 3.24
1640 **/
1641 void
camel_message_info_thaw_notifications(CamelMessageInfo * mi)1642 camel_message_info_thaw_notifications (CamelMessageInfo *mi)
1643 {
1644 g_return_if_fail (CAMEL_IS_MESSAGE_INFO (mi));
1645
1646 camel_message_info_property_lock (mi);
1647 if (!mi->priv->freeze_notifications) {
1648 camel_message_info_property_unlock (mi);
1649
1650 g_warn_if_reached ();
1651 return;
1652 }
1653
1654 mi->priv->freeze_notifications--;
1655 if (!mi->priv->freeze_notifications) {
1656 gboolean notify_folder, notify_folder_with_counts;
1657
1658 notify_folder = mi->priv->thaw_notify_folder;
1659 notify_folder_with_counts = mi->priv->thaw_notify_folder_with_counts;
1660
1661 camel_message_info_property_unlock (mi);
1662
1663 g_object_thaw_notify (G_OBJECT (mi));
1664
1665 if (notify_folder)
1666 camel_message_info_update_summary_and_folder (mi, notify_folder_with_counts);
1667 } else {
1668 camel_message_info_property_unlock (mi);
1669 }
1670 }
1671
1672 /**
1673 * camel_message_info_get_notifications_frozen:
1674 * @mi: a #CamelMessageInfo
1675 *
1676 * Returns: Whether the notifications are frozen.
1677 *
1678 * See: camel_message_info_freeze_notifications()
1679 *
1680 * Since: 3.24
1681 **/
1682 gboolean
camel_message_info_get_notifications_frozen(const CamelMessageInfo * mi)1683 camel_message_info_get_notifications_frozen (const CamelMessageInfo *mi)
1684 {
1685 gboolean result;
1686
1687 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1688
1689 camel_message_info_property_lock (mi);
1690 result = mi->priv->freeze_notifications > 0;
1691 camel_message_info_property_unlock (mi);
1692
1693 return result;
1694 }
1695
1696 /**
1697 * camel_message_info_get_uid:
1698 * @mi: a #CamelMessageInfo
1699 *
1700 * Get the UID of the #mi.
1701 *
1702 * Returns: (transfer none): The UID of the @mi.
1703 *
1704 * Since: 3.24
1705 **/
1706 const gchar *
camel_message_info_get_uid(const CamelMessageInfo * mi)1707 camel_message_info_get_uid (const CamelMessageInfo *mi)
1708 {
1709 const gchar *result;
1710
1711 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1712
1713 camel_message_info_property_lock (mi);
1714 result = mi->priv->uid;
1715 camel_message_info_property_unlock (mi);
1716
1717 return result;
1718 }
1719
1720 /**
1721 * camel_message_info_pooldup_uid:
1722 * @mi: a #CamelMessageInfo
1723 *
1724 * Get the UID of the #mi, duplicated on the Camel's string pool.
1725 * This is good for thread safety, though the UID should not change once set.
1726 *
1727 * Returns: A newly references string in the string pool, the #mi UID.
1728 * Free it with camel_pstring_free() when no longer needed.
1729 *
1730 * Since: 3.24
1731 **/
1732 const gchar *
camel_message_info_pooldup_uid(const CamelMessageInfo * mi)1733 camel_message_info_pooldup_uid (const CamelMessageInfo *mi)
1734 {
1735 const gchar *result;
1736
1737 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1738
1739 camel_message_info_property_lock (mi);
1740 result = camel_pstring_strdup (mi->priv->uid);
1741 camel_message_info_property_unlock (mi);
1742
1743 return result;
1744 }
1745
1746 /**
1747 * camel_message_info_set_uid:
1748 * @mi: a #CamelMessageInfo
1749 * @uid: a UID to set
1750 *
1751 * Changes UID of the @mi to @uid. If it changes, the 'dirty' flag
1752 * of the @mi is set too, unless the @mi is aborting notifications. This change
1753 * does not influence the 'folder-flagged' flag.
1754 *
1755 * Returns: Whether the UID changed.
1756 *
1757 * Since: 3.24
1758 **/
1759 gboolean
camel_message_info_set_uid(CamelMessageInfo * mi,const gchar * uid)1760 camel_message_info_set_uid (CamelMessageInfo *mi,
1761 const gchar *uid)
1762 {
1763 gboolean changed, abort_notifications;
1764
1765 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1766
1767 camel_message_info_property_lock (mi);
1768 changed = mi->priv->uid != uid && g_strcmp0 (mi->priv->uid, uid) != 0;
1769 if (changed) {
1770 camel_pstring_free (mi->priv->uid);
1771 mi->priv->uid = camel_pstring_strdup (uid);
1772 }
1773 abort_notifications = mi->priv->abort_notifications;
1774 camel_message_info_property_unlock (mi);
1775
1776 if (changed && !abort_notifications) {
1777 g_object_notify (G_OBJECT (mi), "uid");
1778 camel_message_info_set_dirty (mi, TRUE);
1779 }
1780
1781 return changed;
1782 }
1783
1784 /**
1785 * camel_message_info_get_flags:
1786 * @mi: a #CamelMessageInfo
1787 *
1788 * Returns: Bit-or of #CamelMessageFlags set on the @mi.
1789 *
1790 * Since: 3.24
1791 **/
1792 guint32
camel_message_info_get_flags(const CamelMessageInfo * mi)1793 camel_message_info_get_flags (const CamelMessageInfo *mi)
1794 {
1795 CamelMessageInfoClass *klass;
1796 guint32 result;
1797
1798 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
1799
1800 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1801 g_return_val_if_fail (klass != NULL, 0);
1802 g_return_val_if_fail (klass->get_flags != NULL, 0);
1803
1804 camel_message_info_property_lock (mi);
1805 result = klass->get_flags (mi);
1806 camel_message_info_property_unlock (mi);
1807
1808 return result;
1809 }
1810
1811 /**
1812 * camel_message_info_set_flags:
1813 * @mi: a #CamelMessageInfo
1814 * @mask: mask of flags to change
1815 * @set: state the flags should be changed to
1816 *
1817 * Change the state of the flags on the @mi. Both @mask and @set are bit-or
1818 * of #CamelMessageFlags.
1819 *
1820 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
1821 * set automatically, unless the @mi is aborting notifications. There is also emitted
1822 * folder's "changed" signal for this @mi, if necessary. In case
1823 * the CAMEL_MESSAGE_FOLDER_FLAGGED flag would be set and the @mi is
1824 * not aborting notifications, the 'folder-flagged-stamp' changes too.
1825 *
1826 * Returns: Whether the flags changed.
1827 *
1828 * Since: 3.24
1829 **/
1830 gboolean
camel_message_info_set_flags(CamelMessageInfo * mi,guint32 mask,guint32 set)1831 camel_message_info_set_flags (CamelMessageInfo *mi,
1832 guint32 mask,
1833 guint32 set)
1834 {
1835 CamelMessageInfoClass *klass;
1836 gboolean changed, abort_notifications;
1837
1838 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1839
1840 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1841 g_return_val_if_fail (klass != NULL, FALSE);
1842 g_return_val_if_fail (klass->set_flags != NULL, FALSE);
1843
1844 camel_message_info_property_lock (mi);
1845
1846 changed = klass->set_flags (mi, mask, set);
1847 abort_notifications = mi->priv->abort_notifications;
1848
1849 if (!abort_notifications &&
1850 (mask & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 &&
1851 (set & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0)
1852 mi->priv->folder_flagged_stamp++;
1853
1854 camel_message_info_property_unlock (mi);
1855
1856 if (changed && !abort_notifications) {
1857 g_object_notify (G_OBJECT (mi), "flags");
1858 camel_message_info_set_dirty (mi, TRUE);
1859
1860 /* Only if the folder-flagged was not part of the change */
1861 if (!(mask & CAMEL_MESSAGE_FOLDER_FLAGGED))
1862 camel_message_info_set_folder_flagged (mi, TRUE);
1863 else
1864 g_object_notify (G_OBJECT (mi), "folder-flagged");
1865
1866 camel_message_info_update_summary_and_folder (mi, TRUE);
1867 }
1868
1869 return changed;
1870 }
1871
1872 /**
1873 * camel_message_info_get_user_flag:
1874 * @mi: a #CamelMessageInfo
1875 * @name: user flag name
1876 *
1877 * Returns: Whther the user flag named @name is set.
1878 *
1879 * Since: 3.24
1880 **/
1881 gboolean
camel_message_info_get_user_flag(const CamelMessageInfo * mi,const gchar * name)1882 camel_message_info_get_user_flag (const CamelMessageInfo *mi,
1883 const gchar *name)
1884 {
1885 CamelMessageInfoClass *klass;
1886 gboolean result;
1887
1888 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1889
1890 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1891 g_return_val_if_fail (klass != NULL, FALSE);
1892 g_return_val_if_fail (klass->get_user_flag != NULL, FALSE);
1893
1894 camel_message_info_property_lock (mi);
1895 result = klass->get_user_flag (mi, name);
1896 camel_message_info_property_unlock (mi);
1897
1898 return result;
1899 }
1900
1901 /**
1902 * camel_message_info_set_user_flag:
1903 * @mi: a #CamelMessageInfo
1904 * @name: user flag name
1905 * @state: state to set for the flag
1906 *
1907 * Change @state of the flag named @name. Unlike user tags, user flags
1908 * can only be set or unset, while the user tags can contain certain values.
1909 *
1910 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
1911 * set automatically, unless the @mi is aborting notifications. There is also emitted
1912 * folder's "changed" signal for this @mi, if necessary.
1913 *
1914 * Returns: Whether the message info changed.
1915 *
1916 * Since: 3.24
1917 **/
1918 gboolean
camel_message_info_set_user_flag(CamelMessageInfo * mi,const gchar * name,gboolean state)1919 camel_message_info_set_user_flag (CamelMessageInfo *mi,
1920 const gchar *name,
1921 gboolean state)
1922 {
1923 CamelMessageInfoClass *klass;
1924 gboolean changed, abort_notifications;
1925
1926 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
1927 g_return_val_if_fail (name != NULL, FALSE);
1928
1929 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1930 g_return_val_if_fail (klass != NULL, FALSE);
1931 g_return_val_if_fail (klass->set_user_flag != NULL, FALSE);
1932
1933 camel_message_info_property_lock (mi);
1934 changed = klass->set_user_flag (mi, name, state);
1935 abort_notifications = mi->priv->abort_notifications;
1936 camel_message_info_property_unlock (mi);
1937
1938 if (changed && !abort_notifications) {
1939 g_object_notify (G_OBJECT (mi), "user-flags");
1940 camel_message_info_set_dirty (mi, TRUE);
1941 camel_message_info_set_folder_flagged (mi, TRUE);
1942
1943 camel_message_info_update_summary_and_folder (mi, FALSE);
1944 }
1945
1946 return changed;
1947 }
1948
1949 /**
1950 * camel_message_info_get_user_flags:
1951 * @mi: a #CamelMessageInfo
1952 *
1953 * Returns: (transfer none) (nullable): A #CamelNamedFlags with all the currently set
1954 * user flags on the @mi. Do not modify it.
1955 *
1956 * Since: 3.24
1957 **/
1958 const CamelNamedFlags *
camel_message_info_get_user_flags(const CamelMessageInfo * mi)1959 camel_message_info_get_user_flags (const CamelMessageInfo *mi)
1960 {
1961 CamelMessageInfoClass *klass;
1962 const CamelNamedFlags *result;
1963
1964 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1965
1966 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1967 g_return_val_if_fail (klass != NULL, NULL);
1968 g_return_val_if_fail (klass->get_user_flags != NULL, NULL);
1969
1970 camel_message_info_property_lock (mi);
1971 result = klass->get_user_flags (mi);
1972 camel_message_info_property_unlock (mi);
1973
1974 return result;
1975 }
1976
1977 /**
1978 * camel_message_info_dup_user_flags:
1979 * @mi: a #CamelMessageInfo
1980 *
1981 * Returns: (transfer full): A newly allocated #CamelNamedFlags with all the currently set
1982 * user flags on the @mi. Free the returned structure with camel_named_flags_free()
1983 * when no londer needed.
1984 *
1985 * Since: 3.24
1986 **/
1987 CamelNamedFlags *
camel_message_info_dup_user_flags(const CamelMessageInfo * mi)1988 camel_message_info_dup_user_flags (const CamelMessageInfo *mi)
1989 {
1990 CamelMessageInfoClass *klass;
1991 CamelNamedFlags *result;
1992
1993 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
1994
1995 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
1996 g_return_val_if_fail (klass != NULL, NULL);
1997 g_return_val_if_fail (klass->dup_user_flags != NULL, NULL);
1998
1999 camel_message_info_property_lock (mi);
2000 result = klass->dup_user_flags (mi);
2001 camel_message_info_property_unlock (mi);
2002
2003 return result;
2004 }
2005
2006 /**
2007 * camel_message_info_take_user_flags:
2008 * @mi: a #CamelMessageInfo
2009 * @user_flags: (transfer full) (nullable): user flags to set
2010 *
2011 * Takes all the @user_flags, which replaces any current user flags on the @mi.
2012 * The passed-in @user_flags is consumed by the @mi, which becomes an owner
2013 * of it. The caller should not change @user_flags afterwards.
2014 *
2015 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2016 * set automatically, unless the @mi is aborting notifications. There is also emitted
2017 * folder's "changed" signal for this @mi, if necessary.
2018 *
2019 * Note that it's not safe to use the @user_flags after the call to this function,
2020 * because it can be freed due to no change.
2021 *
2022 * Returns: Whether the message info changed.
2023 *
2024 * Since: 3.24
2025 **/
2026 gboolean
camel_message_info_take_user_flags(CamelMessageInfo * mi,CamelNamedFlags * user_flags)2027 camel_message_info_take_user_flags (CamelMessageInfo *mi,
2028 CamelNamedFlags *user_flags)
2029 {
2030 CamelMessageInfoClass *klass;
2031 gboolean changed, abort_notifications;
2032
2033 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2034
2035 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2036 g_return_val_if_fail (klass != NULL, FALSE);
2037 g_return_val_if_fail (klass->take_user_flags != NULL, FALSE);
2038
2039 camel_message_info_property_lock (mi);
2040 changed = klass->take_user_flags (mi, user_flags);
2041 abort_notifications = mi->priv->abort_notifications;
2042 camel_message_info_property_unlock (mi);
2043
2044 if (changed && !abort_notifications) {
2045 g_object_notify (G_OBJECT (mi), "user-flags");
2046 camel_message_info_set_dirty (mi, TRUE);
2047 camel_message_info_set_folder_flagged (mi, TRUE);
2048
2049 camel_message_info_update_summary_and_folder (mi, FALSE);
2050 }
2051
2052 return changed;
2053 }
2054
2055 /**
2056 * camel_message_info_get_user_tag:
2057 * @mi: a #CamelMessageInfo
2058 * @name: user tag name
2059 *
2060 * Returns: (transfer none) (nullable): Value of the user tag, or %NULL when
2061 * it is not set.
2062 *
2063 * Since: 3.24
2064 **/
2065 const gchar *
camel_message_info_get_user_tag(const CamelMessageInfo * mi,const gchar * name)2066 camel_message_info_get_user_tag (const CamelMessageInfo *mi,
2067 const gchar *name)
2068 {
2069 CamelMessageInfoClass *klass;
2070 const gchar *result;
2071
2072 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2073 g_return_val_if_fail (name != NULL, NULL);
2074
2075 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2076 g_return_val_if_fail (klass != NULL, NULL);
2077 g_return_val_if_fail (klass->get_user_tag != NULL, NULL);
2078
2079 camel_message_info_property_lock (mi);
2080 result = klass->get_user_tag (mi, name);
2081 camel_message_info_property_unlock (mi);
2082
2083 return result;
2084 }
2085
2086 /**
2087 * camel_message_info_dup_user_tag:
2088 * @mi: a #CamelMessageInfo
2089 * @name: user tag name
2090 *
2091 * Returns: (transfer full) (nullable): Value of the user tag as newly allocated
2092 * string, or %NULL when it is not set. Free it with g_free() when no longer needed.
2093 *
2094 * Since: 3.24
2095 **/
2096 gchar *
camel_message_info_dup_user_tag(const CamelMessageInfo * mi,const gchar * name)2097 camel_message_info_dup_user_tag (const CamelMessageInfo *mi,
2098 const gchar *name)
2099 {
2100 gchar *result;
2101
2102 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2103 g_return_val_if_fail (name != NULL, NULL);
2104
2105 camel_message_info_property_lock (mi);
2106 result = g_strdup (camel_message_info_get_user_tag (mi, name));
2107 camel_message_info_property_unlock (mi);
2108
2109 return result;
2110 }
2111
2112 /**
2113 * camel_message_info_set_user_tag:
2114 * @mi: a #CamelMessageInfo
2115 * @name: user tag name
2116 * @value: (nullable): user tag value, or %NULL to remove the user tag
2117 *
2118 * Set user tag @name to @value, or remove it, if @value is %NULL.
2119 *
2120 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2121 * set automatically, unless the @mi is aborting notifications. There is also emitted
2122 * folder's "changed" signal for this @mi, if necessary.
2123 *
2124 * Returns: Whether the @mi changed.
2125 *
2126 * Since: 3.24
2127 **/
2128 gboolean
camel_message_info_set_user_tag(CamelMessageInfo * mi,const gchar * name,const gchar * value)2129 camel_message_info_set_user_tag (CamelMessageInfo *mi,
2130 const gchar *name,
2131 const gchar *value)
2132 {
2133 CamelMessageInfoClass *klass;
2134 gboolean changed, abort_notifications;
2135
2136 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2137 g_return_val_if_fail (name != NULL, FALSE);
2138
2139 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2140 g_return_val_if_fail (klass != NULL, FALSE);
2141 g_return_val_if_fail (klass->set_user_tag != NULL, FALSE);
2142
2143 camel_message_info_property_lock (mi);
2144 changed = klass->set_user_tag (mi, name, value);
2145 abort_notifications = mi->priv->abort_notifications;
2146 camel_message_info_property_unlock (mi);
2147
2148 if (changed && !abort_notifications) {
2149 g_object_notify (G_OBJECT (mi), "user-tags");
2150 camel_message_info_set_dirty (mi, TRUE);
2151 camel_message_info_set_folder_flagged (mi, TRUE);
2152
2153 camel_message_info_update_summary_and_folder (mi, FALSE);
2154 }
2155
2156 return changed;
2157 }
2158
2159 /**
2160 * camel_message_info_get_user_tags:
2161 * @mi: a #CamelMessageInfo
2162 *
2163 * Returns: (transfer none) (nullable): a #CamelNameValueArray containing all set
2164 * user tags of the @mi. Do not modify it.
2165 *
2166 * Since: 3.24
2167 **/
2168 const CamelNameValueArray *
camel_message_info_get_user_tags(const CamelMessageInfo * mi)2169 camel_message_info_get_user_tags (const CamelMessageInfo *mi)
2170 {
2171 CamelMessageInfoClass *klass;
2172 const CamelNameValueArray *result;
2173
2174 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2175
2176 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2177 g_return_val_if_fail (klass != NULL, NULL);
2178 g_return_val_if_fail (klass->get_user_tags != NULL, NULL);
2179
2180 camel_message_info_property_lock (mi);
2181 result = klass->get_user_tags (mi);
2182 camel_message_info_property_unlock (mi);
2183
2184 return result;
2185 }
2186
2187 /**
2188 * camel_message_info_dup_user_tags:
2189 * @mi: a #CamelMessageInfo
2190 *
2191 * Returns: (transfer full) (nullable): a newly allocated #CamelNameValueArray containing all set
2192 * user tags of the @mi. Free it with camel_name_value_array_free() when no longer needed.
2193 *
2194 * Since: 3.24
2195 **/
2196 CamelNameValueArray *
camel_message_info_dup_user_tags(const CamelMessageInfo * mi)2197 camel_message_info_dup_user_tags (const CamelMessageInfo *mi)
2198 {
2199 CamelMessageInfoClass *klass;
2200 CamelNameValueArray *result;
2201
2202 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2203
2204 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2205 g_return_val_if_fail (klass != NULL, NULL);
2206 g_return_val_if_fail (klass->dup_user_tags != NULL, NULL);
2207
2208 camel_message_info_property_lock (mi);
2209 result = klass->dup_user_tags (mi);
2210 camel_message_info_property_unlock (mi);
2211
2212 return result;
2213 }
2214
2215 /**
2216 * camel_message_info_take_user_tags:
2217 * @mi: a #CamelMessageInfo
2218 * @user_tags: (transfer full) (nullable): user tags to set
2219 *
2220 * Takes all the @user_tags, which replaces any current user tags on the @mi.
2221 * The passed-in @user_tags is consumed by the @mi, which becomes an owner
2222 * of it. The caller should not change @user_tags afterwards.
2223 *
2224 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2225 * set automatically, unless the @mi is aborting notifications. There is also emitted
2226 * folder's "changed" signal for this @mi, if necessary.
2227 *
2228 * Note that it's not safe to use the @user_tags after the call to this function,
2229 * because it can be freed due to no change.
2230 *
2231 * Returns: Whether the @mi changed.
2232 *
2233 * Since: 3.24
2234 **/
2235 gboolean
camel_message_info_take_user_tags(CamelMessageInfo * mi,CamelNameValueArray * user_tags)2236 camel_message_info_take_user_tags (CamelMessageInfo *mi,
2237 CamelNameValueArray *user_tags)
2238 {
2239 CamelMessageInfoClass *klass;
2240 gboolean changed, abort_notifications;
2241
2242 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2243
2244 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2245 g_return_val_if_fail (klass != NULL, FALSE);
2246 g_return_val_if_fail (klass->take_user_tags != NULL, FALSE);
2247
2248 camel_message_info_property_lock (mi);
2249 changed = klass->take_user_tags (mi, user_tags);
2250 abort_notifications = mi->priv->abort_notifications;
2251 camel_message_info_property_unlock (mi);
2252
2253 if (changed && !abort_notifications) {
2254 g_object_notify (G_OBJECT (mi), "user-tags");
2255 camel_message_info_set_dirty (mi, TRUE);
2256 camel_message_info_set_folder_flagged (mi, TRUE);
2257
2258 camel_message_info_update_summary_and_folder (mi, FALSE);
2259 }
2260
2261 return changed;
2262 }
2263
2264 /**
2265 * camel_message_info_get_subject:
2266 * @mi: a #CamelMessageInfo
2267 *
2268 * Returns: (transfer none): Subject of the #mi.
2269 *
2270 * Since: 3.24
2271 **/
2272 const gchar *
camel_message_info_get_subject(const CamelMessageInfo * mi)2273 camel_message_info_get_subject (const CamelMessageInfo *mi)
2274 {
2275 CamelMessageInfoClass *klass;
2276 const gchar *result;
2277
2278 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2279
2280 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2281 g_return_val_if_fail (klass != NULL, NULL);
2282 g_return_val_if_fail (klass->get_subject != NULL, NULL);
2283
2284 camel_message_info_property_lock (mi);
2285 result = klass->get_subject (mi);
2286 camel_message_info_property_unlock (mi);
2287
2288 return result;
2289 }
2290
2291 /**
2292 * camel_message_info_set_subject:
2293 * @mi: a #CamelMessageInfo
2294 * @subject: (nullable): a Subject to set
2295 *
2296 * Sets Subject from the associated message.
2297 *
2298 * This property is considered static, in a meaning that it should
2299 * not change during the life-time of the @mi, the same as it doesn't
2300 * change in the associated message.
2301 *
2302 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2303 * set automatically, unless the @mi is aborting notifications. There is not emitted
2304 * folder's "changed" signal for this @mi.
2305 *
2306 * Returns: Whether the value changed.
2307 *
2308 * Since: 3.24
2309 **/
2310 gboolean
camel_message_info_set_subject(CamelMessageInfo * mi,const gchar * subject)2311 camel_message_info_set_subject (CamelMessageInfo *mi,
2312 const gchar *subject)
2313 {
2314 CamelMessageInfoClass *klass;
2315 gboolean changed, abort_notifications;
2316
2317 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2318
2319 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2320 g_return_val_if_fail (klass != NULL, FALSE);
2321 g_return_val_if_fail (klass->set_subject != NULL, FALSE);
2322
2323 camel_message_info_property_lock (mi);
2324 changed = klass->set_subject (mi, subject);
2325 abort_notifications = mi->priv->abort_notifications;
2326 camel_message_info_property_unlock (mi);
2327
2328 if (changed && !abort_notifications) {
2329 g_object_notify (G_OBJECT (mi), "subject");
2330 camel_message_info_set_dirty (mi, TRUE);
2331 camel_message_info_set_folder_flagged (mi, TRUE);
2332 }
2333
2334 return changed;
2335 }
2336
2337 /**
2338 * camel_message_info_get_from:
2339 * @mi: a #CamelMessageInfo
2340 *
2341 * Returns: (transfer none): From address of the @mi.
2342 *
2343 * Since: 3.24
2344 **/
2345 const gchar *
camel_message_info_get_from(const CamelMessageInfo * mi)2346 camel_message_info_get_from (const CamelMessageInfo *mi)
2347 {
2348 CamelMessageInfoClass *klass;
2349 const gchar *result;
2350
2351 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2352
2353 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2354 g_return_val_if_fail (klass != NULL, NULL);
2355 g_return_val_if_fail (klass->get_from != NULL, NULL);
2356
2357 camel_message_info_property_lock (mi);
2358 result = klass->get_from (mi);
2359 camel_message_info_property_unlock (mi);
2360
2361 return result;
2362 }
2363
2364 /**
2365 * camel_message_info_set_from:
2366 * @mi: a #CamelMessageInfo
2367 * @from: (nullable): a From to set
2368 *
2369 * Sets From from the associated message.
2370 *
2371 * This property is considered static, in a meaning that it should
2372 * not change during the life-time of the @mi, the same as it doesn't
2373 * change in the associated message.
2374 *
2375 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2376 * set automatically, unless the @mi is aborting notifications. There is not emitted
2377 * folder's "changed" signal for this @mi.
2378 *
2379 * Returns: Whether the value changed.
2380 *
2381 * Since: 3.24
2382 **/
2383 gboolean
camel_message_info_set_from(CamelMessageInfo * mi,const gchar * from)2384 camel_message_info_set_from (CamelMessageInfo *mi,
2385 const gchar *from)
2386 {
2387 CamelMessageInfoClass *klass;
2388 gboolean changed, abort_notifications;
2389
2390 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2391
2392 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2393 g_return_val_if_fail (klass != NULL, FALSE);
2394 g_return_val_if_fail (klass->set_from != NULL, FALSE);
2395
2396 camel_message_info_property_lock (mi);
2397 changed = klass->set_from (mi, from);
2398 abort_notifications = mi->priv->abort_notifications;
2399 camel_message_info_property_unlock (mi);
2400
2401 if (changed && !abort_notifications) {
2402 g_object_notify (G_OBJECT (mi), "from");
2403 camel_message_info_set_dirty (mi, TRUE);
2404 camel_message_info_set_folder_flagged (mi, TRUE);
2405 }
2406
2407 return changed;
2408 }
2409
2410 /**
2411 * camel_message_info_get_to:
2412 * @mi: a #CamelMessageInfo
2413 *
2414 * Returns: (transfer none): To address of the @mi.
2415 *
2416 * Since: 3.24
2417 **/
2418 const gchar *
camel_message_info_get_to(const CamelMessageInfo * mi)2419 camel_message_info_get_to (const CamelMessageInfo *mi)
2420 {
2421 CamelMessageInfoClass *klass;
2422 const gchar *result;
2423
2424 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2425
2426 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2427 g_return_val_if_fail (klass != NULL, NULL);
2428 g_return_val_if_fail (klass->get_to != NULL, NULL);
2429
2430 camel_message_info_property_lock (mi);
2431 result = klass->get_to (mi);
2432 camel_message_info_property_unlock (mi);
2433
2434 return result;
2435 }
2436
2437 /**
2438 * camel_message_info_set_to:
2439 * @mi: a #CamelMessageInfo
2440 * @to: (nullable): a To to set
2441 *
2442 * Sets To from the associated message.
2443 *
2444 * This property is considered static, in a meaning that it should
2445 * not change during the life-time of the @mi, the same as it doesn't
2446 * change in the associated message.
2447 *
2448 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2449 * set automatically, unless the @mi is aborting notifications. There is not emitted
2450 * folder's "changed" signal for this @mi.
2451 *
2452 * Returns: Whether the value changed.
2453 *
2454 * Since: 3.24
2455 **/
2456 gboolean
camel_message_info_set_to(CamelMessageInfo * mi,const gchar * to)2457 camel_message_info_set_to (CamelMessageInfo *mi,
2458 const gchar *to)
2459 {
2460 CamelMessageInfoClass *klass;
2461 gboolean changed, abort_notifications;
2462
2463 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2464
2465 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2466 g_return_val_if_fail (klass != NULL, FALSE);
2467 g_return_val_if_fail (klass->set_to != NULL, FALSE);
2468
2469 camel_message_info_property_lock (mi);
2470 changed = klass->set_to (mi, to);
2471 abort_notifications = mi->priv->abort_notifications;
2472 camel_message_info_property_unlock (mi);
2473
2474 if (changed && !abort_notifications) {
2475 g_object_notify (G_OBJECT (mi), "to");
2476 camel_message_info_set_dirty (mi, TRUE);
2477 camel_message_info_set_folder_flagged (mi, TRUE);
2478 }
2479
2480 return changed;
2481 }
2482
2483 /**
2484 * camel_message_info_get_cc:
2485 * @mi: a #CamelMessageInfo
2486 *
2487 * Returns: (transfer none): CC address of the @mi.
2488 *
2489 * Since: 3.24
2490 **/
2491 const gchar *
camel_message_info_get_cc(const CamelMessageInfo * mi)2492 camel_message_info_get_cc (const CamelMessageInfo *mi)
2493 {
2494 CamelMessageInfoClass *klass;
2495 const gchar *result;
2496
2497 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2498
2499 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2500 g_return_val_if_fail (klass != NULL, NULL);
2501 g_return_val_if_fail (klass->get_cc != NULL, NULL);
2502
2503 camel_message_info_property_lock (mi);
2504 result = klass->get_cc (mi);
2505 camel_message_info_property_unlock (mi);
2506
2507 return result;
2508 }
2509
2510 /**
2511 * camel_message_info_set_cc:
2512 * @mi: a #CamelMessageInfo
2513 * @cc: (nullable): a CC to set
2514 *
2515 * Sets CC from the associated message.
2516 *
2517 * This property is considered static, in a meaning that it should
2518 * not change during the life-time of the @mi, the same as it doesn't
2519 * change in the associated message.
2520 *
2521 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2522 * set automatically, unless the @mi is aborting notifications. There is not emitted
2523 * folder's "changed" signal for this @mi.
2524 *
2525 * Returns: Whether the value changed.
2526 *
2527 * Since: 3.24
2528 **/
2529 gboolean
camel_message_info_set_cc(CamelMessageInfo * mi,const gchar * cc)2530 camel_message_info_set_cc (CamelMessageInfo *mi,
2531 const gchar *cc)
2532 {
2533 CamelMessageInfoClass *klass;
2534 gboolean changed, abort_notifications;
2535
2536 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2537
2538 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2539 g_return_val_if_fail (klass != NULL, FALSE);
2540 g_return_val_if_fail (klass->set_cc != NULL, FALSE);
2541
2542 camel_message_info_property_lock (mi);
2543 changed = klass->set_cc (mi, cc);
2544 abort_notifications = mi->priv->abort_notifications;
2545 camel_message_info_property_unlock (mi);
2546
2547 if (changed && !abort_notifications) {
2548 g_object_notify (G_OBJECT (mi), "cc");
2549 camel_message_info_set_dirty (mi, TRUE);
2550 camel_message_info_set_folder_flagged (mi, TRUE);
2551 }
2552
2553 return changed;
2554 }
2555
2556 /**
2557 * camel_message_info_get_mlist:
2558 * @mi: a #CamelMessageInfo
2559 *
2560 * Returns: (transfer none): Mailing list address of the @mi.
2561 *
2562 * Since: 3.24
2563 **/
2564 const gchar *
camel_message_info_get_mlist(const CamelMessageInfo * mi)2565 camel_message_info_get_mlist (const CamelMessageInfo *mi)
2566 {
2567 CamelMessageInfoClass *klass;
2568 const gchar *result;
2569
2570 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2571
2572 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2573 g_return_val_if_fail (klass != NULL, NULL);
2574 g_return_val_if_fail (klass->get_mlist != NULL, NULL);
2575
2576 camel_message_info_property_lock (mi);
2577 result = klass->get_mlist (mi);
2578 camel_message_info_property_unlock (mi);
2579
2580 return result;
2581 }
2582
2583 /**
2584 * camel_message_info_set_mlist:
2585 * @mi: a #CamelMessageInfo
2586 * @mlist: (nullable): a message list address to set
2587 *
2588 * Sets mesage list address from the associated message.
2589 *
2590 * This property is considered static, in a meaning that it should
2591 * not change during the life-time of the @mi, the same as it doesn't
2592 * change in the associated message.
2593 *
2594 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2595 * set automatically, unless the @mi is aborting notifications. There is not emitted
2596 * folder's "changed" signal for this @mi.
2597 *
2598 * Returns: Whether the value changed.
2599 *
2600 * Since: 3.24
2601 **/
2602 gboolean
camel_message_info_set_mlist(CamelMessageInfo * mi,const gchar * mlist)2603 camel_message_info_set_mlist (CamelMessageInfo *mi,
2604 const gchar *mlist)
2605 {
2606 CamelMessageInfoClass *klass;
2607 gboolean changed, abort_notifications;
2608
2609 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2610
2611 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2612 g_return_val_if_fail (klass != NULL, FALSE);
2613 g_return_val_if_fail (klass->set_mlist != NULL, FALSE);
2614
2615 camel_message_info_property_lock (mi);
2616 changed = klass->set_mlist (mi, mlist);
2617 abort_notifications = mi->priv->abort_notifications;
2618 camel_message_info_property_unlock (mi);
2619
2620 if (changed && !abort_notifications) {
2621 g_object_notify (G_OBJECT (mi), "mlist");
2622 camel_message_info_set_dirty (mi, TRUE);
2623 camel_message_info_set_folder_flagged (mi, TRUE);
2624 }
2625
2626 return changed;
2627 }
2628
2629 /**
2630 * camel_message_info_get_size:
2631 * @mi: a #CamelMessageInfo
2632 *
2633 * Returns: Size of the associated message.
2634 *
2635 * Since: 3.24
2636 **/
2637 guint32
camel_message_info_get_size(const CamelMessageInfo * mi)2638 camel_message_info_get_size (const CamelMessageInfo *mi)
2639 {
2640 CamelMessageInfoClass *klass;
2641 guint32 result;
2642
2643 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
2644
2645 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2646 g_return_val_if_fail (klass != NULL, 0);
2647 g_return_val_if_fail (klass->get_size != NULL, 0);
2648
2649 camel_message_info_property_lock (mi);
2650 result = klass->get_size (mi);
2651 camel_message_info_property_unlock (mi);
2652
2653 return result;
2654 }
2655
2656 /**
2657 * camel_message_info_set_size:
2658 * @mi: a #CamelMessageInfo
2659 * @size: a size to set
2660 *
2661 * Sets size of the associated message.
2662 *
2663 * This property is considered static, in a meaning that it should
2664 * not change during the life-time of the @mi, the same as it doesn't
2665 * change in the associated message.
2666 *
2667 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2668 * set automatically, unless the @mi is aborting notifications. There is not emitted
2669 * folder's "changed" signal for this @mi.
2670 *
2671 * Returns: Whether the value changed.
2672 *
2673 * Since: 3.24
2674 **/
2675 gboolean
camel_message_info_set_size(CamelMessageInfo * mi,guint32 size)2676 camel_message_info_set_size (CamelMessageInfo *mi,
2677 guint32 size)
2678 {
2679 CamelMessageInfoClass *klass;
2680 gboolean changed, abort_notifications;
2681
2682 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2683
2684 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2685 g_return_val_if_fail (klass != NULL, FALSE);
2686 g_return_val_if_fail (klass->set_size != NULL, FALSE);
2687
2688 camel_message_info_property_lock (mi);
2689 changed = klass->set_size (mi, size);
2690 abort_notifications = mi->priv->abort_notifications;
2691 camel_message_info_property_unlock (mi);
2692
2693 if (changed && !abort_notifications) {
2694 g_object_notify (G_OBJECT (mi), "size");
2695 camel_message_info_set_dirty (mi, TRUE);
2696 camel_message_info_set_folder_flagged (mi, TRUE);
2697 }
2698
2699 return changed;
2700 }
2701
2702 /**
2703 * camel_message_info_get_date_sent:
2704 * @mi: a #CamelMessageInfo
2705 *
2706 * Returns: time_t of the Date header of the message, encoded as gint64.
2707 *
2708 * Since: 3.24
2709 **/
2710 gint64
camel_message_info_get_date_sent(const CamelMessageInfo * mi)2711 camel_message_info_get_date_sent (const CamelMessageInfo *mi)
2712 {
2713 CamelMessageInfoClass *klass;
2714 gint64 result;
2715
2716 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
2717
2718 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2719 g_return_val_if_fail (klass != NULL, 0);
2720 g_return_val_if_fail (klass->get_date_sent != NULL, 0);
2721
2722 camel_message_info_property_lock (mi);
2723 result = klass->get_date_sent (mi);
2724 camel_message_info_property_unlock (mi);
2725
2726 return result;
2727 }
2728
2729 /**
2730 * camel_message_info_set_date_sent:
2731 * @mi: a #CamelMessageInfo
2732 * @date_sent: a sent date to set
2733 *
2734 * Sets sent date (the Date header) of the associated message.
2735 *
2736 * This property is considered static, in a meaning that it should
2737 * not change during the life-time of the @mi, the same as it doesn't
2738 * change in the associated message.
2739 *
2740 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2741 * set automatically, unless the @mi is aborting notifications. There is not emitted
2742 * folder's "changed" signal for this @mi.
2743 *
2744 * Returns: Whether the value changed.
2745 *
2746 * Since: 3.24
2747 **/
2748 gboolean
camel_message_info_set_date_sent(CamelMessageInfo * mi,gint64 date_sent)2749 camel_message_info_set_date_sent (CamelMessageInfo *mi,
2750 gint64 date_sent)
2751 {
2752 CamelMessageInfoClass *klass;
2753 gboolean changed, abort_notifications;
2754
2755 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2756
2757 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2758 g_return_val_if_fail (klass != NULL, FALSE);
2759 g_return_val_if_fail (klass->set_date_sent != NULL, FALSE);
2760
2761 camel_message_info_property_lock (mi);
2762 changed = klass->set_date_sent (mi, date_sent);
2763 abort_notifications = mi->priv->abort_notifications;
2764 camel_message_info_property_unlock (mi);
2765
2766 if (changed && !abort_notifications) {
2767 g_object_notify (G_OBJECT (mi), "date-sent");
2768 camel_message_info_set_dirty (mi, TRUE);
2769 camel_message_info_set_folder_flagged (mi, TRUE);
2770 }
2771
2772 return changed;
2773 }
2774
2775 /**
2776 * camel_message_info_get_date_received:
2777 * @mi: a #CamelMessageInfo
2778 *
2779 * Returns: time_t of the Received header of the message, encoded as gint64.
2780 *
2781 * Since: 3.24
2782 **/
2783 gint64
camel_message_info_get_date_received(const CamelMessageInfo * mi)2784 camel_message_info_get_date_received (const CamelMessageInfo *mi)
2785 {
2786 CamelMessageInfoClass *klass;
2787 gint64 result;
2788
2789 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
2790
2791 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2792 g_return_val_if_fail (klass != NULL, 0);
2793 g_return_val_if_fail (klass->get_date_received != NULL, 0);
2794
2795 camel_message_info_property_lock (mi);
2796 result = klass->get_date_received (mi);
2797 camel_message_info_property_unlock (mi);
2798
2799 return result;
2800 }
2801
2802 /**
2803 * camel_message_info_set_date_received:
2804 * @mi: a #CamelMessageInfo
2805 * @date_received: a received date to set
2806 *
2807 * Sets received date (the Received header) of the associated message.
2808 *
2809 * This property is considered static, in a meaning that it should
2810 * not change during the life-time of the @mi, the same as it doesn't
2811 * change in the associated message.
2812 *
2813 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2814 * set automatically, unless the @mi is aborting notifications. There is not emitted
2815 * folder's "changed" signal for this @mi.
2816 *
2817 * Returns: Whether the value changed.
2818 *
2819 * Since: 3.24
2820 **/
2821 gboolean
camel_message_info_set_date_received(CamelMessageInfo * mi,gint64 date_received)2822 camel_message_info_set_date_received (CamelMessageInfo *mi,
2823 gint64 date_received)
2824 {
2825 CamelMessageInfoClass *klass;
2826 gboolean changed, abort_notifications;
2827
2828 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2829
2830 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2831 g_return_val_if_fail (klass != NULL, FALSE);
2832 g_return_val_if_fail (klass->set_date_received != NULL, FALSE);
2833
2834 camel_message_info_property_lock (mi);
2835 changed = klass->set_date_received (mi, date_received);
2836 abort_notifications = mi->priv->abort_notifications;
2837 camel_message_info_property_unlock (mi);
2838
2839 if (changed && !abort_notifications) {
2840 g_object_notify (G_OBJECT (mi), "date-received");
2841 camel_message_info_set_dirty (mi, TRUE);
2842 camel_message_info_set_folder_flagged (mi, TRUE);
2843 }
2844
2845 return changed;
2846 }
2847
2848 /**
2849 * camel_message_info_get_message_id:
2850 * @mi: a #CamelMessageInfo
2851 *
2852 * Encoded Message-ID of the associated message as a guint64 number,
2853 * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
2854 *
2855 * Returns: Partial MD5 hash of the Message-ID header of the associated message.
2856 *
2857 * Since: 3.24
2858 **/
2859 guint64
camel_message_info_get_message_id(const CamelMessageInfo * mi)2860 camel_message_info_get_message_id (const CamelMessageInfo *mi)
2861 {
2862 CamelMessageInfoClass *klass;
2863 guint64 result;
2864
2865 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), 0);
2866
2867 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2868 g_return_val_if_fail (klass != NULL, 0);
2869 g_return_val_if_fail (klass->get_message_id != NULL, 0);
2870
2871 camel_message_info_property_lock (mi);
2872 result = klass->get_message_id (mi);
2873 camel_message_info_property_unlock (mi);
2874
2875 return result;
2876 }
2877
2878 /**
2879 * camel_message_info_set_message_id:
2880 * @mi: a #CamelMessageInfo
2881 * @message_id: a message id to set
2882 *
2883 * Sets encoded Message-ID of the associated message as a guint64 number,
2884 * partial MD5 sum. The value can be cast to #CamelSummaryMessageID.
2885 *
2886 * This property is considered static, in a meaning that it should
2887 * not change during the life-time of the @mi, the same as it doesn't
2888 * change in the associated message.
2889 *
2890 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
2891 * set automatically, unless the @mi is aborting notifications. There is not emitted
2892 * folder's "changed" signal for this @mi.
2893 *
2894 * Returns: Whether the value changed.
2895 *
2896 * Since: 3.24
2897 **/
2898 gboolean
camel_message_info_set_message_id(CamelMessageInfo * mi,guint64 message_id)2899 camel_message_info_set_message_id (CamelMessageInfo *mi,
2900 guint64 message_id)
2901 {
2902 CamelMessageInfoClass *klass;
2903 gboolean changed, abort_notifications;
2904
2905 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
2906
2907 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2908 g_return_val_if_fail (klass != NULL, FALSE);
2909 g_return_val_if_fail (klass->set_message_id != NULL, FALSE);
2910
2911 camel_message_info_property_lock (mi);
2912 changed = klass->set_message_id (mi, message_id);
2913 abort_notifications = mi->priv->abort_notifications;
2914 camel_message_info_property_unlock (mi);
2915
2916 if (changed && !abort_notifications) {
2917 g_object_notify (G_OBJECT (mi), "message-id");
2918 camel_message_info_set_dirty (mi, TRUE);
2919 camel_message_info_set_folder_flagged (mi, TRUE);
2920 }
2921
2922 return changed;
2923 }
2924
2925 /**
2926 * camel_message_info_get_references:
2927 * @mi: a #CamelMessageInfo
2928 *
2929 * Gets encoded In-Reply-To and References headers of the associated
2930 * message as an array of guint64 numbers, partial MD5 sums. Each value
2931 * can be cast to #CamelSummaryMessageID.
2932 *
2933 * Returns: (transfer none) (nullable) (element-type guint64): A #GArray of
2934 * guint64 encoded Message-ID-s; or %NULL when none are available.
2935 *
2936 * Since: 3.24
2937 **/
2938 const GArray *
camel_message_info_get_references(const CamelMessageInfo * mi)2939 camel_message_info_get_references (const CamelMessageInfo *mi)
2940 {
2941 CamelMessageInfoClass *klass;
2942 const GArray *result;
2943
2944 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2945
2946 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
2947 g_return_val_if_fail (klass != NULL, NULL);
2948 g_return_val_if_fail (klass->get_references != NULL, NULL);
2949
2950 camel_message_info_property_lock (mi);
2951 result = klass->get_references (mi);
2952 camel_message_info_property_unlock (mi);
2953
2954 return result;
2955 }
2956
2957 /**
2958 * camel_message_info_dup_references:
2959 * @mi: a #CamelMessageInfo
2960 *
2961 * Duplicates encoded In-Reply-To and References headers of the associated
2962 * message as an array of guint64 numbers, partial MD5 sums. Each value
2963 * can be cast to #CamelSummaryMessageID.
2964 *
2965 * Returns: (transfer full) (nullable) (element-type guint64): A #GArray of
2966 * guint64 encoded Message-ID-s; or %NULL when none are available. Free returned
2967 * array with g_array_unref() when no longer needed.
2968 *
2969 * Since: 3.24
2970 **/
2971 GArray *
camel_message_info_dup_references(const CamelMessageInfo * mi)2972 camel_message_info_dup_references (const CamelMessageInfo *mi)
2973 {
2974 const GArray *arr;
2975 GArray *result;
2976
2977 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
2978
2979 camel_message_info_property_lock (mi);
2980 arr = camel_message_info_get_references (mi);
2981 if (arr) {
2982 guint ii;
2983
2984 result = g_array_sized_new (FALSE, FALSE, sizeof (guint64), arr->len);
2985 for (ii = 0; ii < arr->len; ii++) {
2986 g_array_append_val (result, g_array_index (arr, guint64, ii));
2987 }
2988 } else {
2989 result = NULL;
2990 }
2991 camel_message_info_property_unlock (mi);
2992
2993 return result;
2994 }
2995
2996 /**
2997 * camel_message_info_take_references:
2998 * @mi: a #CamelMessageInfo
2999 * @references: (element-type guint64) (transfer full) (nullable): a references to set
3000 *
3001 * Takes encoded In-Reply-To and References headers of the associated message
3002 * as an array of guint64 numbers, partial MD5 sums. Each value can be
3003 * cast to #CamelSummaryMessageID.
3004 *
3005 * This property is considered static, in a meaning that it should
3006 * not change during the life-time of the @mi, the same as it doesn't
3007 * change in the associated message.
3008 *
3009 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
3010 * set automatically, unless the @mi is aborting notifications. There is not emitted
3011 * folder's "changed" signal for this @mi.
3012 *
3013 * Note that it's not safe to use the @references after the call to this function,
3014 * because it can be freed due to no change.
3015 *
3016 * Returns: Whether the value changed.
3017 *
3018 * Since: 3.24
3019 **/
3020 gboolean
camel_message_info_take_references(CamelMessageInfo * mi,GArray * references)3021 camel_message_info_take_references (CamelMessageInfo *mi,
3022 GArray *references)
3023 {
3024 CamelMessageInfoClass *klass;
3025 gboolean changed, abort_notifications;
3026
3027 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
3028
3029 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3030 g_return_val_if_fail (klass != NULL, FALSE);
3031 g_return_val_if_fail (klass->take_references != NULL, FALSE);
3032
3033 camel_message_info_property_lock (mi);
3034 changed = klass->take_references (mi, references);
3035 abort_notifications = mi->priv->abort_notifications;
3036 camel_message_info_property_unlock (mi);
3037
3038 if (changed && !abort_notifications) {
3039 g_object_notify (G_OBJECT (mi), "references");
3040 camel_message_info_set_dirty (mi, TRUE);
3041 camel_message_info_set_folder_flagged (mi, TRUE);
3042 }
3043
3044 return changed;
3045 }
3046
3047 /**
3048 * camel_message_info_get_headers:
3049 * @mi: a #CamelMessageInfo
3050 *
3051 * Returns: (transfer none) (nullable): All the message headers of the associated
3052 * message, or %NULL, when none are available.
3053 *
3054 * Since: 3.24
3055 **/
3056 const CamelNameValueArray *
camel_message_info_get_headers(const CamelMessageInfo * mi)3057 camel_message_info_get_headers (const CamelMessageInfo *mi)
3058 {
3059 CamelMessageInfoClass *klass;
3060 const CamelNameValueArray *result;
3061
3062 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3063
3064 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3065 g_return_val_if_fail (klass != NULL, NULL);
3066 g_return_val_if_fail (klass->get_headers != NULL, NULL);
3067
3068 camel_message_info_property_lock (mi);
3069 result = klass->get_headers (mi);
3070 camel_message_info_property_unlock (mi);
3071
3072 return result;
3073 }
3074
3075 /**
3076 * camel_message_info_dup_headers:
3077 * @mi: a #CamelMessageInfo
3078 *
3079 * Duplicates array of headers for the @mi.
3080 *
3081 * Returns: (transfer full) (nullable): All the message headers of the associated
3082 * message, or %NULL, when none are available. Free returned array with
3083 * camel_name_value_array_free() when no longer needed.
3084 *
3085 * Since: 3.24
3086 **/
3087 CamelNameValueArray *
camel_message_info_dup_headers(const CamelMessageInfo * mi)3088 camel_message_info_dup_headers (const CamelMessageInfo *mi)
3089 {
3090 const CamelNameValueArray *arr;
3091 CamelNameValueArray *result;
3092
3093 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3094
3095 camel_message_info_property_lock (mi);
3096 arr = camel_message_info_get_headers (mi);
3097 if (arr) {
3098 result = camel_name_value_array_copy (arr);
3099 } else {
3100 result = NULL;
3101 }
3102 camel_message_info_property_unlock (mi);
3103
3104 return result;
3105 }
3106
3107 /**
3108 * camel_message_info_take_headers:
3109 * @mi: a #CamelMessageInfo
3110 * @headers: (transfer full) (nullable): headers to set, as #CamelNameValueArray, or %NULL
3111 *
3112 * Takes headers of the associated message.
3113 *
3114 * This property is considered static, in a meaning that it should
3115 * not change during the life-time of the @mi, the same as it doesn't
3116 * change in the associated message.
3117 *
3118 * If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
3119 * set automatically, unless the @mi is aborting notifications. There is not emitted
3120 * folder's "changed" signal for this @mi.
3121 *
3122 * Note that it's not safe to use the @headers after the call to this function,
3123 * because it can be freed due to no change.
3124 *
3125 * Returns: Whether the value changed.
3126 *
3127 * Since: 3.24
3128 **/
3129 gboolean
camel_message_info_take_headers(CamelMessageInfo * mi,CamelNameValueArray * headers)3130 camel_message_info_take_headers (CamelMessageInfo *mi,
3131 CamelNameValueArray *headers)
3132 {
3133 CamelMessageInfoClass *klass;
3134 gboolean changed, abort_notifications;
3135
3136 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
3137
3138 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3139 g_return_val_if_fail (klass != NULL, FALSE);
3140 g_return_val_if_fail (klass->take_headers != NULL, FALSE);
3141
3142 camel_message_info_property_lock (mi);
3143 changed = klass->take_headers (mi, headers);
3144 abort_notifications = mi->priv->abort_notifications;
3145 camel_message_info_property_unlock (mi);
3146
3147 if (changed && !abort_notifications) {
3148 g_object_notify (G_OBJECT (mi), "headers");
3149 camel_message_info_set_dirty (mi, TRUE);
3150 camel_message_info_set_folder_flagged (mi, TRUE);
3151 }
3152
3153 return changed;
3154 }
3155
3156 /**
3157 * camel_message_info_get_user_header:
3158 * @mi: a #CamelMessageInfo
3159 * @name: header name
3160 *
3161 * Returns: (transfer none) (nullable): Value of the header named @name from
3162 * the user-defined message headers of the associated message, or %NULL,
3163 * when not available.
3164 *
3165 * Since: 3.42
3166 **/
3167 const gchar *
camel_message_info_get_user_header(const CamelMessageInfo * mi,const gchar * name)3168 camel_message_info_get_user_header (const CamelMessageInfo *mi,
3169 const gchar *name)
3170 {
3171 CamelMessageInfoClass *klass;
3172 const gchar *result;
3173
3174 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3175 g_return_val_if_fail (name != NULL, NULL);
3176
3177 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3178 g_return_val_if_fail (klass != NULL, NULL);
3179 g_return_val_if_fail (klass->get_user_header != NULL, NULL);
3180
3181 camel_message_info_property_lock (mi);
3182 result = klass->get_user_header (mi, name);
3183 camel_message_info_property_unlock (mi);
3184
3185 return result;
3186 }
3187
3188 /**
3189 * camel_message_info_dup_user_header:
3190 * @mi: a #CamelMessageInfo
3191 * @name: header name
3192 *
3193 * Returns: (transfer full) (nullable): Value of the header named @name from
3194 * the user-defined message headers of the associated message, or %NULL,
3195 * when not available. Free the returned string with g_free(), when no longer
3196 * needed.
3197 *
3198 * Since: 3.42
3199 **/
3200 gchar *
camel_message_info_dup_user_header(const CamelMessageInfo * mi,const gchar * name)3201 camel_message_info_dup_user_header (const CamelMessageInfo *mi,
3202 const gchar *name)
3203 {
3204 gchar *result;
3205
3206 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3207
3208 camel_message_info_property_lock (mi);
3209 result = g_strdup (camel_message_info_get_user_header (mi, name));
3210 camel_message_info_property_unlock (mi);
3211
3212 return result;
3213 }
3214
3215 /**
3216 * camel_message_info_set_user_header:
3217 * @mi: a #CamelMessageInfo
3218 * @name: header name
3219 * @value: (nullable): header value, or %NULL
3220 *
3221 * Set @value for a single user-defined message header of the associated message.
3222 * When the @value is %NULL, the header @name is removed from the user-defined
3223 * headers.
3224 *
3225 * If the @mi changed, the 'dirty' flag is set automatically, unless the @mi is
3226 * aborting notifications. There is not emitted folder's "changed" signal for this @mi.
3227 *
3228 * Returns: Whether the value changed.
3229 *
3230 * Since: 3.42
3231 **/
3232 gboolean
camel_message_info_set_user_header(CamelMessageInfo * mi,const gchar * name,const gchar * value)3233 camel_message_info_set_user_header (CamelMessageInfo *mi,
3234 const gchar *name,
3235 const gchar *value)
3236 {
3237 CamelMessageInfoClass *klass;
3238 gboolean changed, abort_notifications;
3239
3240 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
3241
3242 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3243 g_return_val_if_fail (klass != NULL, FALSE);
3244 g_return_val_if_fail (klass->set_user_header != NULL, FALSE);
3245
3246 camel_message_info_property_lock (mi);
3247 changed = klass->set_user_header (mi, name, value);
3248 abort_notifications = mi->priv->abort_notifications;
3249 camel_message_info_property_unlock (mi);
3250
3251 if (changed && !abort_notifications) {
3252 g_object_notify (G_OBJECT (mi), "user-headers");
3253 camel_message_info_set_dirty (mi, TRUE);
3254 }
3255
3256 return changed;
3257 }
3258
3259 /**
3260 * camel_message_info_get_user_headers:
3261 * @mi: a #CamelMessageInfo
3262 *
3263 * Returns: (transfer none) (nullable): All the user-defined message headers
3264 * of the associated message, or %NULL, when none are available.
3265 *
3266 * Since: 3.42
3267 **/
3268 const CamelNameValueArray *
camel_message_info_get_user_headers(const CamelMessageInfo * mi)3269 camel_message_info_get_user_headers (const CamelMessageInfo *mi)
3270 {
3271 CamelMessageInfoClass *klass;
3272 const CamelNameValueArray *result;
3273
3274 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3275
3276 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3277 g_return_val_if_fail (klass != NULL, NULL);
3278 g_return_val_if_fail (klass->get_user_headers != NULL, NULL);
3279
3280 camel_message_info_property_lock (mi);
3281 result = klass->get_user_headers (mi);
3282 camel_message_info_property_unlock (mi);
3283
3284 return result;
3285 }
3286
3287 /**
3288 * camel_message_info_dup_user_headers:
3289 * @mi: a #CamelMessageInfo
3290 *
3291 * Returns: (transfer full) (nullable): All the user-defined message headers
3292 * of the associated message, or %NULL, when none are available. Free returned
3293 * array with camel_name_value_array_free() when no longer needed.
3294 *
3295 * Since: 3.42
3296 **/
3297 CamelNameValueArray *
camel_message_info_dup_user_headers(const CamelMessageInfo * mi)3298 camel_message_info_dup_user_headers (const CamelMessageInfo *mi)
3299 {
3300 const CamelNameValueArray *arr;
3301 CamelNameValueArray *result;
3302
3303 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3304
3305 camel_message_info_property_lock (mi);
3306 arr = camel_message_info_get_user_headers (mi);
3307 if (arr) {
3308 result = camel_name_value_array_copy (arr);
3309 } else {
3310 result = NULL;
3311 }
3312 camel_message_info_property_unlock (mi);
3313
3314 return result;
3315 }
3316
3317 /**
3318 * camel_message_info_take_user_headers:
3319 * @mi: a #CamelMessageInfo
3320 * @headers: (transfer full) (nullable): headers to set, as #CamelNameValueArray, or %NULL
3321 *
3322 * Takes user-defined message headers of the associated message.
3323 *
3324 * If the @mi changed, the 'dirty' flag is set automatically, unless the @mi is
3325 * aborting notifications. There is not emitted folder's "changed" signal for this @mi.
3326 *
3327 * Note that it's not safe to use the @headers after the call to this function,
3328 * because it can be freed due to no change.
3329 *
3330 * Returns: Whether the value changed.
3331 *
3332 * Since: 3.42
3333 **/
3334 gboolean
camel_message_info_take_user_headers(CamelMessageInfo * mi,CamelNameValueArray * headers)3335 camel_message_info_take_user_headers (CamelMessageInfo *mi,
3336 CamelNameValueArray *headers)
3337 {
3338 CamelMessageInfoClass *klass;
3339 gboolean changed, abort_notifications;
3340
3341 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
3342
3343 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3344 g_return_val_if_fail (klass != NULL, FALSE);
3345 g_return_val_if_fail (klass->take_user_headers != NULL, FALSE);
3346
3347 camel_message_info_property_lock (mi);
3348 changed = klass->take_user_headers (mi, headers);
3349 abort_notifications = mi->priv->abort_notifications;
3350 camel_message_info_property_unlock (mi);
3351
3352 if (changed && !abort_notifications) {
3353 g_object_notify (G_OBJECT (mi), "user-headers");
3354 camel_message_info_set_dirty (mi, TRUE);
3355 }
3356
3357 return changed;
3358 }
3359
3360 /**
3361 * camel_message_info_get_preview:
3362 * @mi: a #CamelMessageInfo
3363 *
3364 * Returns: (transfer none) (nullable): Body preview of the associated
3365 * message, or %NULL, when not available.
3366 *
3367 * Since: 3.42
3368 **/
3369 const gchar *
camel_message_info_get_preview(const CamelMessageInfo * mi)3370 camel_message_info_get_preview (const CamelMessageInfo *mi)
3371 {
3372 CamelMessageInfoClass *klass;
3373 const gchar *result;
3374
3375 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3376
3377 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3378 g_return_val_if_fail (klass != NULL, NULL);
3379 g_return_val_if_fail (klass->get_preview != NULL, NULL);
3380
3381 camel_message_info_property_lock (mi);
3382 result = klass->get_preview (mi);
3383 camel_message_info_property_unlock (mi);
3384
3385 return result;
3386 }
3387
3388 /**
3389 * camel_message_info_dup_preview:
3390 * @mi: a #CamelMessageInfo
3391 *
3392 * Returns: (transfer none) (nullable): Body preview of the associated
3393 * message, or %NULL, when not available. Free the returned string
3394 * with g_free(), when no longer needed.
3395 *
3396 * Since: 3.42
3397 **/
3398 gchar *
camel_message_info_dup_preview(const CamelMessageInfo * mi)3399 camel_message_info_dup_preview (const CamelMessageInfo *mi)
3400 {
3401 gchar *result;
3402
3403 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), NULL);
3404
3405 camel_message_info_property_lock (mi);
3406 result = g_strdup (camel_message_info_get_preview (mi));
3407 camel_message_info_property_unlock (mi);
3408
3409 return result;
3410 }
3411
3412 /**
3413 * camel_message_info_set_preview:
3414 * @mi: a #CamelMessageInfo
3415 * @preview: (nullable): message body preview, or %NULL
3416 *
3417 * Set @preview as the body preview of the associated message. Use %NULL or an empty
3418 * string to unset the value.
3419 *
3420 * If the @mi changed, the 'dirty' flag is set automatically, unless the @mi is
3421 * aborting notifications. There is not emitted folder's "changed" signal for this @mi.
3422 *
3423 * Returns: Whether the value changed.
3424 *
3425 * Since: 3.42
3426 **/
3427 gboolean
camel_message_info_set_preview(CamelMessageInfo * mi,const gchar * preview)3428 camel_message_info_set_preview (CamelMessageInfo *mi,
3429 const gchar *preview)
3430 {
3431 CamelMessageInfoClass *klass;
3432 gboolean changed, abort_notifications;
3433
3434 g_return_val_if_fail (CAMEL_IS_MESSAGE_INFO (mi), FALSE);
3435
3436 klass = CAMEL_MESSAGE_INFO_GET_CLASS (mi);
3437 g_return_val_if_fail (klass != NULL, FALSE);
3438 g_return_val_if_fail (klass->set_preview != NULL, FALSE);
3439
3440 camel_message_info_property_lock (mi);
3441 changed = klass->set_preview (mi, preview);
3442 abort_notifications = mi->priv->abort_notifications;
3443 camel_message_info_property_unlock (mi);
3444
3445 if (changed && !abort_notifications) {
3446 g_object_notify (G_OBJECT (mi), "preview");
3447 camel_message_info_set_dirty (mi, TRUE);
3448 }
3449
3450 return changed;
3451 }
3452
3453 /**
3454 * camel_message_info_dump:
3455 * @mi: a #CamelMessageInfo
3456 *
3457 * Dumps the mesasge info @mi to stdout. This is meand for debugging
3458 * purposes only.
3459 *
3460 * Since: 3.24
3461 **/
3462 void
camel_message_info_dump(CamelMessageInfo * mi)3463 camel_message_info_dump (CamelMessageInfo *mi)
3464 {
3465 if (!mi) {
3466 printf ("No message info\n");
3467 return;
3468 }
3469
3470 camel_message_info_property_lock (mi);
3471
3472 printf ("Message info %s:\n", G_OBJECT_TYPE_NAME (mi));
3473 printf (" UID: %s\n", camel_message_info_get_uid (mi));
3474 printf (" Flags: %04x\n", camel_message_info_get_flags (mi));
3475 printf (" From: %s\n", camel_message_info_get_from (mi));
3476 printf (" To: %s\n", camel_message_info_get_to (mi));
3477 printf (" Cc: %s\n", camel_message_info_get_cc (mi));
3478 printf (" Mailing list: %s\n", camel_message_info_get_mlist (mi));
3479 printf (" Subject: %s\n", camel_message_info_get_subject (mi));
3480
3481 camel_message_info_property_unlock (mi);
3482 }
3483