1
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
8
#include "dsync-mailbox-state.h"
10
#define MAILBOX_SIZE (GUID_128_SIZE + 4 + 4 + 8 + 8)
12
static void put_uint32(buffer_t *output, uint32_t num)
14
buffer_append_c(output, num & 0xff);
15
buffer_append_c(output, (num >> 8) & 0xff);
16
buffer_append_c(output, (num >> 16) & 0xff);
17
buffer_append_c(output, (num >> 24) & 0xff);
20
static uint32_t get_uint32(const unsigned char *data)
22
return data[0] | (data[1] << 8) | (data[2] << 16) |
23
((unsigned int)data[3] << 24);
26
void dsync_mailbox_states_export(const HASH_TABLE_TYPE(dsync_mailbox_state) states,
29
struct hash_iterate_context *iter;
30
struct dsync_mailbox_state *state;
32
buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 128);
35
iter = hash_table_iterate_init(states);
36
while (hash_table_iterate(iter, states, &guid, &state)) {
37
buffer_append(buf, state->mailbox_guid,
38
sizeof(state->mailbox_guid));
39
put_uint32(buf, state->last_uidvalidity);
40
put_uint32(buf, state->last_common_uid);
41
put_uint32(buf, state->last_common_modseq & 0xffffffffU);
42
put_uint32(buf, state->last_common_modseq >> 32);
43
put_uint32(buf, state->last_common_pvt_modseq & 0xffffffffU);
44
put_uint32(buf, state->last_common_pvt_modseq >> 32);
45
if (buf->used % 3 == 0) {
46
crc = crc32_data_more(crc, buf->data, buf->used);
47
base64_encode(buf->data, buf->used, output);
48
buffer_set_used_size(buf, 0);
51
hash_table_iterate_deinit(&iter);
53
crc = crc32_data_more(crc, buf->data, buf->used);
55
base64_encode(buf->data, buf->used, output);
58
int dsync_mailbox_states_import(HASH_TABLE_TYPE(dsync_mailbox_state) states,
59
pool_t pool, const char *input,
62
struct dsync_mailbox_state *state;
65
const unsigned char *data;
67
unsigned int i, count;
69
buf = buffer_create_dynamic(pool_datastack_create(), strlen(input));
70
if (base64_decode(input, strlen(input), &pos, buf) < 0) {
71
*error_r = "Invalid base64 data";
75
*error_r = "Input too small";
78
if ((buf->used-4) % MAILBOX_SIZE != 0) {
79
*error_r = "Invalid input size";
83
count = (buf->used-4) / MAILBOX_SIZE;
85
if (get_uint32(data + buf->used-4) != crc32_data(data, buf->used-4)) {
86
*error_r = "CRC32 mismatch";
90
for (i = 0; i < count; i++, data += MAILBOX_SIZE) {
91
state = p_new(pool, struct dsync_mailbox_state, 1);
92
memcpy(state->mailbox_guid, data, GUID_128_SIZE);
93
state->last_uidvalidity = get_uint32(data + GUID_128_SIZE);
94
state->last_common_uid = get_uint32(data + GUID_128_SIZE + 4);
95
state->last_common_modseq =
96
get_uint32(data + GUID_128_SIZE + 8) |
97
(uint64_t)get_uint32(data + GUID_128_SIZE + 12) << 32;
98
state->last_common_pvt_modseq =
99
get_uint32(data + GUID_128_SIZE + 16) |
100
(uint64_t)get_uint32(data + GUID_128_SIZE + 20) << 32;
101
guid_p = state->mailbox_guid;
102
hash_table_insert(states, guid_p, state);