# Don't replace messages on the replica if one or both of the UUIDs is NULL. # Also fixes a silly bug in find_reserve_messages(): sync_client will have # been missing some messages on the server which could be RESERVEd and then # copied by reference (UPLOAD COPY) rather than value (UPLOAD PARSED). # Index: imap/sync_client.c =================================================================== RCS file: /cvs/src/cyrus/imap/sync_client.c,v retrieving revision 1.17 diff -u -d -r1.17 sync_client.c --- imap/sync_client.c 12 Sep 2007 15:51:04 -0000 1.17 +++ imap/sync_client.c 13 Sep 2007 15:11:21 -0000 @@ -228,10 +228,14 @@ return(IMAP_IOERROR); } - if (msg && ((msg->uid < record.uid) || - ((msg->uid == record.uid) && - message_uuid_compare(&msg->uuid, &record.uuid)))) { + /* Skip over messages recorded on server which are missing on client + * (either will be expunged or have been expunged already) */ + while (msg && (record.uid > msg->uid)) msg = msg->next; + + if (msg && (record.uid == msg->uid) && + message_uuid_compare_allow_null(&record.uuid, &msg->uuid)) { + msg = msg->next; /* Ignore exact match */ continue; } @@ -1106,7 +1110,7 @@ msg = msg->next; if (msg && (record.uid == msg->uid) && - message_uuid_compare(&record.uuid, &msg->uuid)) { + message_uuid_compare_allow_null(&record.uuid, &msg->uuid)) { msg = msg->next; /* Ignore exact match */ continue; } @@ -1251,7 +1255,7 @@ msg = msg->next; if (msg && (record.uid == msg->uid) && - message_uuid_compare(&record.uuid, &msg->uuid)) { + message_uuid_compare_allow_null(&record.uuid, &msg->uuid)) { msg = msg->next; /* Ignore exact match */ continue; } Index: lib/message_uuid.c =================================================================== RCS file: /cvs/src/cyrus/lib/message_uuid.c,v retrieving revision 1.2 diff -u -d -r1.2 message_uuid.c --- lib/message_uuid.c 30 Nov 2006 17:11:22 -0000 1.2 +++ lib/message_uuid.c 13 Sep 2007 15:11:21 -0000 @@ -297,7 +297,7 @@ /* message_uuid_compare() ************************************************ * - * Compare a pair of UUIDs: Returns 1 => match + * Compare a pair of UUIDs: Returns 1 => match. NULL UUIDs do not match. * ************************************************************************/ @@ -308,6 +308,34 @@ unsigned char *t = &uuid2->value[0]; int i; + /* Refuse to match NULL UUIDs: message could be anything */ + if (message_uuid_isnull(uuid1) || message_uuid_isnull(uuid2)) + return(0); + + for (i = 0; i < MESSAGE_UUID_SIZE; i++) { + if (s[i] != t[i]) return(0); + } + return(1); +} + +/* message_uuid_compare_allow_null() ************************************* + * + * Compare a pair of UUIDs: Returns 1 => match. NULL UUIDs match anything. + * + ************************************************************************/ + +int +message_uuid_compare_allow_null(struct message_uuid *uuid1, + struct message_uuid *uuid2) +{ + unsigned char *s = &uuid1->value[0]; + unsigned char *t = &uuid2->value[0]; + int i; + + /* Match if either UUID is NULL, trust caller knows what they are doing */ + if (message_uuid_isnull(uuid1) || message_uuid_isnull(uuid2)) + return(1); + for (i = 0; i < MESSAGE_UUID_SIZE; i++) { if (s[i] != t[i]) return(0); } Index: lib/message_uuid.h =================================================================== RCS file: /cvs/src/cyrus/lib/message_uuid.h,v retrieving revision 1.2 diff -u -d -r1.2 message_uuid.h --- lib/message_uuid.h 30 Nov 2006 17:11:22 -0000 1.2 +++ lib/message_uuid.h 13 Sep 2007 15:11:21 -0000 @@ -31,7 +31,12 @@ int message_uuid_compare(struct message_uuid *uuid1, struct message_uuid *uuid2); - /* Compare a pair of UUIDs: Returns 1 => match */ + /* Compare a pair of UUIDs: Returns 1 => match. NULL UUIDs do not match. */ + +int +message_uuid_compare_allow_null(struct message_uuid *uuid1, + struct message_uuid *uuid2); + /* Compare a pair of UUIDs: Returns 1 => match. NULL UUIDs match anything */ int message_uuid_copy(struct message_uuid *dst, struct message_uuid *src);