Commit 06c07ce7 authored by Nathan Dushman's avatar Nathan Dushman

The attached patch provides improved support for IMAP ACLs (on

servers that support them).  This means that mutt will now write the
Seen flag in mailboxes that allow it, even if the mailbox doesn't
allow other changes.
parent 93406c61
......@@ -30,7 +30,7 @@
#endif
#ifdef USE_IMAP
#include "imap.h"
#include "imap_private.h"
#endif
#include "mutt_crypt.h"
......@@ -78,6 +78,17 @@ static const char *No_visible = N_("No visible messages.");
break; \
}
#ifdef USE_IMAP
/* the error message returned here could be better. */
#define CHECK_IMAP_ACL(aclbit) if (Context->magic == M_IMAP) \
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,aclbit)){ \
mutt_flushinp(); \
mutt_error ("Operation not permitted by the IMAP ACL for this mailbox"); \
break; \
}
#endif
#define CHECK_ATTACH if(option(OPTATTACHMSG)) \
{\
mutt_flushinp (); \
......@@ -744,6 +755,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
CHECK_ATTACH;
mutt_pattern_func (M_DELETE, _("Delete messages matching: "));
menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
......@@ -901,6 +917,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
if (mutt_pattern_func (M_UNDELETE, _("Undelete messages matching: ")) == 0)
menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
break;
......@@ -1342,6 +1363,10 @@ int mutt_index_menu (void)
}
#endif
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_WRITE);
#endif
if (tag)
{
for (j = 0; j < Context->vcount; j++)
......@@ -1377,6 +1402,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_SEEN);
#endif
if (tag)
{
for (j = 0; j < Context->vcount; j++)
......@@ -1489,6 +1519,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
/* #ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_WRITE);
#endif */
if (mutt_change_flag (tag ? NULL : CURHDR, (op == OP_MAIN_SET_FLAG)) == 0)
{
menu->redraw = REDRAW_STATUS;
......@@ -1627,6 +1662,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
if (tag)
{
mutt_tag_set_flag (M_DELETE, 1);
......@@ -1667,6 +1707,10 @@ int mutt_index_menu (void)
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
rc = mutt_thread_set_flag (CURHDR, M_DELETE, 1,
op == OP_DELETE_THREAD ? 0 : 1);
......@@ -1716,6 +1760,10 @@ int mutt_index_menu (void)
}
#endif
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_INSERT);
#endif
mutt_edit_message (Context, tag ? NULL : CURHDR);
menu->redraw = REDRAW_FULL;
......@@ -1814,6 +1862,10 @@ int mutt_index_menu (void)
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_SEEN);
#endif
rc = mutt_thread_set_flag (CURHDR, M_READ, 1,
op == OP_MAIN_READ_THREAD ? 0 : 1);
......@@ -1896,6 +1948,11 @@ int mutt_index_menu (void)
CHECK_MSGCOUNT;
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
if (tag)
{
mutt_tag_set_flag (M_DELETE, 0);
......@@ -1922,6 +1979,10 @@ int mutt_index_menu (void)
CHECK_VISIBLE;
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
op == OP_UNDELETE_THREAD ? 0 : 1);
......
......@@ -21,6 +21,10 @@
#include "sort.h"
#include "mx.h"
#ifdef USE_IMAP
#include "imap_private.h"
#endif
void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
{
int changed = h->changed;
......@@ -33,9 +37,17 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
switch (flag)
{
case M_DELETE:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_DELETE))
return;
#endif
if (bf)
{
if (!h->deleted)
if (!h->deleted && !ctx->readonly)
{
h->deleted = 1;
if (upd_ctx) ctx->deleted++;
......@@ -76,6 +88,14 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
break;
case M_NEW:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_SEEN))
return;
#endif
if (bf)
{
if (h->read || h->old)
......@@ -103,6 +123,14 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
break;
case M_OLD:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_SEEN))
return;
#endif
if (bf)
{
if (!h->old)
......@@ -125,6 +153,14 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
break;
case M_READ:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_SEEN))
return;
#endif
if (bf)
{
if (!h->read)
......@@ -149,6 +185,14 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
break;
case M_REPLIED:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_WRITE))
return;
#endif
if (bf)
{
if (!h->replied)
......@@ -174,6 +218,14 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
break;
case M_FLAG:
#ifdef USE_IMAP
if (Context->magic == M_IMAP)
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,IMAP_ACL_WRITE))
return;
#endif
if (bf)
{
if (!h->flagged)
......
......@@ -611,7 +611,8 @@ int imap_open_mailbox (CONTEXT* ctx)
goto fail;
/* check for READ-ONLY notification */
if (!ascii_strncasecmp (imap_get_qualifier (idata->cmd.buf), "[READ-ONLY]", 11))
if (!ascii_strncasecmp (imap_get_qualifier (idata->cmd.buf), "[READ-ONLY]", 11) \
&& !mutt_bit_isset (idata->capabilities, ACL))
{
dprint (2, (debugfile, "Mailbox is read-only.\n"));
ctx->readonly = 1;
......@@ -644,6 +645,11 @@ int imap_open_mailbox (CONTEXT* ctx)
{
if (imap_check_acl (idata))
goto fail;
if (!(mutt_bit_isset(idata->rights, IMAP_ACL_DELETE) ||
mutt_bit_isset(idata->rights, IMAP_ACL_SEEN) ||
mutt_bit_isset(idata->rights, IMAP_ACL_WRITE) ||
mutt_bit_isset(idata->rights, IMAP_ACL_INSERT)))
ctx->readonly = 1;
}
/* assume we have all rights if ACL is unavailable */
else
......
......@@ -30,7 +30,7 @@
#include "mx.h"
#ifdef USE_IMAP
#include "imap.h"
#include "imap_private.h"
#endif
#include "mutt_crypt.h"
......@@ -75,6 +75,17 @@ static const char *Function_not_permitted_in_attach_message_mode = N_("Function
break; \
}
#ifdef USE_IMAP
/* the error message returned here could be better. */
#define CHECK_IMAP_ACL(aclbit) if (Context->magic == M_IMAP) \
if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,aclbit)){ \
mutt_flushinp(); \
mutt_error ("Operation not permitted by the IMAP ACL for this mailbox"); \
break; \
}
#endif
struct q_class_t
{
int length;
......@@ -2175,6 +2186,11 @@ search_next:
case OP_DELETE:
CHECK_MODE(IsHeader (extra));
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
mutt_set_flag (Context, extra->hdr, M_DELETE, 1);
if (option (OPTDELETEUNTAG))
mutt_set_flag (Context, extra->hdr, M_TAG, 0);
......@@ -2191,6 +2207,10 @@ search_next:
CHECK_MODE(IsHeader (extra));
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
r = mutt_thread_set_flag (extra->hdr, M_DELETE, 1,
ch == OP_DELETE_THREAD ? 0 : 1);
......@@ -2319,6 +2339,10 @@ search_next:
}
#endif
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_WRITE);
#endif
mutt_set_flag (Context, extra->hdr, M_FLAG, !extra->hdr->flagged);
redraw = REDRAW_STATUS | REDRAW_INDEX;
if (option (OPTRESOLVE))
......@@ -2468,6 +2492,11 @@ search_next:
case OP_TOGGLE_NEW:
CHECK_MODE(IsHeader (extra));
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_SEEN);
#endif
if (extra->hdr->read || extra->hdr->old)
mutt_set_flag (Context, extra->hdr, M_NEW, 1);
else if (!first)
......@@ -2485,6 +2514,11 @@ search_next:
case OP_UNDELETE:
CHECK_MODE(IsHeader (extra));
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
mutt_set_flag (Context, extra->hdr, M_DELETE, 0);
redraw = REDRAW_STATUS | REDRAW_INDEX;
if (option (OPTRESOLVE))
......@@ -2499,6 +2533,10 @@ search_next:
CHECK_MODE(IsHeader (extra));
CHECK_READONLY;
#ifdef USE_IMAP
CHECK_IMAP_ACL(IMAP_ACL_DELETE);
#endif
r = mutt_thread_set_flag (extra->hdr, M_DELETE, 0,
ch == OP_UNDELETE_THREAD ? 0 : 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment