BUFFY* inc;
IMAP_MBOX mx;
int count;
- IMAP_STATUS status;
+ IMAP_STATUS *status, sb;
+ int olduv, oldun;
dprint (2, (debugfile, "Handling STATUS\n"));
mailbox = imap_next_word (s);
s = imap_next_word (mailbox);
*(s - 1) = '\0';
-
imap_unmunge_mbox_name (mailbox);
- status.name = mailbox;
+
+ if (!(status = imap_mboxcache_get (idata, mailbox)))
+ {
+ /* ugly interface - why should I look up what I just added? */
+ memset (&sb, 0, sizeof (IMAP_STATUS));
+ sb.name = mailbox;
+ idata->mboxcache = mutt_add_list_n (idata->mboxcache, &sb, sizeof (IMAP_STATUS));
+ status = imap_mboxcache_get (idata, mailbox);
+ status->name = safe_strdup (mailbox);
+ }
+ olduv = status->uidvalidity;
+ oldun = status->uidnext;
if (*s++ != '(')
{
count = strtol (value, &value, 10);
if (!ascii_strncmp ("MESSAGES", s, 8))
- {
- dprint (2, (debugfile, "%d messages in %s\n", count, mailbox));
- status.messages = count;
- }
+ status->messages = count;
else if (!ascii_strncmp ("RECENT", s, 6))
- {
- dprint (2, (debugfile, "%d recent in %s\n", count, mailbox));
- status.recent = count;
- }
+ status->recent = count;
else if (!ascii_strncmp ("UIDNEXT", s, 7))
- {
- dprint (2, (debugfile, "UIDNEXT for %s is %d\n", mailbox, count));
- status.uidnext = count;
- }
+ status->uidnext = count;
else if (!ascii_strncmp ("UIDVALIDITY", s, 11))
- {
- dprint (2, (debugfile, "UIDVALIDITY for %s is %d\n", mailbox, count));
- status.uidvalidity = count;
- }
+ status->uidvalidity = count;
else if (!ascii_strncmp ("UNSEEN", s, 6))
- {
- dprint (2, (debugfile, "%d unseen in %s\n", count, mailbox));
- status.unseen = count;
- }
-
+ status->unseen = count;
+
s = value;
+ if (*s && *s != ')')
+ s = imap_next_word (s);
}
+ dprint (2, (debugfile, "%s (UIDVALIDITY: %d, UIDNEXT: %d) %d messages, %d recent, %d unseen\n",
+ status->name, status->uidvalidity, status->uidnext,
+ status->messages, status->recent, status->unseen));
/* caller is prepared to handle the result herself */
if (idata->cmddata)
{
- memcpy (idata->cmddata, &status, sizeof (status));
+ memcpy (idata->cmddata, status, sizeof (IMAP_STATUS));
return;
}
if (mutt_account_match (&idata->conn->account, &mx.account) && mx.mbox
&& mutt_strncmp (mailbox, mx.mbox, strlen (mailbox)) == 0)
{
- inc->new = status.recent;
+ if (olduv && olduv == status->uidvalidity)
+ {
+ if (oldun < status->uidnext)
+ {
+ inc->new = status->unseen;
+ }
+ }
+ else
+ inc->new = status->unseen;
+ /* forced back to keep detecting new mail until the mailbox is opened */
+ status->uidnext = oldun;
+
FREE (&mx.mbox);
return;
}
{
CONNECTION *conn;
IMAP_DATA *idata;
+ IMAP_STATUS* status, sb;
char buf[LONG_STRING];
char bufout[LONG_STRING];
int count = 0;
imap_cmd_start (idata, bufout);
+ if (!(status = imap_mboxcache_get (idata, idata->mailbox)))
+ {
+ memset (&sb, 0, sizeof (IMAP_STATUS));
+ sb.name = idata->mailbox;
+ idata->mboxcache = mutt_add_list_n (idata->mboxcache, &sb, sizeof (IMAP_STATUS));
+ status = imap_mboxcache_get (idata, idata->mailbox);
+ status->name = safe_strdup (idata->mailbox);
+ }
do
{
char *pc;
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
goto fail;
}
-#ifdef USE_HCACHE
/* save UIDVALIDITY for the header cache */
- else if (ascii_strncasecmp("OK [UIDVALIDITY", pc, 14) == 0)
+ else if (ascii_strncasecmp ("OK [UIDVALIDITY", pc, 14) == 0)
{
- dprint(2, (debugfile, "Getting mailbox UIDVALIDITY\n"));
+ dprint (2, (debugfile, "Getting mailbox UIDVALIDITY\n"));
pc += 3;
- pc = imap_next_word(pc);
- sscanf(pc, "%lu", &(idata->uid_validity));
+ pc = imap_next_word (pc);
+ sscanf (pc, "%lu", &(idata->uid_validity));
+ status->uidvalidity = idata->uid_validity;
+ }
+ else if (ascii_strncasecmp ("OK [UIDNEXT", pc, 11) == 0)
+ {
+ dprint (2, (debugfile, "Getting mailbox UIDNEXT\n"));
+ pc += 3;
+ pc = imap_next_word (pc);
+ sscanf (pc, "%lu", &status->uidnext);
}
-#endif
else
{
pc = imap_next_word (pc);
/* Don't issue STATUS on the selected mailbox, it will be NOOPed or
* IDLEd elsewhere */
- if (mutt_strcmp (name, idata->mailbox) == 0
- || (ascii_strcasecmp (name, "INBOX") == 0
- && mutt_strcasecmp (name, idata->mailbox) == 0))
+ if (!imap_mxcmp (name, idata->mailbox))
continue;
if (!lastdata)
}
imap_munge_mbox_name (munged, sizeof (munged), name);
- /* we need a better way to detect new mail... */
- snprintf (command, sizeof (command), "STATUS %s (RECENT)", munged);
+ snprintf (command, sizeof (command), "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN)", munged);
if (imap_cmd_queue (idata, command) < 0)
{
if (imap_get_mailbox (path, &idata, buf, sizeof (buf)) < 0)
return -1;
- if (mutt_strcmp (buf, idata->mailbox) == 0
- || (ascii_strcasecmp (buf, "INBOX") == 0
- && mutt_strcasecmp (buf, idata->mailbox) == 0))
+ if (!imap_mxcmp (buf, idata->mailbox))
/* We are in the folder we're polling - just return the mailbox count */
return idata->ctx->msgcount;
else if (mutt_bit_isset(idata->capabilities,IMAP4REV1) ||
return messages;
}
+/* return cached mailbox stats or NULL */
+IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox)
+{
+ LIST* cur;
+ IMAP_STATUS* status;
+
+ for (cur = idata->mboxcache; cur; cur = cur->next)
+ {
+ status = (IMAP_STATUS*)cur->data;
+
+ if (!imap_mxcmp (mbox, status->name))
+ return status;
+ }
+
+ return NULL;
+}
+
+void imap_mboxcache_free (IMAP_DATA* idata)
+{
+ LIST* cur;
+ IMAP_STATUS* status;
+
+ for (cur = idata->mboxcache; cur; cur = cur->next)
+ {
+ status = (IMAP_STATUS*)cur->data;
+
+ FREE (&status->name);
+ }
+
+ mutt_free_list (&idata->mboxcache);
+}
+
/* returns number of patterns in the search that should be done server-side
* (eg are full-text) */
static int do_search (const pattern_t* search, int allpats)
int lastcmd;
BUFFER* cmdbuf;
+ /* cache IMAP_STATUS of visited mailboxes */
+ LIST* mboxcache;
+
/* The following data is all specific to the currently SELECTED mbox */
char delim;
CONTEXT *ctx;
unsigned char rights[(RIGHTSMAX + 7)/8];
unsigned int newMailCount;
IMAP_CACHE cache[IMAP_CACHE_LEN];
-#ifdef USE_HCACHE
unsigned long uid_validity;
-#endif
/* all folder flags - system flags AND keywords */
LIST *flags;
/* imap.c */
int imap_create_mailbox (IMAP_DATA* idata, char* mailbox);
int imap_rename_mailbox (IMAP_DATA* idata, IMAP_MBOX* mx, const char* newname);
+IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox);
+void imap_mboxcache_free (IMAP_DATA* idata);
int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed);
int imap_open_connection (IMAP_DATA* idata);
IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags);
size_t plen);
int imap_get_literal_count (const char* buf, long* bytes);
char* imap_get_qualifier (char* buf);
+int imap_mxcmp (const char* mx1, const char* mx2);
char* imap_next_word (char* s);
time_t imap_parse_date (char* s);
void imap_qualify_path (char *dest, size_t len, IMAP_MBOX *mx, char* path);
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $Id$
*/
/* message parsing/updating functions */
char tempfile[_POSIX_PATH_MAX];
int msgno;
IMAP_HEADER h;
+ IMAP_STATUS* status;
int rc, mfhrc, oldmsgcount;
int fetchlast = 0;
+ int maxuid = 0;
const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE CONTENT-DESCRIPTION IN-REPLY-TO REPLY-TO LINES LIST-POST X-LABEL";
#if USE_HCACHE
ctx->hdrs[msgno]->received = h.received;
ctx->hdrs[msgno]->data = (void *) (h.data);
+ if (maxuid < h.data->uid)
+ maxuid = h.data->uid;
+
rewind (fp);
/* NOTE: if Date: header is missing, mutt_read_rfc822_header depends
* on h.received being set */
mx_update_context (ctx, ctx->msgcount - oldmsgcount);
}
+ if (maxuid && (status = imap_mboxcache_get (idata, idata->mailbox)))
+ status->uidnext = maxuid + 1;
+
return msgend;
}
return 0;
}
+/* silly helper for mailbox name string comparisons, because of INBOX */
+int imap_mxcmp (const char* mx1, const char* mx2)
+{
+ if (!ascii_strcasecmp (mx1, "INBOX") && !ascii_strcasecmp (mx2, "INBOX"))
+ return 0;
+
+ return mutt_strcmp (mx1, mx2);
+}
+
/* imap_pretty_mailbox: called by mutt_pretty_mailbox to make IMAP paths
* look nice. */
void imap_pretty_mailbox (char* path)
FREE (&(*idata)->capstr);
mutt_free_list (&(*idata)->flags);
+ imap_mboxcache_free (*idata);
mutt_buffer_free(&(*idata)->cmdbuf);
FREE (&(*idata)->buf);
FREE (idata);