summaryrefslogtreecommitdiff
blob: 124546871592840307c0d053bee32826fb6edcff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
--- imap.c.old	2006-01-23 13:07:04.000000000 +0100
+++ imap.c	2006-01-23 13:45:14.000000000 +0100
@@ -310,13 +310,8 @@
 }
 #endif
 
-/* Ok, now fetch all the headers from the first UNSEEN through the
- * end of the mailbox.  This could be lower bandwidth (maybe) by first
- * fetching all of the flags, and then only fetching the headers of
- * the messages which are new, but there is a lot of protocol crap
- * which would probably negate the lower bandwidth */
-static int parse_fetch (BOX_INFO *ibox, CONNECTION *conn, GList *headers, 
-    int unseen)
+/* Ok, now fetch all the headers from the supplied range */
+static int parse_fetch_range (CONNECTION *conn, GList *headers, char *range)
 {
   char from[LONG_STRING] = "";
   char subject[LONG_STRING] = "";
@@ -328,7 +323,7 @@
 
 
   imap_make_sequence (seq, sizeof (seq));
-  snprintf (buf, sizeof (buf), "%s FETCH %d:%d (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT X-FACE)])\r\n", seq, unseen, ibox->num_messages);
+  snprintf (buf, sizeof (buf), "%s FETCH %s (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT X-FACE)])\r\n", seq, range);
   msocket_write (conn, buf);
 
   do 
@@ -428,6 +423,83 @@
   return 0;
 }
 
+/* Fetch only recent unseen information, since X-Face is unlikely to be cached
+ * and any mailbox with multiple threads may have people reading sub-ranges,
+ * leaving large gaps in the sequence range.  */
+static int parse_fetch (BOX_INFO *ibox, CONNECTION *conn, GList *headers, 
+    int unseen)
+{
+  char buf[LONG_STRING];
+  char seq[8];
+  char *s, *t, *commacopy, csave;
+  size_t len, slen, tlen;
+  int ret, line;
+
+  imap_make_sequence (seq, sizeof (seq));
+  snprintf (buf, sizeof (buf), "%s SEARCH RECENT UNSEEN\r\n", seq);
+  msocket_write (conn, buf);
+
+  commacopy = NULL;
+  do 
+  {
+    if (msocket_read_line_d (buf, sizeof (buf), conn) < 0)
+    {
+      conn->uses = 0;
+      return (-1);
+    }
+    line = 1;
+
+    while (line--)
+    {
+      if (buf[0] != '*')
+	continue;
+
+      s = imap_next_word (buf);
+      if (strncasecmp ("SEARCH", s, 6) != 0)
+	continue;
+      s = imap_next_word (s);
+
+      t = s + strcspn (s, "\r\n");
+      csave = *t;
+      *t = '\0';
+
+      if (commacopy)
+      {
+	len = strlen (commacopy);
+	slen = strlen (s);
+	tlen = len + slen + 2;
+	safe_realloc ((void **) &commacopy, tlen);
+	commacopy[len] = ' ';
+	strfcpy (commacopy + len + 1, s, slen);
+      }
+      else
+	commacopy = safe_strdup (s);
+
+      *t = csave;
+      t += strspn (t, "\r\n");
+      if (*t != '\0')
+	++line;
+    }
+  }
+  while ((strncmp (buf, seq, SEQLEN) != 0));
+
+  s = commacopy;
+  /* First character guaranteed not whitespace by imap_next_word */
+  while (*++s)
+  {
+    if (isspace(*s))
+      *s = ',';
+  }
+  while (*--s == ',')
+    *s = '\0';
+
+  ret = parse_fetch_range (conn, headers, commacopy);
+
+  safe_free ((void **) &commacopy);
+
+  return ret;
+}
+
 static int imap_fetch_new_headers (BOX_INFO *ibox, CONNECTION *conn, GList *headers)
 {
   char buf[LONG_STRING];