1 #ifndef DSYNC_MAILBOX_TREE_H
2 #define DSYNC_MAILBOX_TREE_H
3 
4 #include "guid.h"
5 #include "mail-error.h"
6 
7 struct mail_namespace;
8 struct dsync_brain;
9 
10 enum dsync_mailbox_trees_sync_type {
11 	/* two-way sync for both mailboxes */
12 	DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY,
13 	/* make remote tree look exactly like the local tree */
14 	DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL,
15 	/* make local tree look exactly like the remote tree */
16 	DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE
17 };
18 
19 enum dsync_mailbox_trees_sync_flags {
20 	/* Enable debugging */
21 	DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG		= 0x01,
22 	/* Show ourself as "master brain" in the debug output */
23 	DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN	= 0x02,
24 	/* Disable mailbox renaming logic. This is just a kludge that should
25 	   be removed once the renaming logic has no more bugs.. */
26 	DSYNC_MAILBOX_TREES_SYNC_FLAG_NO_RENAMES	= 0x04
27 };
28 
29 enum dsync_mailbox_node_existence {
30 	/* this is just a filler node for children or for
31 	   subscription deletion */
32 	DSYNC_MAILBOX_NODE_NONEXISTENT = 0,
33 	/* if mailbox GUID is set, the mailbox exists.
34 	   otherwise the directory exists. */
35 	DSYNC_MAILBOX_NODE_EXISTS,
36 	/* if mailbox GUID is set, the mailbox has been deleted.
37 	   otherwise the directory has been deleted. */
38 	DSYNC_MAILBOX_NODE_DELETED
39 };
40 
41 struct dsync_mailbox_node {
42 	struct dsync_mailbox_node *parent, *next, *first_child;
43 
44 	/* namespace where this node belongs to */
45 	struct mail_namespace *ns;
46 	/* this node's name (not including parents) */
47 	const char *name;
48 	/* mailbox GUID, or full of zeros if this is about a directory name */
49 	guid_128_t mailbox_guid;
50 	/* mailbox's UIDVALIDITY/UIDNEXT (may be 0 if not assigned yet) */
51 	uint32_t uid_validity, uid_next;
52 
53 	/* existence of this mailbox/directory.
54 	   doesn't affect subscription state. */
55 	enum dsync_mailbox_node_existence existence;
56 	/* last time the mailbox/directory was created/renamed,
57 	   0 if not known */
58 	time_t last_renamed_or_created;
59 
60 	/* last time the subscription state was changed, 0 if not known */
61 	time_t last_subscription_change;
62 	/* is this mailbox or directory subscribed? */
63 	bool subscribed:1;
64 
65 	/* Internal syncing flags: */
66 	bool sync_delayed_guid_change:1;
67 	bool sync_temporary_name:1;
68 };
69 ARRAY_DEFINE_TYPE(dsync_mailbox_node, struct dsync_mailbox_node *);
70 
71 #define dsync_mailbox_node_guids_equal(node1, node2) \
72 	(memcmp((node1)->mailbox_guid, (node2)->mailbox_guid, \
73 		sizeof(guid_128_t)) == 0)
74 
75 #define dsync_mailbox_node_is_dir(node) \
76 	guid_128_is_empty((node)->mailbox_guid)
77 
78 enum dsync_mailbox_delete_type {
79 	/* Delete mailbox by given GUID */
80 	DSYNC_MAILBOX_DELETE_TYPE_MAILBOX = 1,
81 	/* Delete mailbox directory by given SHA1 name */
82 	DSYNC_MAILBOX_DELETE_TYPE_DIR,
83 	/* Unsubscribe mailbox by given SHA1 name */
84 	DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE,
85 };
86 
87 struct dsync_mailbox_delete {
88 	enum dsync_mailbox_delete_type type;
89 	guid_128_t guid;
90 	time_t timestamp;
91 };
92 
93 enum dsync_mailbox_tree_sync_type {
94 	DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_BOX,
95 	DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_DIR,
96 	DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX,
97 	DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR,
98 	/* Rename given mailbox name and its children */
99 	DSYNC_MAILBOX_TREE_SYNC_TYPE_RENAME,
100 	DSYNC_MAILBOX_TREE_SYNC_TYPE_SUBSCRIBE,
101 	DSYNC_MAILBOX_TREE_SYNC_TYPE_UNSUBSCRIBE
102 };
103 
104 struct dsync_mailbox_tree_sync_change {
105 	enum dsync_mailbox_tree_sync_type type;
106 
107 	/* for all types: */
108 	struct mail_namespace *ns;
109 	const char *full_name;
110 
111 	/* for create_box and delete_box: */
112 	guid_128_t mailbox_guid;
113 	/* for create_box: */
114 	uint32_t uid_validity;
115 	/* for rename: */
116 	const char *rename_dest_name;
117 };
118 
119 struct dsync_mailbox_tree *dsync_mailbox_tree_init(char sep, char alt_char);
120 void dsync_mailbox_tree_deinit(struct dsync_mailbox_tree **tree);
121 
122 /* Lookup a mailbox node by name. Returns NULL if not known. */
123 struct dsync_mailbox_node *
124 dsync_mailbox_tree_lookup(struct dsync_mailbox_tree *tree,
125 			  const char *full_name);
126 /* Lookup a mailbox node by GUID. Returns NULL if not known.
127    The mailbox GUID hash must have been build before calling this. */
128 struct dsync_mailbox_node *
129 dsync_mailbox_tree_lookup_guid(struct dsync_mailbox_tree *tree,
130 			       const guid_128_t guid);
131 /* Lookup or create a mailbox node by name. */
132 struct dsync_mailbox_node *
133 dsync_mailbox_tree_get(struct dsync_mailbox_tree *tree, const char *full_name);
134 
135 /* Returns full name for the given mailbox node. */
136 const char *dsync_mailbox_node_get_full_name(const struct dsync_mailbox_tree *tree,
137 					     const struct dsync_mailbox_node *node);
138 void dsync_mailbox_node_append_full_name(string_t *str,
139 					 const struct dsync_mailbox_tree *tree,
140 					 const struct dsync_mailbox_node *node);
141 
142 /* Copy everything from src to dest, except name and hierarchy pointers */
143 void dsync_mailbox_node_copy_data(struct dsync_mailbox_node *dest,
144 				  const struct dsync_mailbox_node *src);
145 
146 /* Add nodes to tree from the given namespace. If box_name or box_guid is
147    non-NULL, add only that mailbox to the tree. */
148 int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
149 			    struct mail_namespace *ns, const char *box_name,
150 			    const guid_128_t box_guid,
151 			    const char *const *exclude_mailboxes,
152 			    enum mail_error *error_r);
153 
154 /* Return all known deleted mailboxes and directories. */
155 const struct dsync_mailbox_delete *
156 dsync_mailbox_tree_get_deletes(struct dsync_mailbox_tree *tree,
157 			       unsigned int *count_r);
158 /* Return mailbox node for a given delete record, or NULL if it doesn't exist.
159    The delete record is intended to come from another tree, possibly with
160    a different hierarchy separator. dsync_mailbox_tree_build_guid_hash() must
161    have been called before this. */
162 struct dsync_mailbox_node *
163 dsync_mailbox_tree_find_delete(struct dsync_mailbox_tree *tree,
164 			       const struct dsync_mailbox_delete *del);
165 /* Build GUID lookup hash, if it's not already built. Returns 0 if ok, -1 if
166    there are duplicate GUIDs. The nodes with the duplicate GUIDs are
167    returned. */
168 int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree,
169 				       struct dsync_mailbox_node **dup_node1_r,
170 				       struct dsync_mailbox_node **dup_node2_r);
171 /* Manually add a new node to hash. */
172 int dsync_mailbox_tree_guid_hash_add(struct dsync_mailbox_tree *tree,
173 				     struct dsync_mailbox_node *node,
174 				     struct dsync_mailbox_node **old_node_r);
175 /* Set remote separator used for directory deletions in
176    dsync_mailbox_tree_find_delete() */
177 void dsync_mailbox_tree_set_remote_sep(struct dsync_mailbox_tree *tree,
178 				       char remote_sep);
179 
180 /* Iterate through all nodes in a tree (depth-first) */
181 struct dsync_mailbox_tree_iter *
182 dsync_mailbox_tree_iter_init(struct dsync_mailbox_tree *tree);
183 bool dsync_mailbox_tree_iter_next(struct dsync_mailbox_tree_iter *iter,
184 				  const char **full_name_r,
185 				  struct dsync_mailbox_node **node_r);
186 void dsync_mailbox_tree_iter_deinit(struct dsync_mailbox_tree_iter **iter);
187 
188 /* Sync local and remote trees so at the end they're exactly the same.
189    Return changes done to local tree. */
190 struct dsync_mailbox_tree_sync_ctx *
191 dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
192 			      struct dsync_mailbox_tree *remote_tree,
193 			      enum dsync_mailbox_trees_sync_type sync_type,
194 			      enum dsync_mailbox_trees_sync_flags sync_flags);
195 const struct dsync_mailbox_tree_sync_change *
196 dsync_mailbox_trees_sync_next(struct dsync_mailbox_tree_sync_ctx *ctx);
197 int dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **ctx);
198 
199 const char *dsync_mailbox_node_to_string(const struct dsync_mailbox_node *node);
200 const char *
201 dsync_mailbox_delete_type_to_string(enum dsync_mailbox_delete_type type);
202 
203 #endif
204