1 /*
2  * camel-imapx-mailbox.c
3  *
4  * This library is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library. If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 /**
19  * SECTION: camel-imapx-mailbox
20  * @include: camel/camel.h
21  * @short_description: Stores the state of an IMAP mailbox
22  *
23  * #CamelIMAPXMailbox models the current state of an IMAP mailbox as
24  * accumulated from untagged IMAP server responses in the current session.
25  *
26  * In particular, a #CamelIMAPXMailbox should <emphasis>not</emphasis> be
27  * populated with locally cached information from the previous session.
28  * This is why instantiation requires a #CamelIMAPXListResponse.
29  **/
30 
31 #include "evolution-data-server-config.h"
32 
33 #include "camel-imapx-mailbox.h"
34 #include "camel-imapx-utils.h"
35 
36 struct _CamelIMAPXMailboxPrivate {
37 	gchar *name;
38 	gchar separator;
39 	CamelIMAPXNamespace *namespace;
40 
41 	guint32 messages;
42 	guint32 recent;
43 	guint32 unseen;
44 	guint32 uidnext;
45 	guint32 uidvalidity;
46 	guint64 highestmodseq;
47 	guint32 permanentflags;
48 
49 	volatile gint change_stamp;
50 
51 	CamelIMAPXMailboxState state;
52 
53 	GMutex property_lock;
54 	GMutex update_lock;
55 	gint update_count;
56 
57 	/* Protected by the "property_lock". */
58 	GHashTable *attributes;
59 	GSequence *message_map;
60 	gchar **quota_roots;
61 };
62 
G_DEFINE_TYPE_WITH_PRIVATE(CamelIMAPXMailbox,camel_imapx_mailbox,G_TYPE_OBJECT)63 G_DEFINE_TYPE_WITH_PRIVATE (
64 	CamelIMAPXMailbox,
65 	camel_imapx_mailbox,
66 	G_TYPE_OBJECT)
67 
68 static gint
69 imapx_mailbox_message_map_compare (gconstpointer a,
70                                    gconstpointer b,
71                                    gpointer unused)
72 {
73 	guint32 uid_a = GPOINTER_TO_UINT (a);
74 	guint32 uid_b = GPOINTER_TO_UINT (b);
75 
76 	return (uid_a == uid_b) ? 0 : (uid_a < uid_b) ? -1 : 1;
77 }
78 
79 static void
imapx_mailbox_dispose(GObject * object)80 imapx_mailbox_dispose (GObject *object)
81 {
82 	CamelIMAPXMailboxPrivate *priv;
83 
84 	priv = CAMEL_IMAPX_MAILBOX (object)->priv;
85 
86 	g_clear_object (&priv->namespace);
87 
88 	/* Chain up to parent's dispose() method. */
89 	G_OBJECT_CLASS (camel_imapx_mailbox_parent_class)->dispose (object);
90 }
91 
92 static void
imapx_mailbox_finalize(GObject * object)93 imapx_mailbox_finalize (GObject *object)
94 {
95 	CamelIMAPXMailboxPrivate *priv;
96 
97 	priv = CAMEL_IMAPX_MAILBOX (object)->priv;
98 
99 	g_free (priv->name);
100 
101 	g_mutex_clear (&priv->property_lock);
102 	g_mutex_clear (&priv->update_lock);
103 	g_hash_table_destroy (priv->attributes);
104 	g_sequence_free (priv->message_map);
105 	g_strfreev (priv->quota_roots);
106 
107 	/* Chain up to parent's finalize() method. */
108 	G_OBJECT_CLASS (camel_imapx_mailbox_parent_class)->finalize (object);
109 }
110 
111 static void
camel_imapx_mailbox_class_init(CamelIMAPXMailboxClass * class)112 camel_imapx_mailbox_class_init (CamelIMAPXMailboxClass *class)
113 {
114 	GObjectClass *object_class;
115 
116 	object_class = G_OBJECT_CLASS (class);
117 	object_class->dispose = imapx_mailbox_dispose;
118 	object_class->finalize = imapx_mailbox_finalize;
119 }
120 
121 static void
camel_imapx_mailbox_init(CamelIMAPXMailbox * mailbox)122 camel_imapx_mailbox_init (CamelIMAPXMailbox *mailbox)
123 {
124 	mailbox->priv = camel_imapx_mailbox_get_instance_private (mailbox);
125 
126 	g_mutex_init (&mailbox->priv->property_lock);
127 	g_mutex_init (&mailbox->priv->update_lock);
128 	mailbox->priv->message_map = g_sequence_new (NULL);
129 	mailbox->priv->permanentflags = ~0;
130 	mailbox->priv->state = CAMEL_IMAPX_MAILBOX_STATE_CREATED;
131 	mailbox->priv->update_count = 0;
132 	mailbox->priv->change_stamp = 0;
133 }
134 
135 /**
136  * camel_imapx_mailbox_new:
137  * @response: a #CamelIMAPXListResponse
138  * @namespace_: a #CamelIMAPXNamespace
139  *
140  * Creates a new #CamelIMAPXMailbox from @response and @namespace.
141  *
142  * The mailbox's name, path separator character, and attribute set are
143  * initialized from the #CamelIMAPXListResponse.
144  *
145  * Returns: a #CamelIMAPXMailbox
146  *
147  * Since: 3.12
148  **/
149 CamelIMAPXMailbox *
camel_imapx_mailbox_new(CamelIMAPXListResponse * response,CamelIMAPXNamespace * namespace)150 camel_imapx_mailbox_new (CamelIMAPXListResponse *response,
151                          CamelIMAPXNamespace *namespace)
152 {
153 	CamelIMAPXMailbox *mailbox;
154 	GHashTable *attributes;
155 	const gchar *name;
156 	gchar separator;
157 
158 	g_return_val_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response), NULL);
159 	g_return_val_if_fail (CAMEL_IS_IMAPX_NAMESPACE (namespace), NULL);
160 
161 	name = camel_imapx_list_response_get_mailbox_name (response);
162 	separator = camel_imapx_list_response_get_separator (response);
163 	attributes = camel_imapx_list_response_dup_attributes (response);
164 
165 	/* The INBOX mailbox is case-insensitive. */
166 	if (g_ascii_strcasecmp (name, "INBOX") == 0)
167 		name = "INBOX";
168 
169 	mailbox = g_object_new (CAMEL_TYPE_IMAPX_MAILBOX, NULL);
170 	mailbox->priv->name = g_strdup (name);
171 	mailbox->priv->separator = separator;
172 	mailbox->priv->namespace = g_object_ref (namespace);
173 	mailbox->priv->attributes = attributes;  /* takes ownership */
174 
175 	return mailbox;
176 }
177 
178 /**
179  * camel_imapx_mailbox_clone:
180  * @mailbox: a #CamelIMAPXMailbox
181  * @new_mailbox_name: new name for the cloned mailbox
182  *
183  * Creates an identical copy of @mailbox, except for the mailbox name.
184  * The copied #CamelIMAPXMailbox is given the name @new_mailbox_name.
185  *
186  * The @new_mailbox_name must be in the same IMAP namespace as @mailbox.
187  *
188  * This is primarily useful for handling mailbox renames.  It is safer to
189  * create a new #CamelIMAPXMailbox instance with the new name than to try
190  * and rename an existing #CamelIMAPXMailbox, which could disrupt mailbox
191  * operations in progress as well as data structures that track mailboxes
192  * by name.
193  *
194  * Returns: a copy of @mailbox, named @new_mailbox_name
195  *
196  * Since: 3.12
197  **/
198 CamelIMAPXMailbox *
camel_imapx_mailbox_clone(CamelIMAPXMailbox * mailbox,const gchar * new_mailbox_name)199 camel_imapx_mailbox_clone (CamelIMAPXMailbox *mailbox,
200                            const gchar *new_mailbox_name)
201 {
202 	CamelIMAPXMailbox *clone;
203 	GHashTableIter iter;
204 	gpointer key;
205 
206 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
207 	g_return_val_if_fail (new_mailbox_name != NULL, NULL);
208 
209 	/* The INBOX mailbox is case-insensitive. */
210 	if (g_ascii_strcasecmp (new_mailbox_name, "INBOX") == 0)
211 		new_mailbox_name = "INBOX";
212 
213 	clone = g_object_new (CAMEL_TYPE_IMAPX_MAILBOX, NULL);
214 	clone->priv->name = g_strdup (new_mailbox_name);
215 	clone->priv->separator = mailbox->priv->separator;
216 	clone->priv->namespace = g_object_ref (mailbox->priv->namespace);
217 
218 	clone->priv->messages = mailbox->priv->messages;
219 	clone->priv->recent = mailbox->priv->recent;
220 	clone->priv->unseen = mailbox->priv->unseen;
221 	clone->priv->uidnext = mailbox->priv->uidnext;
222 	clone->priv->uidvalidity = mailbox->priv->uidvalidity;
223 	clone->priv->highestmodseq = mailbox->priv->highestmodseq;
224 	clone->priv->state = mailbox->priv->state;
225 
226 	clone->priv->quota_roots = g_strdupv (mailbox->priv->quota_roots);
227 
228 	/* Use camel_imapx_list_response_dup_attributes()
229 	 * as a guide for cloning the mailbox attributes. */
230 
231 	clone->priv->attributes = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
232 
233 	g_mutex_lock (&mailbox->priv->property_lock);
234 
235 	g_hash_table_iter_init (&iter, mailbox->priv->attributes);
236 
237 	while (g_hash_table_iter_next (&iter, &key, NULL))
238 		g_hash_table_add (clone->priv->attributes, key);
239 
240 	g_mutex_unlock (&mailbox->priv->property_lock);
241 
242 	return clone;
243 }
244 
245 /**
246  * camel_imapx_mailbox_get_state:
247  * @mailbox: a #CamelIMAPXMailbox
248  *
249  * Returns current state of the mailbox. This is used for folder
250  * structure updates, to identify newly created, updated, renamed
251  * or removed mailboxes.
252  *
253  * Returns: Current (update) state of the mailbox.
254  *
255  * Since: 3.16
256  **/
257 CamelIMAPXMailboxState
camel_imapx_mailbox_get_state(CamelIMAPXMailbox * mailbox)258 camel_imapx_mailbox_get_state (CamelIMAPXMailbox *mailbox)
259 {
260 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN);
261 
262 	return mailbox->priv->state;
263 }
264 
265 /**
266  * camel_imapx_mailbox_set_state:
267  * @mailbox: a #CamelIMAPXMailbox
268  * @state: a new #CamelIMAPXMailboxState to set
269  *
270  * Sets current (update) state of the mailbox. This is used for folder
271  * structure updates, to identify newly created, updated, renamed
272  * or removed mailboxes.
273  *
274  * Since: 3.16
275  **/
276 void
camel_imapx_mailbox_set_state(CamelIMAPXMailbox * mailbox,CamelIMAPXMailboxState state)277 camel_imapx_mailbox_set_state (CamelIMAPXMailbox *mailbox,
278 			       CamelIMAPXMailboxState state)
279 {
280 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
281 
282 	mailbox->priv->state = state;
283 }
284 
285 /**
286  * camel_imapx_mailbox_exists:
287  * @mailbox: a #CamelIMAPXMailbox
288  *
289  * Convenience function returns whether @mailbox exists; that is, whether it
290  * <emphasis>lacks</emphasis> a #CAMEL_IMAPX_LIST_ATTR_NONEXISTENT attribute.
291  *
292  * Non-existent mailboxes should generally be disregarded.
293  *
294  * Returns: whether @mailbox exists
295  *
296  * Since: 3.12
297  **/
298 gboolean
camel_imapx_mailbox_exists(CamelIMAPXMailbox * mailbox)299 camel_imapx_mailbox_exists (CamelIMAPXMailbox *mailbox)
300 {
301 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
302 
303 	return !camel_imapx_mailbox_has_attribute (
304 		mailbox, CAMEL_IMAPX_LIST_ATTR_NONEXISTENT);
305 }
306 
307 /**
308  * camel_imapx_mailbox_compare:
309  * @mailbox_a: the first #CamelIMAPXMailbox
310  * @mailbox_b: the second #CamelIMAPXMailbox
311  *
312  * Compares two #CamelIMAPXMailbox instances by their mailbox names.
313  *
314  * Returns: a negative value if @mailbox_a compares before @mailbox_b,
315  *          zero if they compare equal, or a positive value if @mailbox_a
316  *          compares after @mailbox_b
317  *
318  * Since: 3.12
319  **/
320 gint
camel_imapx_mailbox_compare(CamelIMAPXMailbox * mailbox_a,CamelIMAPXMailbox * mailbox_b)321 camel_imapx_mailbox_compare (CamelIMAPXMailbox *mailbox_a,
322                              CamelIMAPXMailbox *mailbox_b)
323 {
324 	const gchar *mailbox_name_a;
325 	const gchar *mailbox_name_b;
326 
327 	mailbox_name_a = camel_imapx_mailbox_get_name (mailbox_a);
328 	mailbox_name_b = camel_imapx_mailbox_get_name (mailbox_b);
329 
330 	return g_strcmp0 (mailbox_name_a, mailbox_name_b);
331 }
332 
333 /**
334  * camel_imapx_mailbox_matches:
335  * @mailbox: a #CamelIMAPXMailbox
336  * @pattern: mailbox name with possible wildcards
337  *
338  * Returns %TRUE if @mailbox's name matches @pattern.  The @pattern may
339  * contain wildcard characters '*' and '%', which are interpreted similar
340  * to the IMAP LIST command.
341  *
342  * Returns: %TRUE if @mailbox's name matches @pattern, %FALSE otherwise
343  *
344  * Since: 3.12
345  **/
346 gboolean
camel_imapx_mailbox_matches(CamelIMAPXMailbox * mailbox,const gchar * pattern)347 camel_imapx_mailbox_matches (CamelIMAPXMailbox *mailbox,
348                              const gchar *pattern)
349 {
350 	const gchar *name;
351 	gchar separator;
352 	gchar name_ch;
353 	gchar patt_ch;
354 
355 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
356 	g_return_val_if_fail (pattern != NULL, FALSE);
357 
358 	name = camel_imapx_mailbox_get_name (mailbox);
359 	separator = camel_imapx_mailbox_get_separator (mailbox);
360 
361 	name_ch = *name++;
362 	patt_ch = *pattern++;
363 
364 	while (name_ch != '\0' && patt_ch != '\0') {
365 		if (name_ch == patt_ch) {
366 			name_ch = *name++;
367 			patt_ch = *pattern++;
368 		} else if (patt_ch == '%') {
369 			if (name_ch != separator)
370 				name_ch = *name++;
371 			else
372 				patt_ch = *pattern++;
373 		} else {
374 			return (patt_ch == '*');
375 		}
376 	}
377 
378 	return (name_ch == '\0') &&
379 		(patt_ch == '%' || patt_ch == '*' || patt_ch == '\0');
380 }
381 
382 /**
383  * camel_imapx_mailbox_get_name:
384  * @mailbox: a #CamelIMAPXMailbox
385  *
386  * Returns the mailbox name for @mailbox.
387  *
388  * Returns: the mailbox name
389  *
390  * Since: 3.12
391  **/
392 const gchar *
camel_imapx_mailbox_get_name(CamelIMAPXMailbox * mailbox)393 camel_imapx_mailbox_get_name (CamelIMAPXMailbox *mailbox)
394 {
395 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
396 
397 	return mailbox->priv->name;
398 }
399 
400 /**
401  * camel_imapx_mailbox_get_separator:
402  * @mailbox: a #CamelIMAPXMailbox
403  *
404  * Returns the path separator character for @mailbox.
405  *
406  * Returns: the mailbox path separator character
407  *
408  * Since: 3.12
409  **/
410 gchar
camel_imapx_mailbox_get_separator(CamelIMAPXMailbox * mailbox)411 camel_imapx_mailbox_get_separator (CamelIMAPXMailbox *mailbox)
412 {
413 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), '\0');
414 
415 	return mailbox->priv->separator;
416 }
417 
418 /**
419  * camel_imapx_mailbox_dup_folder_path:
420  * @mailbox: a #CamelIMAPXMailbox
421  *
422  * Returns the mailbox name as folder path.
423  *
424  * Returns: the mailbox name as folder path.
425  *
426  * Since: 3.16
427  **/
428 gchar *
camel_imapx_mailbox_dup_folder_path(CamelIMAPXMailbox * mailbox)429 camel_imapx_mailbox_dup_folder_path (CamelIMAPXMailbox *mailbox)
430 {
431 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
432 
433 	return camel_imapx_mailbox_to_folder_path (
434 		camel_imapx_mailbox_get_name (mailbox),
435 		camel_imapx_mailbox_get_separator (mailbox));
436 }
437 
438 /**
439  * camel_imapx_mailbox_get_namespace:
440  * @mailbox: a #CamelIMAPXMailbox
441  *
442  * Returns the #CamelIMAPXNamespace representing the IMAP server namespace
443  * to which @mailbox belongs.
444  *
445  * Returns: a #CamelIMAPXNamespace
446  *
447  * Since: 3.12
448  **/
449 CamelIMAPXNamespace *
camel_imapx_mailbox_get_namespace(CamelIMAPXMailbox * mailbox)450 camel_imapx_mailbox_get_namespace (CamelIMAPXMailbox *mailbox)
451 {
452 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
453 
454 	return mailbox->priv->namespace;
455 }
456 
457 /**
458  * camel_imapx_mailbox_get_messages:
459  * @mailbox: a #CamelIMAPXMailbox
460  *
461  * Returns the last known number of messages in the mailbox.
462  *
463  * This value should reflect the present state of the IMAP server as
464  * reported through untagged server responses in the current session.
465  *
466  * Returns: the last known "MESSAGES" value
467  *
468  * Since: 3.12
469  **/
470 guint32
camel_imapx_mailbox_get_messages(CamelIMAPXMailbox * mailbox)471 camel_imapx_mailbox_get_messages (CamelIMAPXMailbox *mailbox)
472 {
473 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
474 
475 	return mailbox->priv->messages;
476 }
477 
478 /**
479  * camel_imapx_mailbox_set_messages:
480  * @mailbox: a #CamelIMAPXMailbox
481  * @messages: a newly-reported "MESSAGES" value
482  *
483  * Updates the last known number of messages in the mailbox.
484  *
485  * This value should reflect the present state of the IMAP server as
486  * reported through untagged server responses in the current session.
487  *
488  * Since: 3.12
489  **/
490 void
camel_imapx_mailbox_set_messages(CamelIMAPXMailbox * mailbox,guint32 messages)491 camel_imapx_mailbox_set_messages (CamelIMAPXMailbox *mailbox,
492                                   guint32 messages)
493 {
494 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
495 
496 	if (mailbox->priv->messages == messages)
497 		return;
498 
499 	mailbox->priv->messages = messages;
500 
501 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
502 }
503 
504 /**
505  * camel_imapx_mailbox_get_recent:
506  * @mailbox: a #CamelIMAPXMailbox
507  *
508  * Returns the last known number of messages with the \Recent flag set.
509  *
510  * This value should reflect the present state of the IMAP server as
511  * reported through untagged server responses in the current session.
512  *
513  * Returns: the last known "RECENT" value
514  *
515  * Since: 3.12
516  **/
517 guint32
camel_imapx_mailbox_get_recent(CamelIMAPXMailbox * mailbox)518 camel_imapx_mailbox_get_recent (CamelIMAPXMailbox *mailbox)
519 {
520 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
521 
522 	return mailbox->priv->recent;
523 }
524 
525 /**
526  * camel_imapx_mailbox_set_recent:
527  * @mailbox: a #CamelIMAPXMailbox
528  * @recent: a newly-reported "RECENT" value
529  *
530  * Updates the last known number of messages with the \Recent flag set.
531  *
532  * This value should reflect the present state of the IMAP server as
533  * reported through untagged server responses in the current session.
534  *
535  * Since: 3.12
536  **/
537 void
camel_imapx_mailbox_set_recent(CamelIMAPXMailbox * mailbox,guint32 recent)538 camel_imapx_mailbox_set_recent (CamelIMAPXMailbox *mailbox,
539                                 guint32 recent)
540 {
541 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
542 
543 	if (mailbox->priv->recent == recent)
544 		return;
545 
546 	mailbox->priv->recent = recent;
547 
548 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
549 }
550 
551 /**
552  * camel_imapx_mailbox_get_unseen:
553  * @mailbox: a #CamelIMAPXMailbox
554  *
555  * Returns the last known number of messages which do not have the \Seen
556  * flag set.
557  *
558  * This value should reflect the present state of the IMAP server as
559  * reported through untagged server responses in the current session.
560  *
561  * Returns: the last known "UNSEEN" value
562  *
563  * Since: 3.12
564  **/
565 guint32
camel_imapx_mailbox_get_unseen(CamelIMAPXMailbox * mailbox)566 camel_imapx_mailbox_get_unseen (CamelIMAPXMailbox *mailbox)
567 {
568 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
569 
570 	return mailbox->priv->unseen;
571 }
572 
573 /**
574  * camel_imapx_mailbox_set_unseen:
575  * @mailbox: a #CamelIMAPXMailbox
576  * @unseen: a newly-reported "UNSEEN" value
577  *
578  * Updates the last known number of messages which do not have the \Seen
579  * flag set.
580  *
581  * This value should reflect the present state of the IMAP server as
582  * reported through untagged server responses in the current session.
583  *
584  * Since: 3.12
585  **/
586 void
camel_imapx_mailbox_set_unseen(CamelIMAPXMailbox * mailbox,guint32 unseen)587 camel_imapx_mailbox_set_unseen (CamelIMAPXMailbox *mailbox,
588                                 guint32 unseen)
589 {
590 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
591 
592 	if (mailbox->priv->unseen == unseen)
593 		return;
594 
595 	mailbox->priv->unseen = unseen;
596 
597 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
598 }
599 
600 /**
601  * camel_imapx_mailbox_get_uidnext:
602  * @mailbox: a #CamelIMAPXMailbox
603  *
604  * Returns the last known next unique identifier value of the mailbox.
605  *
606  * This value should reflect the present state of the IMAP server as
607  * reported through untagged server responses in the current session.
608  *
609  * Returns: the last known "UIDNEXT" value
610  *
611  * Since: 3.12
612  **/
613 guint32
camel_imapx_mailbox_get_uidnext(CamelIMAPXMailbox * mailbox)614 camel_imapx_mailbox_get_uidnext (CamelIMAPXMailbox *mailbox)
615 {
616 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
617 
618 	return mailbox->priv->uidnext;
619 }
620 
621 /**
622  * camel_imapx_mailbox_set_uidnext:
623  * @mailbox: a #CamelIMAPXMailbox
624  * @uidnext: a newly-reported "UIDNEXT" value
625  *
626  * Updates the last known next unique identifier value of the mailbox.
627  *
628  * This value should reflect the present state of the IMAP server as
629  * reported through untagged server responses in the current session.
630  *
631  * Since: 3.12
632  **/
633 void
camel_imapx_mailbox_set_uidnext(CamelIMAPXMailbox * mailbox,guint32 uidnext)634 camel_imapx_mailbox_set_uidnext (CamelIMAPXMailbox *mailbox,
635                                  guint32 uidnext)
636 {
637 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
638 
639 	if (mailbox->priv->uidnext == uidnext)
640 		return;
641 
642 	mailbox->priv->uidnext = uidnext;
643 
644 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
645 }
646 
647 /**
648  * camel_imapx_mailbox_get_uidvalidity:
649  * @mailbox: a #CamelIMAPXMailbox
650  *
651  * Returns the last known unique identifier validity value of the mailbox.
652  *
653  * This valud should reflect the present state of the IMAP server as
654  * reported through untagged server responses in the current session.
655  *
656  * Returns: the last known "UIDVALIDITY" value
657  *
658  * Since: 3.12
659  **/
660 guint32
camel_imapx_mailbox_get_uidvalidity(CamelIMAPXMailbox * mailbox)661 camel_imapx_mailbox_get_uidvalidity (CamelIMAPXMailbox *mailbox)
662 {
663 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
664 
665 	return mailbox->priv->uidvalidity;
666 }
667 
668 /**
669  * camel_imapx_mailbox_set_uidvalidity:
670  * @mailbox: a #CamelIMAPXMailbox
671  * @uidvalidity: a newly-reported "UIDVALIDITY" value
672  *
673  * Updates the last known unique identifier validity value of the mailbox.
674  *
675  * This value should reflect the present state of the IMAP server as
676  * reported through untagged server responses in the current session.
677  *
678  * Since: 3.12
679  **/
680 void
camel_imapx_mailbox_set_uidvalidity(CamelIMAPXMailbox * mailbox,guint32 uidvalidity)681 camel_imapx_mailbox_set_uidvalidity (CamelIMAPXMailbox *mailbox,
682                                      guint32 uidvalidity)
683 {
684 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
685 
686 	if (mailbox->priv->uidvalidity == uidvalidity)
687 		return;
688 
689 	mailbox->priv->uidvalidity = uidvalidity;
690 
691 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
692 }
693 
694 /**
695  * camel_imapx_mailbox_get_highestmodseq:
696  * @mailbox: a #CamelIMAPXMailbox
697  *
698  * Returns the last known highest mod-sequence value of all messages in the
699  * mailbox, or zero if the server does not support the persistent storage of
700  * mod-sequences for the mailbox.
701  *
702  * This value should reflect the present state of the IMAP server as
703  * reported through untagged server responses in the current session.
704  *
705  * Returns: the last known "HIGHESTMODSEQ" value
706  *
707  * Since: 3.12
708  **/
709 guint64
camel_imapx_mailbox_get_highestmodseq(CamelIMAPXMailbox * mailbox)710 camel_imapx_mailbox_get_highestmodseq (CamelIMAPXMailbox *mailbox)
711 {
712 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
713 
714 	return mailbox->priv->highestmodseq;
715 }
716 
717 /**
718  * camel_imapx_mailbox_set_highestmodseq:
719  * @mailbox: a #CamelIMAPXMailbox
720  * @highestmodseq: a newly-reported "HIGHESTMODSEQ" value
721  *
722  * Updates the last known highest mod-sequence value of all messages in
723  * the mailbox.  If the server does not support the persistent storage of
724  * mod-sequences for the mailbox then the value should remain zero.
725  *
726  * This value should reflect the present state of the IMAP server as
727  * reported through untagged server responses in the current session.
728  *
729  * Since: 3.12
730  **/
731 void
camel_imapx_mailbox_set_highestmodseq(CamelIMAPXMailbox * mailbox,guint64 highestmodseq)732 camel_imapx_mailbox_set_highestmodseq (CamelIMAPXMailbox *mailbox,
733                                        guint64 highestmodseq)
734 {
735 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
736 
737 	if (mailbox->priv->highestmodseq == highestmodseq)
738 		return;
739 
740 	mailbox->priv->highestmodseq = highestmodseq;
741 
742 	g_atomic_int_add (&mailbox->priv->change_stamp, 1);
743 }
744 
745 /**
746  * camel_imapx_mailbox_get_permanentflags:
747  * @mailbox: a #CamelIMAPXMailbox
748  *
749  * Returns: PERMANENTFLAGS response for the mailbox, or ~0, if the mailbox
750  *    was not selected yet.
751  *
752  * Since: 3.16
753  **/
754 guint32
camel_imapx_mailbox_get_permanentflags(CamelIMAPXMailbox * mailbox)755 camel_imapx_mailbox_get_permanentflags (CamelIMAPXMailbox *mailbox)
756 {
757 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), ~0);
758 
759 	return mailbox->priv->permanentflags;
760 }
761 
762 /**
763  * camel_imapx_mailbox_set_permanentflags:
764  * @mailbox: a #CamelIMAPXMailbox
765  * @permanentflags: a newly-reported "PERMANENTFLAGS" value
766  *
767  * Updates the last know value for PERMANENTFLAGS for this mailbox.
768  *
769  * Since: 3.16
770  **/
771 void
camel_imapx_mailbox_set_permanentflags(CamelIMAPXMailbox * mailbox,guint32 permanentflags)772 camel_imapx_mailbox_set_permanentflags (CamelIMAPXMailbox *mailbox,
773 					guint32 permanentflags)
774 {
775 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
776 
777 	if ((permanentflags & CAMEL_MESSAGE_USER) != 0) {
778 		permanentflags |= CAMEL_MESSAGE_JUNK;
779 		permanentflags |= CAMEL_MESSAGE_NOTJUNK;
780 	}
781 
782 	mailbox->priv->permanentflags = permanentflags;
783 }
784 
785 /**
786  * camel_imapx_mailbox_dup_quota_roots:
787  * @mailbox: a #CamelIMAPXMailbox
788  *
789  * Returns the last known list of quota roots for @mailbox as described
790  * in <ulink url="http://tools.ietf.org/html/rfc2087">RFC 2087</ulink>,
791  * or %NULL if no quota information for @mailbox is available.
792  *
793  * This value should reflect the present state of the IMAP server as
794  * reported through untagged server responses in the current session.
795  *
796  * The returned newly-allocated, %NULL-terminated string array should
797  * be freed with g_strfreev() when finished with it.
798  *
799  * Returns: the last known "QUOTAROOT" value
800  *
801  * Since: 3.12
802  **/
803 gchar **
camel_imapx_mailbox_dup_quota_roots(CamelIMAPXMailbox * mailbox)804 camel_imapx_mailbox_dup_quota_roots (CamelIMAPXMailbox *mailbox)
805 {
806 	gchar **quota_roots;
807 
808 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
809 
810 	g_mutex_lock (&mailbox->priv->property_lock);
811 
812 	quota_roots = g_strdupv (mailbox->priv->quota_roots);
813 
814 	g_mutex_unlock (&mailbox->priv->property_lock);
815 
816 	return quota_roots;
817 }
818 
819 /**
820  * camel_imapx_mailbox_set_quota_roots:
821  * @mailbox: a #CamelIMAPXMailbox
822  * @quota_roots: a newly-reported "QUOTAROOT" value
823  *
824  * Updates the last known list of quota roots for @mailbox as described
825  * in <ulink url="http://tools.ietf.org/html/rfc2087">RFC 2087</ulink>.
826  *
827  * This value should reflect the present state of the IMAP server as
828  * reported through untagged server responses in the current session.
829  *
830  * Since: 3.12
831  **/
832 void
camel_imapx_mailbox_set_quota_roots(CamelIMAPXMailbox * mailbox,const gchar ** quota_roots)833 camel_imapx_mailbox_set_quota_roots (CamelIMAPXMailbox *mailbox,
834                                      const gchar **quota_roots)
835 {
836 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
837 
838 	g_mutex_lock (&mailbox->priv->property_lock);
839 
840 	g_strfreev (mailbox->priv->quota_roots);
841 	mailbox->priv->quota_roots = g_strdupv ((gchar **) quota_roots);
842 
843 	g_mutex_unlock (&mailbox->priv->property_lock);
844 }
845 
846 /**
847  * camel_imapx_mailbox_copy_message_map:
848  * @mailbox: a #CamelIMAPXMailbox
849  *
850  * Creates a copy of @mailbox's message map: a #GSequence of 32-bit integers
851  * which map message sequence numbers (MSNs) to unique identifiers (UIDs).
852  *
853  * Free the returned #GSequence with g_sequence_free() when finished with it.
854  *
855  * Returns: a #GSequence mapping MSNs to UIDs
856  *
857  * Since: 3.12
858  **/
859 GSequence *
camel_imapx_mailbox_copy_message_map(CamelIMAPXMailbox * mailbox)860 camel_imapx_mailbox_copy_message_map (CamelIMAPXMailbox *mailbox)
861 {
862 	GSequence *copy;
863 	GSequenceIter *iter;
864 
865 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
866 
867 	copy = g_sequence_new (NULL);
868 
869 	g_mutex_lock (&mailbox->priv->property_lock);
870 
871 	iter = g_sequence_get_begin_iter (mailbox->priv->message_map);
872 
873 	while (!g_sequence_iter_is_end (iter)) {
874 		gpointer data;
875 
876 		data = g_sequence_get (iter);
877 		g_sequence_append (copy, data);
878 
879 		iter = g_sequence_iter_next (iter);
880 	}
881 
882 	g_mutex_unlock (&mailbox->priv->property_lock);
883 
884 	return copy;
885 }
886 
887 /**
888  * camel_imapx_mailbox_take_message_map:
889  * @mailbox: a #CamelIMAPXMailbox
890  * @message_map: a #GSequence mapping MSNs to UIDs
891  *
892  * Takes ownership of a #GSequence of 32-bit integers which map message
893  * sequence numbers (MSNs) to unique identifiers (UIDs) for @mailbox.
894  *
895  * The @message_map is expected to be assembled from a local cache of
896  * previously fetched UIDs.  The @mailbox will update it as untagged
897  * server responses are processed.
898  *
899  * Since: 3.12
900  **/
901 void
camel_imapx_mailbox_take_message_map(CamelIMAPXMailbox * mailbox,GSequence * message_map)902 camel_imapx_mailbox_take_message_map (CamelIMAPXMailbox *mailbox,
903                                       GSequence *message_map)
904 {
905 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
906 	g_return_if_fail (message_map != NULL);
907 
908 	g_mutex_lock (&mailbox->priv->property_lock);
909 
910 	/* XXX GSequence is not reference counted. */
911 	if (message_map != mailbox->priv->message_map) {
912 		g_sequence_free (mailbox->priv->message_map);
913 		mailbox->priv->message_map = message_map;
914 	}
915 
916 	g_mutex_unlock (&mailbox->priv->property_lock);
917 }
918 
919 /**
920  * camel_imapx_mailbox_get_msn_for_uid:
921  * @mailbox: a #CamelIMAPXMailbox
922  * @uid: a message's unique identifier
923  * @out_msn: return location for the message's sequence number, or %NULL
924  *
925  * Given a message's unique identifier (@uid), write the message's sequence
926  * number to @out_msn and return %TRUE.  If the unique identifier is unknown
927  * (as far as @mailbox has been informed), the function returns %FALSE.
928  *
929  * Returns: whether @out_msn was set
930  *
931  * Since: 3.12
932  **/
933 gboolean
camel_imapx_mailbox_get_msn_for_uid(CamelIMAPXMailbox * mailbox,guint32 uid,guint32 * out_msn)934 camel_imapx_mailbox_get_msn_for_uid (CamelIMAPXMailbox *mailbox,
935                                      guint32 uid,
936                                      guint32 *out_msn)
937 {
938 	GSequence *message_map;
939 	GSequenceIter *iter;
940 	gboolean success = FALSE;
941 
942 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
943 
944 	/* Remember: Message sequence numbers start at 1.
945 	 *           GSequence position numbers start at 0. */
946 
947 	g_mutex_lock (&mailbox->priv->property_lock);
948 
949 	message_map = mailbox->priv->message_map;
950 	iter = g_sequence_lookup (
951 		message_map, GUINT_TO_POINTER (uid),
952 		imapx_mailbox_message_map_compare, NULL);
953 
954 	if (iter != NULL) {
955 		if (out_msn != NULL)
956 			*out_msn = g_sequence_iter_get_position (iter) + 1;
957 		success = TRUE;
958 	}
959 
960 	g_mutex_unlock (&mailbox->priv->property_lock);
961 
962 	return success;
963 }
964 
965 /**
966  * camel_imapx_mailbox_get_uid_for_msn:
967  * @mailbox: a #CamelIMAPXMailbox
968  * @msn: a message's sequence number (1..n)
969  * @out_uid: return location for the message's unique identifier, or %NULL
970  *
971  * Given a message's sequence number (@msn), write the message's unique
972  * identifier to @out_uid and return %TRUE.  If the sequence number is out of
973  * range (as far as @mailbox has been informed), the function returns %FALSE.
974  *
975  * Returns: whether @out_uid was set
976  *
977  * Since: 3.12
978  **/
979 gboolean
camel_imapx_mailbox_get_uid_for_msn(CamelIMAPXMailbox * mailbox,guint32 msn,guint32 * out_uid)980 camel_imapx_mailbox_get_uid_for_msn (CamelIMAPXMailbox *mailbox,
981                                      guint32 msn,
982                                      guint32 *out_uid)
983 {
984 	GSequence *message_map;
985 	GSequenceIter *iter;
986 	gboolean success = FALSE;
987 
988 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
989 
990 	/* Remember: Message sequence numbers start at 1.
991 	 *           GSequence position numbers start at 0. */
992 
993 	if (msn == 0)
994 		return FALSE;
995 
996 	g_mutex_lock (&mailbox->priv->property_lock);
997 
998 	message_map = mailbox->priv->message_map;
999 	iter = g_sequence_get_iter_at_pos (message_map, msn - 1);
1000 
1001 	if (!g_sequence_iter_is_end (iter)) {
1002 		if (out_uid != NULL) {
1003 			gpointer data = g_sequence_get (iter);
1004 			*out_uid = GPOINTER_TO_UINT (data);
1005 		}
1006 		success = TRUE;
1007 	}
1008 
1009 	g_mutex_unlock (&mailbox->priv->property_lock);
1010 
1011 	return success;
1012 }
1013 
1014 /**
1015  * camel_imapx_mailbox_deleted:
1016  * @mailbox: a #CamelIMAPXMailbox
1017  *
1018  * Adds the #CAMEL_IMAPX_LIST_ATTR_NONEXISTENT attribute to @mailbox.
1019  *
1020  * Call this function after successfully completing a DELETE command.
1021  *
1022  * Since: 3.12
1023  **/
1024 void
camel_imapx_mailbox_deleted(CamelIMAPXMailbox * mailbox)1025 camel_imapx_mailbox_deleted (CamelIMAPXMailbox *mailbox)
1026 {
1027 	const gchar *attribute;
1028 
1029 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1030 
1031 	attribute = CAMEL_IMAPX_LIST_ATTR_NONEXISTENT;
1032 
1033 	g_mutex_lock (&mailbox->priv->property_lock);
1034 
1035 	g_hash_table_add (
1036 		mailbox->priv->attributes,
1037 		(gpointer) g_intern_string (attribute));
1038 
1039 	g_mutex_unlock (&mailbox->priv->property_lock);
1040 }
1041 
1042 /**
1043  * camel_imapx_mailbox_subscribed:
1044  * @mailbox: a #CamelIMAPXMailbox
1045  *
1046  * Add the #CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED attribute to @mailbox.
1047  *
1048  * Call this function after successfully completing a SUBSCRIBE command.
1049  *
1050  * Since: 3.12
1051  **/
1052 void
camel_imapx_mailbox_subscribed(CamelIMAPXMailbox * mailbox)1053 camel_imapx_mailbox_subscribed (CamelIMAPXMailbox *mailbox)
1054 {
1055 	const gchar *attribute;
1056 
1057 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1058 
1059 	attribute = CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED;
1060 
1061 	g_mutex_lock (&mailbox->priv->property_lock);
1062 
1063 	g_hash_table_add (
1064 		mailbox->priv->attributes,
1065 		(gpointer) g_intern_string (attribute));
1066 
1067 	g_mutex_unlock (&mailbox->priv->property_lock);
1068 }
1069 
1070 /**
1071  * camel_imapx_mailbox_unsubscribed:
1072  * @mailbox: a #CamelIMAPXMailbox
1073  *
1074  * Removes the #CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED attribute from @mailbox.
1075  *
1076  * Call this function after successfully completing an UNSUBSCRIBE command.
1077  *
1078  * Since: 3.12
1079  **/
1080 void
camel_imapx_mailbox_unsubscribed(CamelIMAPXMailbox * mailbox)1081 camel_imapx_mailbox_unsubscribed (CamelIMAPXMailbox *mailbox)
1082 {
1083 	const gchar *attribute;
1084 
1085 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1086 
1087 	attribute = CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED;
1088 
1089 	g_mutex_lock (&mailbox->priv->property_lock);
1090 
1091 	g_hash_table_remove (mailbox->priv->attributes, attribute);
1092 
1093 	g_mutex_unlock (&mailbox->priv->property_lock);
1094 }
1095 
1096 /**
1097  * camel_imapx_mailbox_has_attribute:
1098  * @mailbox: a #CamelIMAPXMailbox
1099  * @attribute: a mailbox attribute
1100  *
1101  * Returns whether @mailbox includes the given mailbox attribute.
1102  * The @attribute should be one of the LIST attribute macros defined
1103  * for #CamelIMAPXListResponse.
1104  *
1105  * Returns: %TRUE if @mailbox has @attribute, or else %FALSE
1106  *
1107  * Since: 3.12
1108  **/
1109 gboolean
camel_imapx_mailbox_has_attribute(CamelIMAPXMailbox * mailbox,const gchar * attribute)1110 camel_imapx_mailbox_has_attribute (CamelIMAPXMailbox *mailbox,
1111                                    const gchar *attribute)
1112 {
1113 	gboolean has_it;
1114 
1115 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
1116 	g_return_val_if_fail (attribute != NULL, FALSE);
1117 
1118 	g_mutex_lock (&mailbox->priv->property_lock);
1119 
1120 	has_it = g_hash_table_contains (mailbox->priv->attributes, attribute);
1121 
1122 	g_mutex_unlock (&mailbox->priv->property_lock);
1123 
1124 	return has_it;
1125 }
1126 
1127 /**
1128  * camel_imapx_mailbox_handle_list_response:
1129  * @mailbox: a #CamelIMAPXMailbox
1130  * @response: a #CamelIMAPXListResponse
1131  *
1132  * Updates the internal state of @mailbox from the data in @response.
1133  *
1134  * Since: 3.12
1135  **/
1136 void
camel_imapx_mailbox_handle_list_response(CamelIMAPXMailbox * mailbox,CamelIMAPXListResponse * response)1137 camel_imapx_mailbox_handle_list_response (CamelIMAPXMailbox *mailbox,
1138                                           CamelIMAPXListResponse *response)
1139 {
1140 	GHashTable *attributes;
1141 
1142 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1143 	g_return_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response));
1144 
1145 	attributes = camel_imapx_list_response_dup_attributes (response);
1146 
1147 	g_mutex_lock (&mailbox->priv->property_lock);
1148 
1149 	g_hash_table_destroy (mailbox->priv->attributes);
1150 	mailbox->priv->attributes = attributes;  /* takes ownership */
1151 
1152 	g_mutex_unlock (&mailbox->priv->property_lock);
1153 }
1154 
1155 /**
1156  * camel_imapx_mailbox_handle_lsub_response:
1157  * @mailbox: a #CamelIMAPXMailbox
1158  * @response: a #CamelIMAPXListResponse
1159  *
1160  * Updates the internal state of @mailbox from the data in @response.
1161  *
1162  * Since: 3.12
1163  **/
1164 void
camel_imapx_mailbox_handle_lsub_response(CamelIMAPXMailbox * mailbox,CamelIMAPXListResponse * response)1165 camel_imapx_mailbox_handle_lsub_response (CamelIMAPXMailbox *mailbox,
1166                                           CamelIMAPXListResponse *response)
1167 {
1168 	GHashTable *attributes;
1169 	GHashTableIter iter;
1170 	gpointer key;
1171 
1172 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1173 	g_return_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response));
1174 
1175 	/* LIST responses are more authoritative than LSUB responses,
1176 	 * so instead of replacing the old attribute set as we would
1177 	 * for a LIST response, we'll merge the LSUB attributes. */
1178 
1179 	attributes = camel_imapx_list_response_dup_attributes (response);
1180 
1181 	g_hash_table_iter_init (&iter, attributes);
1182 
1183 	g_mutex_lock (&mailbox->priv->property_lock);
1184 
1185 	while (g_hash_table_iter_next (&iter, &key, NULL))
1186 		g_hash_table_add (mailbox->priv->attributes, key);
1187 
1188 	g_mutex_unlock (&mailbox->priv->property_lock);
1189 
1190 	g_hash_table_destroy (attributes);
1191 }
1192 
1193 /**
1194  * camel_imapx_mailbox_handle_status_response:
1195  * @mailbox: a #CamelIMAPXMailbox
1196  * @response: a #CamelIMAPXStatusResponse
1197  *
1198  * Updates the internal state of @mailbox from the data in @response.
1199  *
1200  * Since: 3.12
1201  **/
1202 void
camel_imapx_mailbox_handle_status_response(CamelIMAPXMailbox * mailbox,CamelIMAPXStatusResponse * response)1203 camel_imapx_mailbox_handle_status_response (CamelIMAPXMailbox *mailbox,
1204                                             CamelIMAPXStatusResponse *response)
1205 {
1206 	guint32 value32;
1207 	guint64 value64;
1208 
1209 	g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1210 	g_return_if_fail (CAMEL_IS_IMAPX_STATUS_RESPONSE (response));
1211 
1212 	if (camel_imapx_status_response_get_messages (response, &value32))
1213 		camel_imapx_mailbox_set_messages (mailbox, value32);
1214 
1215 	if (camel_imapx_status_response_get_recent (response, &value32))
1216 		camel_imapx_mailbox_set_recent (mailbox, value32);
1217 
1218 	if (camel_imapx_status_response_get_unseen (response, &value32))
1219 		camel_imapx_mailbox_set_unseen (mailbox, value32);
1220 
1221 	if (camel_imapx_status_response_get_uidnext (response, &value32))
1222 		camel_imapx_mailbox_set_uidnext (mailbox, value32);
1223 
1224 	if (camel_imapx_status_response_get_uidvalidity (response, &value32))
1225 		camel_imapx_mailbox_set_uidvalidity (mailbox, value32);
1226 
1227 	if (camel_imapx_status_response_get_highestmodseq (response, &value64))
1228 		camel_imapx_mailbox_set_highestmodseq (mailbox, value64);
1229 }
1230 
1231 gint
camel_imapx_mailbox_get_update_count(CamelIMAPXMailbox * mailbox)1232 camel_imapx_mailbox_get_update_count (CamelIMAPXMailbox *mailbox)
1233 {
1234 	gint res;
1235 
1236 	g_mutex_lock (&mailbox->priv->update_lock);
1237 	res = mailbox->priv->update_count;
1238 	g_mutex_unlock (&mailbox->priv->update_lock);
1239 
1240 	return res;
1241 }
1242 
1243 void
camel_imapx_mailbox_inc_update_count(CamelIMAPXMailbox * mailbox,gint inc)1244 camel_imapx_mailbox_inc_update_count (CamelIMAPXMailbox *mailbox,
1245 				      gint inc)
1246 {
1247 	g_mutex_lock (&mailbox->priv->update_lock);
1248 	mailbox->priv->update_count += inc;
1249 	g_mutex_unlock (&mailbox->priv->update_lock);
1250 }
1251 
1252 gint
camel_imapx_mailbox_get_change_stamp(CamelIMAPXMailbox * mailbox)1253 camel_imapx_mailbox_get_change_stamp (CamelIMAPXMailbox *mailbox)
1254 {
1255 	g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), 0);
1256 
1257 	return mailbox->priv->change_stamp;
1258 }
1259