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