]>
Commit | Line | Data |
---|---|---|
b40388bb MT |
1 | # Small patch to Cyrus IMAP 2.2.12 which modifies \Seen state handling to |
2 | # make it compatible with Outlook Express. OE makes two connections to a | |
3 | # given mailfolder: one generates indexes while the other fetches messages. | |
4 | # Unfortunately it gets confused if \Seen updates caused by the message | |
5 | # stream aren't immediately flushed and picked up by the index stream. | |
6 | # | |
7 | # Apparently Mozilla Thunderbird has the same problem. | |
8 | # | |
9 | # This patch is a 2.2.12 port from the patch found here: | |
10 | # http://www-uxsup.csx.cam.ac.uk/~dpc22/cyrus/patches/2.1.16/seenstate.patch | |
11 | # | |
12 | diff -Naur cyrus-imapd-2.2.12.orig/imap/imapd.c cyrus-imapd-2.2.12/imap/imapd.c | |
13 | --- cyrus-imapd-2.2.12.orig/imap/imapd.c 2005-02-14 07:39:55.000000000 +0100 | |
14 | +++ cyrus-imapd-2.2.12/imap/imapd.c 2006-01-04 07:41:45.000000000 +0100 | |
15 | @@ -3095,6 +3095,10 @@ | |
16 | snprintf(mytime, sizeof(mytime), "%2.3f", | |
17 | (clock() - start) / (double) CLOCKS_PER_SEC); | |
18 | ||
19 | + /* Checkpoint \Seen immediately after each FETCH completes. Checks for | |
20 | + * changes from other processes at the same time */ | |
21 | + index_check_existing(imapd_mailbox, usinguid, 1); | |
22 | + | |
23 | if (r) { | |
24 | prot_printf(imapd_out, "%s NO %s (%s sec)\r\n", tag, | |
25 | error_message(r), mytime); | |
26 | @@ -3219,7 +3223,8 @@ | |
27 | ||
28 | index_fetch(imapd_mailbox, msgno, 0, &fetchargs, &fetchedsomething); | |
29 | ||
30 | - index_check(imapd_mailbox, 0, 0); | |
31 | + /* Vanilla index_check() can generate illegal EXPUNGE events */ | |
32 | + index_check_existing(imapd_mailbox, 0, 1); | |
33 | ||
34 | if (fetchedsomething) { | |
35 | prot_printf(imapd_out, "%s OK %s\r\n", tag, | |
36 | @@ -3352,7 +3357,9 @@ | |
37 | flag, nflags); | |
38 | ||
39 | if (usinguid) { | |
40 | - index_check(imapd_mailbox, 1, 0); | |
41 | + index_check(imapd_mailbox, 1, 1); /* Check \Seen too */ | |
42 | + } else { | |
43 | + index_check_existing(imapd_mailbox, 0, 1); | |
44 | } | |
45 | ||
46 | if (r) { | |
47 | diff -Naur cyrus-imapd-2.2.12.orig/imap/imapd.h cyrus-imapd-2.2.12/imap/imapd.h | |
48 | --- cyrus-imapd-2.2.12.orig/imap/imapd.h 2004-06-22 23:36:18.000000000 +0200 | |
49 | +++ cyrus-imapd-2.2.12/imap/imapd.h 2006-01-04 07:41:45.000000000 +0100 | |
50 | @@ -232,6 +232,8 @@ | |
51 | extern void index_operatemailbox(struct mailbox *mailbox); | |
52 | extern void index_check(struct mailbox *mailbox, int usinguid, | |
53 | int checkseen); | |
54 | +extern void | |
55 | +index_check_existing(struct mailbox *mailbox, int usinguid, int checkseen); | |
56 | extern void index_checkseen(struct mailbox *mailbox, int quiet, | |
57 | int usinguid, int oldexists); | |
58 | ||
59 | diff -Naur cyrus-imapd-2.2.12.orig/imap/index.c cyrus-imapd-2.2.12/imap/index.c | |
60 | --- cyrus-imapd-2.2.12.orig/imap/index.c 2005-02-14 17:42:08.000000000 +0100 | |
61 | +++ cyrus-imapd-2.2.12/imap/index.c 2006-01-04 08:08:51.000000000 +0100 | |
62 | @@ -425,6 +425,53 @@ | |
63 | } | |
64 | } | |
65 | ||
66 | +/* Nasty hack to report system + user flags updates without checking for | |
67 | + * new mail or expunge (relies on index atomic rewrite+rename for expunge). | |
68 | + * | |
69 | + * Needed to keep Outlook Express happy without breaking IMAP concurrent | |
70 | + * access regime which (quite correctly) prohibits unsolicited EXPUNGE and | |
71 | + * EXIST responses for non-UID versions of FETCH and STORE. Otherwise you | |
72 | + * can end up with hilarous situations such as: | |
73 | + * | |
74 | + * . FETCH 2 fast | |
75 | + * * EXPUNGE 1 <-- from concurrent session. | |
76 | + * . FETCH (data relating to previous message _3_, if it exists) | |
77 | + * | |
78 | + */ | |
79 | + | |
80 | +void | |
81 | +index_check_existing(struct mailbox *mailbox, int usinguid, int checkseen) | |
82 | +{ | |
83 | + struct stat sbuf; | |
84 | + int msgno, i; | |
85 | + bit32 user_flags[MAX_USER_FLAGS/32]; | |
86 | + | |
87 | + if (imapd_exists == -1) | |
88 | + return; | |
89 | + | |
90 | + /* Bail out if the mailbox was rotated under our feet */ | |
91 | + if ((index_len > 0) && | |
92 | + ((stat(FNAME_INDEX+1, &sbuf) != 0) || | |
93 | + (sbuf.st_ino != mailbox->index_ino) || | |
94 | + (index_ino != mailbox->index_ino))) | |
95 | + return; | |
96 | + | |
97 | + if (checkseen) | |
98 | + index_checkseen(mailbox, 0, usinguid, imapd_exists); | |
99 | + | |
100 | + for (msgno = 1; msgno <= imapd_exists; msgno++) { | |
101 | + if (flagreport[msgno] < LAST_UPDATED(msgno)) { | |
102 | + for (i = 0; i < VECTOR_SIZE(user_flags); i++) { | |
103 | + user_flags[i] = USER_FLAGS(msgno, i); | |
104 | + } | |
105 | + index_fetchflags(mailbox, msgno, SYSTEM_FLAGS(msgno), user_flags, | |
106 | + LAST_UPDATED(msgno)); | |
107 | + if (usinguid) prot_printf(imapd_out, " UID %u", UID(msgno)); | |
108 | + prot_printf(imapd_out, ")\r\n"); | |
109 | + } | |
110 | + } | |
111 | +} | |
112 | + | |
113 | /* | |
114 | * Checkpoint the user's \Seen state | |
115 | * | |
116 | @@ -458,6 +505,7 @@ | |
117 | char *saveseenuids, *save; | |
118 | int savealloced; | |
119 | unsigned start, newallseen, inrange, usecomma; | |
120 | + mailbox_notifyproc_t *updatenotifier; | |
121 | ||
122 | if (!keepingseen || !seendb) return; | |
123 | if (imapd_exists == 0) { | |
124 | @@ -731,6 +779,9 @@ | |
125 | ||
126 | free(newseenuids); | |
127 | seenuids = saveseenuids; | |
128 | + | |
129 | + updatenotifier = mailbox_get_updatenotifier(); | |
130 | + if (updatenotifier) updatenotifier(mailbox); | |
131 | } | |
132 | ||
133 | ||
134 | diff -Naur cyrus-imapd-2.2.12.orig/imap/mailbox.c cyrus-imapd-2.2.12/imap/mailbox.c | |
135 | --- cyrus-imapd-2.2.12.orig/imap/mailbox.c 2005-02-14 07:39:57.000000000 +0100 | |
136 | +++ cyrus-imapd-2.2.12/imap/mailbox.c 2006-01-04 07:41:45.000000000 +0100 | |
137 | @@ -230,6 +230,14 @@ | |
138 | } | |
139 | ||
140 | /* | |
141 | + * Get the updatenotifier function | |
142 | + */ | |
143 | +mailbox_notifyproc_t *mailbox_get_updatenotifier(void) | |
144 | +{ | |
145 | + return updatenotifier; | |
146 | +} | |
147 | + | |
148 | +/* | |
149 | * Create connection to acappush (obsolete) | |
150 | */ | |
151 | int mailbox_initialize(void) | |
152 | diff -Naur cyrus-imapd-2.2.12.orig/imap/mailbox.h cyrus-imapd-2.2.12/imap/mailbox.h | |
153 | --- cyrus-imapd-2.2.12.orig/imap/mailbox.h 2004-01-22 22:17:09.000000000 +0100 | |
154 | +++ cyrus-imapd-2.2.12/imap/mailbox.h 2006-01-04 07:41:45.000000000 +0100 | |
155 | @@ -224,6 +224,8 @@ | |
156 | ||
157 | extern void mailbox_set_updatenotifier(mailbox_notifyproc_t *notifyproc); | |
158 | ||
159 | +extern mailbox_notifyproc_t *mailbox_get_updatenotifier(void); | |
160 | + | |
161 | extern int mailbox_initialize(void); | |
162 | ||
163 | extern char *mailbox_message_fname(struct mailbox *mailbox, |