1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "mail-storage-private.h"
5 #include "mailbox-recent-flags.h"
6 
mailbox_recent_flags_set_uid(struct mailbox * box,uint32_t uid)7 void mailbox_recent_flags_set_uid(struct mailbox *box, uint32_t uid)
8 {
9 	if (uid <= box->recent_flags_prev_uid) {
10 		if (seq_range_exists(&box->recent_flags, uid))
11 			return;
12 
13 		mailbox_set_critical(box, "Recent flags state corrupted");
14 		array_clear(&box->recent_flags);
15 		box->recent_flags_count = 0;
16 	}
17 	mailbox_recent_flags_set_uid_forced(box, uid);
18 }
19 
mailbox_recent_flags_set_uid_forced(struct mailbox * box,uint32_t uid)20 void mailbox_recent_flags_set_uid_forced(struct mailbox *box, uint32_t uid)
21 {
22 	box->recent_flags_prev_uid = uid;
23 
24 	if (!mailbox_recent_flags_have_uid(box, uid)) {
25 		seq_range_array_add_with_init(&box->recent_flags, 64, uid);
26 		box->recent_flags_count++;
27 	}
28 }
29 
mailbox_recent_flags_set_seqs(struct mailbox * box,struct mail_index_view * view,uint32_t seq1,uint32_t seq2)30 void mailbox_recent_flags_set_seqs(struct mailbox *box,
31 				   struct mail_index_view *view,
32 				   uint32_t seq1, uint32_t seq2)
33 {
34 	uint32_t uid;
35 
36 	for (; seq1 <= seq2; seq1++) {
37 		mail_index_lookup_uid(view, seq1, &uid);
38 		mailbox_recent_flags_set_uid(box, uid);
39 	}
40 }
41 
mailbox_recent_flags_have_uid(struct mailbox * box,uint32_t uid)42 bool mailbox_recent_flags_have_uid(struct mailbox *box, uint32_t uid)
43 {
44 	return array_is_created(&box->recent_flags) &&
45 		seq_range_exists(&box->recent_flags, uid);
46 }
47 
mailbox_recent_flags_reset(struct mailbox * box)48 void mailbox_recent_flags_reset(struct mailbox *box)
49 {
50 	if (array_is_created(&box->recent_flags))
51 		array_clear(&box->recent_flags);
52 	box->recent_flags_count = 0;
53 	box->recent_flags_prev_uid = 0;
54 }
55 
mailbox_recent_flags_count(struct mailbox * box)56 unsigned int mailbox_recent_flags_count(struct mailbox *box)
57 {
58 	const struct mail_index_header *hdr;
59 	const struct seq_range *range;
60 	unsigned int i, count, recent_count;
61 
62 	if (!array_is_created(&box->recent_flags))
63 		return 0;
64 
65 	hdr = mail_index_get_header(box->view);
66 	recent_count = box->recent_flags_count;
67 	range = array_get(&box->recent_flags, &count);
68 	for (i = count; i > 0; ) {
69 		i--;
70 		if (range[i].seq2 < hdr->next_uid)
71 			break;
72 
73 		if (range[i].seq1 >= hdr->next_uid) {
74 			/* completely invisible to this view */
75 			recent_count -= range[i].seq2 - range[i].seq1 + 1;
76 		} else {
77 			/* partially invisible */
78 			recent_count -= range[i].seq2 - hdr->next_uid + 1;
79 			break;
80 		}
81 	}
82 	return recent_count;
83 }
84 
mailbox_recent_flags_expunge_seqs(struct mailbox * box,uint32_t seq1,uint32_t seq2)85 void mailbox_recent_flags_expunge_seqs(struct mailbox *box,
86 				       uint32_t seq1, uint32_t seq2)
87 {
88 	uint32_t uid;
89 
90 	if (!array_is_created(&box->recent_flags))
91 		return;
92 
93 	for (; seq1 <= seq2; seq1++) {
94 		mail_index_lookup_uid(box->view, seq1, &uid);
95 		if (seq_range_array_remove(&box->recent_flags, uid))
96 			box->recent_flags_count--;
97 	}
98 }
99 
mailbox_recent_flags_expunge_uid(struct mailbox * box,uint32_t uid)100 void mailbox_recent_flags_expunge_uid(struct mailbox *box, uint32_t uid)
101 {
102 	if (array_is_created(&box->recent_flags)) {
103 		if (seq_range_array_remove(&box->recent_flags, uid))
104 			box->recent_flags_count--;
105 	}
106 }
107