2
2
* Copyright (C) 1996-8 Michael R. Elkins <me@mutt.org>
3
3
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
4
* Copyright (C) 1999-2006 Brendan Cully <brendan@kublai.com>
4
* Copyright (C) 1999-2007 Brendan Cully <brendan@kublai.com>
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
88
if (imap_mboxcache_get (idata, mailbox, 0))
90
dprint (3, (debugfile, "imap_access: found %s in cache\n", mailbox));
87
94
imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
89
96
if (mutt_bit_isset (idata->capabilities, IMAP4REV1))
99
if (imap_exec (idata, buf, IMAP_CMD_FAIL_OK) < 0)
106
if ((rc = imap_exec (idata, buf, IMAP_CMD_FAIL_OK)) < 0)
101
108
dprint (1, (debugfile, "imap_access: Can't check STATUS of %s\n", mbox));
225
232
if (pbar && !(pos % 1024))
226
mutt_progress_bar (pbar, pos);
233
mutt_progress_update (pbar, pos, -1);
228
235
if (debuglevel >= IMAP_LOG_LTRL)
229
236
fputc (c, debugfile);
257
261
dprint (2, (debugfile, "Expunging message UID %d.\n", HEADER_DATA (h)->uid));
264
idata->ctx->size -= h->content->length;
261
266
imap_cache_del (idata, h);
265
sprintf (uidbuf, "/%u", HEADER_DATA(h)->uid);
266
mutt_hcache_delete (hc, uidbuf, imap_hcache_keylen);
268
imap_hcache_del (idata, HEADER_DATA(h)->uid);
270
271
/* free cached body from disk, if necessary */
377
383
if (new && idata->state == IMAP_AUTHENTICATED)
385
/* capabilities may have changed */
386
imap_cmd_queue (idata, "CAPABILITY");
379
387
/* get root delimiter, '/' as default */
380
388
idata->delim = '/';
381
389
imap_cmd_queue (idata, "LIST \"\" \"\"");
468
475
#if defined(USE_SSL)
477
imap_close_connection (idata);
480
FREE (&idata->capstr);
484
void imap_close_connection(IMAP_DATA* idata)
470
486
mutt_socket_close (idata->conn);
471
487
idata->state = IMAP_DISCONNECTED;
474
FREE (&idata->capstr);
488
idata->seqno = idata->nextcmd = idata->lastcmd = idata->status = 0;
489
memset (idata->cmds, 0, sizeof (IMAP_COMMAND) * IMAP_PIPELINE_DEPTH);
478
492
/* imap_get_flags: Make a simple list out of a FLAGS response.
560
574
/* once again the context is new */
561
575
ctx->data = idata;
576
ctx->mx_close = imap_close_mailbox;
563
578
/* Clean up path and replace the one in the ctx */
564
579
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
574
589
/* clear mailbox status */
575
590
idata->status = 0;
576
memset (idata->rights, 0, (RIGHTSMAX+7)/8);
591
memset (idata->ctx->rights, 0, sizeof (idata->ctx->rights));
577
592
idata->newMailCount = 0;
579
594
mutt_message (_("Selecting %s..."), idata->mailbox);
588
603
/* assume we have all rights if ACL is unavailable */
591
mutt_bit_set (idata->rights, IMAP_ACL_LOOKUP);
592
mutt_bit_set (idata->rights, IMAP_ACL_READ);
593
mutt_bit_set (idata->rights, IMAP_ACL_SEEN);
594
mutt_bit_set (idata->rights, IMAP_ACL_WRITE);
595
mutt_bit_set (idata->rights, IMAP_ACL_INSERT);
596
mutt_bit_set (idata->rights, IMAP_ACL_POST);
597
mutt_bit_set (idata->rights, IMAP_ACL_CREATE);
598
mutt_bit_set (idata->rights, IMAP_ACL_DELETE);
606
mutt_bit_set (idata->ctx->rights, M_ACL_LOOKUP);
607
mutt_bit_set (idata->ctx->rights, M_ACL_READ);
608
mutt_bit_set (idata->ctx->rights, M_ACL_SEEN);
609
mutt_bit_set (idata->ctx->rights, M_ACL_WRITE);
610
mutt_bit_set (idata->ctx->rights, M_ACL_INSERT);
611
mutt_bit_set (idata->ctx->rights, M_ACL_POST);
612
mutt_bit_set (idata->ctx->rights, M_ACL_CREATE);
613
mutt_bit_set (idata->ctx->rights, M_ACL_DELETE);
600
615
/* pipeline the postponed count if possible */
612
627
imap_cmd_start (idata, bufout);
614
if (!(status = imap_mboxcache_get (idata, idata->mailbox)))
616
memset (&sb, 0, sizeof (IMAP_STATUS));
617
sb.name = idata->mailbox;
618
idata->mboxcache = mutt_add_list_n (idata->mboxcache, &sb, sizeof (IMAP_STATUS));
619
status = imap_mboxcache_get (idata, idata->mailbox);
620
status->name = safe_strdup (idata->mailbox);
629
status = imap_mboxcache_get (idata, idata->mailbox, 1);
727
if (!(mutt_bit_isset(idata->rights, IMAP_ACL_DELETE) ||
728
mutt_bit_isset(idata->rights, IMAP_ACL_SEEN) ||
729
mutt_bit_isset(idata->rights, IMAP_ACL_WRITE) ||
730
mutt_bit_isset(idata->rights, IMAP_ACL_INSERT)))
736
if (!(mutt_bit_isset(idata->ctx->rights, M_ACL_DELETE) ||
737
mutt_bit_isset(idata->ctx->rights, M_ACL_SEEN) ||
738
mutt_bit_isset(idata->ctx->rights, M_ACL_WRITE) ||
739
mutt_bit_isset(idata->ctx->rights, M_ACL_INSERT)))
731
740
ctx->readonly = 1;
733
742
ctx->hdrmax = count;
734
743
ctx->hdrs = safe_calloc (count, sizeof (HEADER *));
735
744
ctx->v2r = safe_calloc (count, sizeof (int));
736
745
ctx->msgcount = 0;
737
747
if (count && (imap_read_headers (idata, 0, count-1) < 0))
739
749
mutt_error _("Error opening mailbox");
784
795
/* really we should also check for W_OK */
785
if (!imap_access (ctx->path, F_OK))
796
if ((rc = imap_access (ctx->path, F_OK)) == 0)
788
802
snprintf (buf, sizeof (buf), _("Create %s?"), mailbox);
789
803
if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
815
829
static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,
816
830
const char *str, char *flags, size_t flsize)
818
if (mutt_bit_isset (idata->rights, aclbit))
832
if (mutt_bit_isset (idata->ctx->rights, aclbit))
819
833
if (flag && imap_has_flag (idata->flags, str))
820
834
safe_strcat (flags, flsize, str);
846
860
* headers, given a flag enum to filter on.
847
861
* Params: idata: IMAP_DATA containing context containing header set
848
862
* buf: to write message set into
849
* buflen: length of buffer
850
863
* flag: enum of flag type on which to filter
851
864
* changed: include only changed messages in message set
852
865
* invert: invert sense of flag, eg M_READ matches unread messages
928
941
else if (n == idata->ctx->msgcount-1)
929
942
mutt_buffer_printf (buf, ":%u", HEADER_DATA (hdrs[n])->uid);
931
/* this message is not expunged and doesn't match. End current set. */
932
else if (setstart && hdrs[n]->active)
944
/* End current set if message doesn't match or we've reached the end
945
* of the mailbox via inactive messages following the last match. */
946
else if (setstart && (hdrs[n]->active || n == idata->ctx->msgcount-1))
934
948
if (HEADER_DATA (hdrs[n-1])->uid > setstart)
935
949
mutt_buffer_printf (buf, ":%u", HEADER_DATA (hdrs[n-1])->uid);
986
1000
flags[0] = '\0';
988
imap_set_flag (idata, IMAP_ACL_SEEN, hdr->read, "\\Seen ",
1002
imap_set_flag (idata, M_ACL_SEEN, hdr->read, "\\Seen ",
989
1003
flags, sizeof (flags));
990
imap_set_flag (idata, IMAP_ACL_WRITE, hdr->old,
1004
imap_set_flag (idata, M_ACL_WRITE, hdr->old,
991
1005
"Old ", flags, sizeof (flags));
992
imap_set_flag (idata, IMAP_ACL_WRITE, hdr->flagged,
1006
imap_set_flag (idata, M_ACL_WRITE, hdr->flagged,
993
1007
"\\Flagged ", flags, sizeof (flags));
994
imap_set_flag (idata, IMAP_ACL_WRITE, hdr->replied,
1008
imap_set_flag (idata, M_ACL_WRITE, hdr->replied,
995
1009
"\\Answered ", flags, sizeof (flags));
996
imap_set_flag (idata, IMAP_ACL_DELETE, hdr->deleted,
1010
imap_set_flag (idata, M_ACL_DELETE, hdr->deleted,
997
1011
"\\Deleted ", flags, sizeof (flags));
999
1013
/* now make sure we don't lose custom tags */
1000
if (mutt_bit_isset (idata->rights, IMAP_ACL_WRITE))
1014
if (mutt_bit_isset (idata->ctx->rights, M_ACL_WRITE))
1001
1015
imap_add_keywords (flags, hdr, idata->flags, sizeof (flags));
1003
1017
mutt_remove_trailing_ws (flags);
1006
1020
* explicitly revoke all system flags (if we have permission) */
1009
imap_set_flag (idata, IMAP_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags));
1010
imap_set_flag (idata, IMAP_ACL_WRITE, 1, "Old ", flags, sizeof (flags));
1011
imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Flagged ", flags, sizeof (flags));
1012
imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags));
1013
imap_set_flag (idata, IMAP_ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags));
1023
imap_set_flag (idata, M_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags));
1024
imap_set_flag (idata, M_ACL_WRITE, 1, "Old ", flags, sizeof (flags));
1025
imap_set_flag (idata, M_ACL_WRITE, 1, "\\Flagged ", flags, sizeof (flags));
1026
imap_set_flag (idata, M_ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags));
1027
imap_set_flag (idata, M_ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags));
1015
1029
mutt_remove_trailing_ws (flags);
1049
if (!mutt_bit_isset (idata->rights, right))
1063
if (!mutt_bit_isset (idata->ctx->rights, right))
1052
if (right == IMAP_ACL_WRITE && !imap_has_flag (idata->flags, name))
1066
if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name))
1055
1069
buf->dptr = buf->data;
1111
1121
memset (&cmd, 0, sizeof (cmd));
1113
1123
/* if we are expunging anyway, we can do deleted messages very quickly... */
1114
if (expunge && mutt_bit_isset (idata->rights, IMAP_ACL_DELETE))
1124
if (expunge && mutt_bit_isset (idata->ctx->rights, M_ACL_DELETE))
1116
1126
mutt_buffer_addstr (&cmd, "UID STORE ");
1117
1127
deleted = imap_make_msg_set (idata, &cmd, M_DELETED, 1, 0);
1140
if (expunge && ctx->closing)
1141
hc = mutt_hcache_open (HeaderCache, idata->ctx->path);
1150
idata->hcache = imap_hcache_open (idata, NULL);
1144
1153
/* save messages with real (non-flag) changes */
1147
1156
h = ctx->hdrs[n];
1149
1158
if (h->deleted)
1150
1160
imap_cache_del (idata, h);
1152
if (hc && h->deleted)
1154
sprintf (uidbuf, "/%u", HEADER_DATA(h)->uid);
1155
mutt_hcache_delete (hc, uidbuf, imap_hcache_keylen);
1162
imap_hcache_del (idata, HEADER_DATA(h)->uid);
1158
1166
if (h->active && h->changed)
1160
1168
/* if the message has been rethreaded or attachments have been deleted
1194
1206
mutt_get_sort_func (SORT_ORDER));
1197
rc += sync_helper (idata, &cmd, IMAP_ACL_DELETE, M_DELETED, "\\Deleted");
1198
rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_FLAG, "\\Flagged");
1199
rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_OLD, "Old");
1200
rc += sync_helper (idata, &cmd, IMAP_ACL_SEEN, M_READ, "\\Seen");
1201
rc += sync_helper (idata, &cmd, IMAP_ACL_WRITE, M_REPLIED, "\\Answered");
1209
rc += sync_helper (idata, &cmd, M_ACL_DELETE, M_DELETED, "\\Deleted");
1210
rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_FLAG, "\\Flagged");
1211
rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_OLD, "Old");
1212
rc += sync_helper (idata, &cmd, M_ACL_SEEN, M_READ, "\\Seen");
1213
rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_REPLIED, "\\Answered");
1203
1215
if (oldsort != Sort)
1232
1244
/* We must send an EXPUNGE command if we're not closing. */
1233
1245
if (expunge && !(ctx->closing) &&
1234
mutt_bit_isset(idata->rights, IMAP_ACL_DELETE))
1246
mutt_bit_isset(idata->ctx->rights, M_ACL_DELETE))
1236
1248
mutt_message _("Expunging messages from server...");
1237
1249
/* Set expunge bit so we don't get spurious reopened messages */
1301
1314
/* free IMAP part of headers */
1302
1315
for (i = 0; i < ctx->msgcount; i++)
1303
imap_free_header_data (&(ctx->hdrs[i]->data));
1316
/* mailbox may not have fully loaded */
1317
if (ctx->hdrs[i] && ctx->hdrs[i]->data)
1318
imap_free_header_data (&(ctx->hdrs[i]->data));
1305
1320
for (i = 0; i < IMAP_CACHE_LEN; i++)
1444
1461
* IDLEd elsewhere */
1445
1462
if (!imap_mxcmp (name, idata->mailbox))
1451
if (idata != lastdata)
1465
if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) &&
1466
!mutt_bit_isset (idata->capabilities, STATUS))
1468
dprint (2, (debugfile, "Server doesn't support STATUS\n"));
1472
if (lastdata && idata != lastdata)
1453
1474
/* Send commands to previous server. Sorting the buffy list
1454
1475
* may prevent some infelicitous interleavings */
1458
1479
lastdata = NULL;
1461
if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) &&
1462
!mutt_bit_isset (idata->capabilities, STATUS))
1464
dprint (2, (debugfile, "Server doesn't support STATUS\n"));
1468
1485
imap_munge_mbox_name (munged, sizeof (munged), name);
1469
snprintf (command, sizeof (command), "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN)", munged);
1486
snprintf (command, sizeof (command),
1487
"STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
1471
1489
if (imap_cmd_queue (idata, command) < 0)
1540
1558
imap_exec (idata, buf, 0);
1543
if ((status = imap_mboxcache_get (idata, mbox)))
1561
if ((status = imap_mboxcache_get (idata, mbox, 0)))
1544
1562
return status->messages;
1549
/* return cached mailbox stats or NULL */
1550
IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox)
1567
/* return cached mailbox stats or NULL if create is 0 */
1568
IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox, int create)
1553
1571
IMAP_STATUS* status;
1574
header_cache_t *hc = NULL;
1575
unsigned int *uidvalidity = NULL;
1576
unsigned int *uidnext = NULL;
1555
1579
for (cur = idata->mboxcache; cur; cur = cur->next)
1559
1583
if (!imap_mxcmp (mbox, status->name))
1591
memset (&scache, 0, sizeof (scache));
1592
scache.name = (char*)mbox;
1593
idata->mboxcache = mutt_add_list_n (idata->mboxcache, &scache,
1595
status = imap_mboxcache_get (idata, mbox, 0);
1596
status->name = safe_strdup (mbox);
1600
hc = imap_hcache_open (idata, mbox);
1603
uidvalidity = mutt_hcache_fetch_raw (hc, "/UIDVALIDITY", imap_hcache_keylen);
1604
uidnext = mutt_hcache_fetch_raw (hc, "/UIDNEXT", imap_hcache_keylen);
1605
mutt_hcache_close (hc);
1610
FREE (&uidvalidity);
1612
return imap_mboxcache_get (idata, mbox, 1);
1614
status->uidvalidity = *uidvalidity;
1615
status->uidnext = uidnext ? *uidnext: 0;
1616
dprint (3, (debugfile, "mboxcache: hcache uidvalidity %d, uidnext %d\n",
1617
status->uidvalidity, status->uidnext));
1619
FREE (&uidvalidity);
1566
1627
void imap_mboxcache_free (IMAP_DATA* idata)
1807
1868
matchlen = mutt_strlen (dest);
1808
for (mailbox = Incoming; mailbox && mailbox->next; mailbox = mailbox->next)
1869
for (mailbox = Incoming; mailbox; mailbox = mailbox->next)
1810
1871
if (!mutt_strncmp (dest, mailbox->path, matchlen))
1864
if (imap_parse_path (path, &mx) || !mx.mbox)
1925
if (imap_parse_path (path, &mx))
1866
1927
strfcpy (dest, path, dlen);
1867
1928
return imap_complete_hosts (dest, dlen);