Changeset 5499:1d94905ad00b for imap

Show
Ignore:
Timestamp:
2008-08-28 11:19:36 (3 months ago)
Author:
Brendan Cully <brendan@…>
Branch:
HEAD
Message:

The msgset changes seem buggy. Reverting pending further testing.

Location:
imap
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • imap/command.c

    r5498 r5499  
    197197 *     for checking for a mailbox on append and login 
    198198 *   IMAP_CMD_PASS: command contains a password. Suppress logging. 
    199  *   IMAP_CMD_QUEUE: only queue command, do not execute. 
    200199 * Return 0 on success, -1 on Failure, -2 on OK Failure 
    201200 */ 
  • imap/imap.c

    r5498 r5499  
    857857} 
    858858 
    859 /* Note: headers must be in SORT_ORDER. See imap_exec_msgset for args. 
    860  * Pos is an opaque pointer a la strtok. It should be 0 at first call. */ 
    861 static int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, 
    862                               int changed, int invert, int* pos) 
    863 { 
    864   HEADER** hdrs = idata->ctx->hdrs; 
     859/* imap_make_msg_set: make an IMAP4rev1 UID message set out of a set of 
     860 *   headers, given a flag enum to filter on. 
     861 * Params: idata: IMAP_DATA containing context containing header set 
     862 *         buf: to write message set into 
     863 *         flag: enum of flag type on which to filter 
     864 *         changed: include only changed messages in message set 
     865 *         invert: invert sense of flag, eg M_READ matches unread messages 
     866 * Returns: number of messages in message set (0 if no matches) */ 
     867int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed, 
     868                       int invert) 
     869{ 
     870  HEADER** hdrs;        /* sorted local copy */ 
    865871  int count = 0;        /* number of messages in message set */ 
    866872  int match = 0;        /* whether current message matches flag condition */ 
    867873  unsigned int setstart = 0;    /* start of current message range */ 
    868874  int n; 
     875  short oldsort;        /* we clobber reverse, must restore it */ 
    869876  int started = 0; 
    870877 
    871   hdrs = idata->ctx->hdrs; 
     878  if (Sort != SORT_ORDER) 
     879  { 
     880    hdrs = safe_calloc (idata->ctx->msgcount, sizeof (HEADER*)); 
     881    memcpy (hdrs, idata->ctx->hdrs, idata->ctx->msgcount * sizeof (HEADER*)); 
     882     
     883    oldsort = Sort; 
     884    Sort = SORT_ORDER; 
     885    qsort ((void*) hdrs, idata->ctx->msgcount, sizeof (HEADER*), 
     886      mutt_get_sort_func (SORT_ORDER)); 
     887    Sort = oldsort; 
     888  } 
     889  else 
     890    hdrs = idata->ctx->hdrs; 
    872891   
    873   for (n = *pos; 
    874        n < idata->ctx->msgcount && buf->dptr - buf->data < IMAP_MAX_CMDLEN; 
    875        n++) 
     892  for (n = 0; n < idata->ctx->msgcount; n++) 
    876893  { 
    877894    match = 0; 
     
    935952  } 
    936953 
    937   *pos = n; 
    938  
    939   return count; 
    940 } 
    941  
    942 /* Prepares commands for all messages matching conditions (must be flushed 
    943  * with imap_exec) 
    944  * Params: 
    945  *   idata: IMAP_DATA containing context containing header set 
    946  *   pre, post: commands are of the form "%s %s %s %s", tag, 
    947  *     pre, message set, post 
    948  *   flag: enum of flag type on which to filter 
    949  *   changed: include only changed messages in message set 
    950  *   invert: invert sense of flag, eg M_READ matches unread messages 
    951  * Returns: number of matched messages, or -1 on failure */ 
    952 int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post, 
    953                       int flag, int changed, int invert) 
    954 { 
    955   HEADER** hdrs;        /* sorted local copy */ 
    956   short oldsort;        /* we clobber reverse, must restore it */ 
    957   BUFFER* cmd; 
    958   int pos; 
    959   int rc; 
    960   int count = 0; 
    961  
    962   if (! (cmd = mutt_buffer_init (NULL))) 
    963   { 
    964     dprint (1, (debugfile, "imap_exec_msgset: unable to allocate buffer\n")); 
    965     return -1; 
    966   } 
    967  
    968   /* We make a copy of the headers just in case resorting doesn't give 
    969    exactly the original order (duplicate messages?), because other parts of 
    970    the ctx are tied to the header order. This may be overkill. */ 
    971   if (Sort != SORT_ORDER) 
    972   { 
    973     hdrs = safe_calloc (idata->ctx->msgcount, sizeof (HEADER*)); 
    974     memcpy (hdrs, idata->ctx->hdrs, idata->ctx->msgcount * sizeof (HEADER*)); 
    975      
    976     oldsort = Sort; 
    977     Sort = SORT_ORDER; 
    978     qsort ((void*) hdrs, idata->ctx->msgcount, sizeof (HEADER*), 
    979            mutt_get_sort_func (Sort)); 
    980     Sort = oldsort; 
    981   } 
    982   else 
    983     hdrs = idata->ctx->hdrs; 
    984  
    985   pos = 0; 
    986  
    987   do 
    988   { 
    989     cmd->dptr = cmd->data; 
    990     mutt_buffer_printf (cmd, "%s ", pre); 
    991     rc = imap_make_msg_set (idata, cmd, flag, changed, invert, &pos); 
    992     if (rc > 0) 
    993     { 
    994       mutt_buffer_printf (cmd, " %s", post); 
    995       if (imap_exec (idata, cmd->data, IMAP_CMD_QUEUE)) 
    996       { 
    997         rc = -1; 
    998         goto out; 
    999       } 
    1000       count += rc; 
    1001     } 
    1002   } 
    1003   while (rc > 0); 
    1004    
    1005   rc = count; 
    1006  
    1007 out: 
    1008   mutt_buffer_free (&cmd); 
    1009954  if (Sort != SORT_ORDER) 
    1010955    FREE (&hdrs); 
    1011956 
    1012   return rc; 
     957  return count; 
    1013958} 
    1014959 
     
    1033978 
    1034979/* Update the IMAP server to reflect the flags a single message.  */ 
     980 
    1035981int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, 
    1036982                       int *err_continue) 
     
    11101056} 
    11111057 
    1112 static int sync_helper (IMAP_DATA* idata, int right, int flag, const char* name) 
    1113 { 
    1114   int count = 0; 
    1115   int rc; 
    1116  
    1117   char buf[LONG_STRING]; 
     1058static int sync_helper (IMAP_DATA* idata, BUFFER* buf, int right, int flag, 
     1059                        const char* name) 
     1060{ 
     1061  int rc = 0; 
    11181062 
    11191063  if (!mutt_bit_isset (idata->ctx->rights, right)) 
    11201064    return 0; 
    1121  
     1065   
    11221066  if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name)) 
    11231067    return 0; 
    11241068 
    1125   snprintf (buf, sizeof(buf), "+FLAGS.SILENT (%s)", name); 
    1126   if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 0)) < 0) 
    1127     return rc; 
    1128   count += rc; 
    1129  
    1130   buf[0] = '-'; 
    1131   if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 1)) < 0) 
    1132     return rc; 
    1133   count += rc; 
    1134  
    1135   return count; 
     1069  buf->dptr = buf->data; 
     1070  mutt_buffer_addstr (buf, "UID STORE "); 
     1071  if (imap_make_msg_set (idata, buf, flag, 1, 0)) 
     1072  { 
     1073    rc++; 
     1074    mutt_buffer_printf (buf, " +FLAGS.SILENT (%s)", name); 
     1075    imap_exec (idata, buf->data, IMAP_CMD_QUEUE); 
     1076  } 
     1077  buf->dptr = buf->data; 
     1078  mutt_buffer_addstr (buf, "UID STORE "); 
     1079  if (imap_make_msg_set (idata, buf, flag, 1, 1)) 
     1080  { 
     1081    rc++; 
     1082    mutt_buffer_printf (buf, " -FLAGS.SILENT (%s)", name); 
     1083    imap_exec (idata, buf->data, IMAP_CMD_QUEUE); 
     1084  } 
     1085   
     1086  return rc; 
    11361087} 
    11371088 
     
    11451096  IMAP_DATA* idata; 
    11461097  CONTEXT* appendctx = NULL; 
     1098  BUFFER cmd; 
    11471099  HEADER* h; 
    11481100  HEADER** hdrs = NULL; 
    11491101  int oldsort; 
     1102  int deleted; 
    11501103  int n; 
    11511104  int rc; 
     
    11661119    return rc; 
    11671120 
     1121  memset (&cmd, 0, sizeof (cmd)); 
     1122 
    11681123  /* if we are expunging anyway, we can do deleted messages very quickly... */ 
    11691124  if (expunge && mutt_bit_isset (idata->ctx->rights, M_ACL_DELETE)) 
    11701125  { 
    1171     if ((rc = imap_exec_msgset (idata, "UID STORE", "+FLAGS.SILENT (\\Deleted)", 
    1172                                 M_DELETED, 1, 0)) < 0) 
    1173     { 
    1174       mutt_error (_("Expunge failed")); 
    1175       mutt_sleep (1); 
    1176       goto out; 
    1177     } 
    1178  
    1179     if (rc > 0) 
    1180     { 
     1126    mutt_buffer_addstr (&cmd, "UID STORE "); 
     1127    deleted = imap_make_msg_set (idata, &cmd, M_DELETED, 1, 0); 
     1128 
     1129    /* if we have a message set, then let's delete */ 
     1130    if (deleted) 
     1131    { 
     1132      mutt_message (_("Marking %d messages deleted..."), deleted); 
     1133      mutt_buffer_addstr (&cmd, " +FLAGS.SILENT (\\Deleted)"); 
    11811134      /* mark these messages as unchanged so second pass ignores them. Done 
    11821135       * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */ 
    11831136      for (n = 0; n < ctx->msgcount; n++) 
    1184         if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed) 
    1185           ctx->hdrs[n]->active = 0; 
    1186       mutt_message (_("Marking %d messages deleted..."), rc); 
     1137        if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed) 
     1138          ctx->hdrs[n]->active = 0; 
     1139      if (imap_exec (idata, cmd.data, 0) != 0) 
     1140      { 
     1141        mutt_error (_("Expunge failed")); 
     1142        mutt_sleep (1); 
     1143        rc = -1; 
     1144        goto out; 
     1145      } 
    11871146    } 
    11881147  } 
     
    12181177          appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL); 
    12191178        if (!appendctx) 
     1179        { 
    12201180          dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n")); 
     1181        } 
    12211182        else 
    12221183          _mutt_save_message (h, appendctx, 1, 0, 0); 
     
    12321193  rc = 0; 
    12331194 
    1234   /* presort here to avoid doing 10 resorts in imap_exec_msgset */ 
     1195  /* presort here to avoid doing 10 resorts in imap_make_msg_set */ 
    12351196  oldsort = Sort; 
    12361197  if (Sort != SORT_ORDER) 
     
    12461207  } 
    12471208 
    1248   rc += sync_helper (idata, M_ACL_DELETE, M_DELETED, "\\Deleted"); 
    1249   rc += sync_helper (idata, M_ACL_WRITE, M_FLAG, "\\Flagged"); 
    1250   rc += sync_helper (idata, M_ACL_WRITE, M_OLD, "Old"); 
    1251   rc += sync_helper (idata, M_ACL_SEEN, M_READ, "\\Seen"); 
    1252   rc += sync_helper (idata, M_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"); 
    12531214 
    12541215  if (oldsort != Sort) 
     
    12591220  } 
    12601221 
    1261   if (rc && (imap_exec (idata, NULL, 0) != IMAP_CMD_OK)) 
    1262   { 
    1263     if (ctx->closing) 
    1264     { 
    1265       if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES) 
     1222  if (rc) 
     1223  { 
     1224    if ((rc = imap_exec (idata, NULL, 0)) != IMAP_CMD_OK) 
     1225    { 
     1226      if (ctx->closing) 
    12661227      { 
    1267         rc = 0; 
    1268         idata->state = IMAP_AUTHENTICATED; 
    1269         goto out; 
     1228        if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES) 
     1229        { 
     1230          rc = 0; 
     1231          idata->state = IMAP_AUTHENTICATED; 
     1232          goto out; 
     1233        } 
    12701234      } 
    1271     } 
    1272     else 
    1273       mutt_error _("Error saving flags"); 
    1274     goto out; 
    1275   } 
    1276  
     1235      else 
     1236        mutt_error _("Error saving flags"); 
     1237      goto out; 
     1238    } 
     1239  } 
    12771240  for (n = 0; n < ctx->msgcount; n++) 
    12781241    ctx->hdrs[n]->changed = 0; 
     
    13061269 
    13071270 out: 
     1271  if (cmd.data) 
     1272    FREE (&cmd.data); 
    13081273  if (appendctx) 
    13091274  { 
  • imap/imap_private.h

    r5498 r5499  
    5656 
    5757#define SEQLEN 5 
    58 /* maximum length of command lines before they must be split (for 
    59  * lazy servers) */ 
    60 #define IMAP_MAX_CMDLEN 1024 
    6158 
    6259#define IMAP_REOPEN_ALLOW     (1<<0) 
     
    229226                                 int create); 
    230227void imap_mboxcache_free (IMAP_DATA* idata); 
    231 int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post, 
    232                       int flag, int changed, int invert); 
     228int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed, 
     229                      int invert); 
    233230int imap_open_connection (IMAP_DATA* idata); 
    234231void imap_close_connection (IMAP_DATA* idata); 
  • imap/message.c

    r5498 r5499  
    689689  IMAP_DATA* idata; 
    690690  BUFFER cmd, sync_cmd; 
     691  char uid[11]; 
    691692  char mbox[LONG_STRING]; 
    692693  char mmbox[LONG_STRING]; 
    693   char prompt[LONG_STRING]; 
    694694  int rc; 
    695695  int n; 
    696696  IMAP_MBOX mx; 
    697697  int err_continue = M_NO; 
    698   int triedcreate = 0; 
    699698 
    700699  idata = (IMAP_DATA*) ctx->data; 
     
    721720   
    722721  imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); 
     722 
     723  memset (&sync_cmd, 0, sizeof (sync_cmd)); 
     724  memset (&cmd, 0, sizeof (cmd)); 
     725  mutt_buffer_addstr (&cmd, "UID COPY "); 
     726 
     727  /* Null HEADER* means copy tagged messages */ 
     728  if (!h) 
     729  { 
     730    /* if any messages have attachments to delete, fall through to FETCH 
     731     * and APPEND. TODO: Copy what we can with COPY, fall through for the 
     732     * remainder. */ 
     733    for (n = 0; n < ctx->msgcount; n++) 
     734    { 
     735      if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->attach_del) 
     736      { 
     737        dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); 
     738        return 1; 
     739      } 
     740 
     741      if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active && 
     742          ctx->hdrs[n]->changed) 
     743      { 
     744        rc = imap_sync_message (idata, ctx->hdrs[n], &sync_cmd, &err_continue); 
     745        if (rc < 0) 
     746        { 
     747          dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); 
     748          goto fail; 
     749        } 
     750      } 
     751    } 
     752 
     753    rc = imap_make_msg_set (idata, &cmd, M_TAG, 0, 0); 
     754    if (!rc) 
     755    { 
     756      dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n")); 
     757      goto fail; 
     758    } 
     759    mutt_message (_("Copying %d messages to %s..."), rc, mbox); 
     760  } 
     761  else 
     762  { 
     763    mutt_message (_("Copying message %d to %s..."), h->index+1, mbox); 
     764    snprintf (uid, sizeof (uid), "%u", HEADER_DATA (h)->uid); 
     765    mutt_buffer_addstr (&cmd, uid); 
     766 
     767    if (h->active && h->changed) 
     768    { 
     769      rc = imap_sync_message (idata, h, &sync_cmd, &err_continue); 
     770      if (rc < 0) 
     771      { 
     772        dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); 
     773        goto fail; 
     774      } 
     775    } 
     776  } 
     777 
     778  /* let's get it on */ 
     779  mutt_buffer_addstr (&cmd, " "); 
    723780  imap_munge_mbox_name (mmbox, sizeof (mmbox), mbox); 
    724  
    725   /* loop in case of TRYCREATE */ 
    726   do 
    727   { 
    728     memset (&sync_cmd, 0, sizeof (sync_cmd)); 
    729     memset (&cmd, 0, sizeof (cmd)); 
    730  
    731     /* Null HEADER* means copy tagged messages */ 
    732     if (!h) 
    733     { 
    734       /* if any messages have attachments to delete, fall through to FETCH 
    735        * and APPEND. TODO: Copy what we can with COPY, fall through for the 
    736        * remainder. */ 
    737       for (n = 0; n < ctx->msgcount; n++) 
    738       { 
    739         if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->attach_del) 
    740         { 
    741           dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); 
    742           return 1; 
    743         } 
    744  
    745         if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active && 
    746             ctx->hdrs[n]->changed) 
    747         { 
    748           rc = imap_sync_message (idata, ctx->hdrs[n], &sync_cmd, &err_continue); 
    749           if (rc < 0) 
    750           { 
    751             dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); 
    752             goto fail; 
    753           } 
    754         } 
    755       } 
    756  
    757       rc = imap_exec_msgset (idata, "UID COPY", mmbox, M_TAG, 0, 0); 
    758       if (!rc) 
    759       { 
    760         dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n")); 
    761         goto fail; 
    762       } 
    763       else if (rc < 0) 
    764       { 
    765         dprint (1, (debugfile, "could not queue copy\n")); 
    766         goto fail; 
    767       } 
    768       else 
    769         mutt_message (_("Copying %d messages to %s..."), rc, mbox); 
    770     } 
    771     else 
    772     { 
    773       mutt_message (_("Copying message %d to %s..."), h->index+1, mbox); 
    774       mutt_buffer_printf (&cmd, "UID COPY %u %s", HEADER_DATA (h)->uid, mmbox); 
    775  
    776       if (h->active && h->changed) 
    777       { 
    778         rc = imap_sync_message (idata, h, &sync_cmd, &err_continue); 
    779         if (rc < 0) 
    780         { 
    781           dprint (1, (debugfile, "imap_copy_messages: could not sync\n")); 
    782           goto fail; 
    783         } 
    784       }     
    785       if ((rc = imap_exec (idata, cmd.data, IMAP_CMD_QUEUE)) < 0) 
    786       { 
    787         dprint (1, (debugfile, "could not queue copy\n")); 
    788         goto fail; 
    789       } 
    790     } 
    791  
    792     /* let's get it on */ 
    793     rc = imap_exec (idata, NULL, IMAP_CMD_FAIL_OK); 
    794     if (rc == -2) 
    795     { 
    796       if (triedcreate) 
    797       { 
    798         dprint (1, (debugfile, "Already tried to create mailbox %s\n", mbox)); 
    799         break; 
    800       } 
    801       /* bail out if command failed for reasons other than nonexistent target */ 
    802       if (ascii_strncasecmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11)) 
    803         break; 
    804       dprint (3, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n")); 
    805       snprintf (prompt, sizeof (prompt), _("Create %s?"), mbox); 
    806       if (option (OPTCONFIRMCREATE) && mutt_yesorno (prompt, 1) < 1) 
    807       { 
    808         mutt_clear_error (); 
    809         break; 
    810       } 
    811       if (imap_create_mailbox (idata, mbox) < 0) 
    812         break; 
    813       triedcreate = 1; 
    814     } 
    815   } 
    816   while (rc == -2); 
    817  
     781  mutt_buffer_addstr (&cmd, mmbox); 
     782 
     783  rc = imap_exec (idata, cmd.data, IMAP_CMD_FAIL_OK); 
     784  if (rc == -2) 
     785  { 
     786    /* bail out if command failed for reasons other than nonexistent target */ 
     787    if (ascii_strncasecmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11)) 
     788    { 
     789      imap_error ("imap_copy_messages", idata->buf); 
     790      goto fail; 
     791    } 
     792    dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n")); 
     793    snprintf (mmbox, sizeof (mmbox), _("Create %s?"), mbox); 
     794    if (option (OPTCONFIRMCREATE) && mutt_yesorno (mmbox, 1) < 1) 
     795    { 
     796      mutt_clear_error (); 
     797      goto fail; 
     798    } 
     799    if (imap_create_mailbox (idata, mbox) < 0) 
     800      goto fail; 
     801 
     802    /* try again */ 
     803    rc = imap_exec (idata, cmd.data, 0); 
     804  } 
    818805  if (rc != 0) 
    819806  {