Changeset 5499:1d94905ad00b for imap
Legend:
- Unmodified
- Added
- Removed
-
imap/command.c
r5498 r5499 197 197 * for checking for a mailbox on append and login 198 198 * IMAP_CMD_PASS: command contains a password. Suppress logging. 199 * IMAP_CMD_QUEUE: only queue command, do not execute.200 199 * Return 0 on success, -1 on Failure, -2 on OK Failure 201 200 */ -
imap/imap.c
r5498 r5499 857 857 } 858 858 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) */ 867 int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed, 868 int invert) 869 { 870 HEADER** hdrs; /* sorted local copy */ 865 871 int count = 0; /* number of messages in message set */ 866 872 int match = 0; /* whether current message matches flag condition */ 867 873 unsigned int setstart = 0; /* start of current message range */ 868 874 int n; 875 short oldsort; /* we clobber reverse, must restore it */ 869 876 int started = 0; 870 877 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; 872 891 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++) 876 893 { 877 894 match = 0; … … 935 952 } 936 953 937 *pos = n;938 939 return count;940 }941 942 /* Prepares commands for all messages matching conditions (must be flushed943 * with imap_exec)944 * Params:945 * idata: IMAP_DATA containing context containing header set946 * pre, post: commands are of the form "%s %s %s %s", tag,947 * pre, message set, post948 * flag: enum of flag type on which to filter949 * changed: include only changed messages in message set950 * invert: invert sense of flag, eg M_READ matches unread messages951 * 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 give969 exactly the original order (duplicate messages?), because other parts of970 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 else983 hdrs = idata->ctx->hdrs;984 985 pos = 0;986 987 do988 {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);1009 954 if (Sort != SORT_ORDER) 1010 955 FREE (&hdrs); 1011 956 1012 return rc;957 return count; 1013 958 } 1014 959 … … 1033 978 1034 979 /* Update the IMAP server to reflect the flags a single message. */ 980 1035 981 int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, 1036 982 int *err_continue) … … 1110 1056 } 1111 1057 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]; 1058 static int sync_helper (IMAP_DATA* idata, BUFFER* buf, int right, int flag, 1059 const char* name) 1060 { 1061 int rc = 0; 1118 1062 1119 1063 if (!mutt_bit_isset (idata->ctx->rights, right)) 1120 1064 return 0; 1121 1065 1122 1066 if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name)) 1123 1067 return 0; 1124 1068 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; 1136 1087 } 1137 1088 … … 1145 1096 IMAP_DATA* idata; 1146 1097 CONTEXT* appendctx = NULL; 1098 BUFFER cmd; 1147 1099 HEADER* h; 1148 1100 HEADER** hdrs = NULL; 1149 1101 int oldsort; 1102 int deleted; 1150 1103 int n; 1151 1104 int rc; … … 1166 1119 return rc; 1167 1120 1121 memset (&cmd, 0, sizeof (cmd)); 1122 1168 1123 /* if we are expunging anyway, we can do deleted messages very quickly... */ 1169 1124 if (expunge && mutt_bit_isset (idata->ctx->rights, M_ACL_DELETE)) 1170 1125 { 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)"); 1181 1134 /* mark these messages as unchanged so second pass ignores them. Done 1182 1135 * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */ 1183 1136 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 } 1187 1146 } 1188 1147 } … … 1218 1177 appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL); 1219 1178 if (!appendctx) 1179 { 1220 1180 dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n")); 1181 } 1221 1182 else 1222 1183 _mutt_save_message (h, appendctx, 1, 0, 0); … … 1232 1193 rc = 0; 1233 1194 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 */ 1235 1196 oldsort = Sort; 1236 1197 if (Sort != SORT_ORDER) … … 1246 1207 } 1247 1208 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"); 1253 1214 1254 1215 if (oldsort != Sort) … … 1259 1220 } 1260 1221 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) 1266 1227 { 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 } 1270 1234 } 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 } 1277 1240 for (n = 0; n < ctx->msgcount; n++) 1278 1241 ctx->hdrs[n]->changed = 0; … … 1306 1269 1307 1270 out: 1271 if (cmd.data) 1272 FREE (&cmd.data); 1308 1273 if (appendctx) 1309 1274 { -
imap/imap_private.h
r5498 r5499 56 56 57 57 #define SEQLEN 5 58 /* maximum length of command lines before they must be split (for59 * lazy servers) */60 #define IMAP_MAX_CMDLEN 102461 58 62 59 #define IMAP_REOPEN_ALLOW (1<<0) … … 229 226 int create); 230 227 void 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);228 int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed, 229 int invert); 233 230 int imap_open_connection (IMAP_DATA* idata); 234 231 void imap_close_connection (IMAP_DATA* idata); -
imap/message.c
r5498 r5499 689 689 IMAP_DATA* idata; 690 690 BUFFER cmd, sync_cmd; 691 char uid[11]; 691 692 char mbox[LONG_STRING]; 692 693 char mmbox[LONG_STRING]; 693 char prompt[LONG_STRING];694 694 int rc; 695 695 int n; 696 696 IMAP_MBOX mx; 697 697 int err_continue = M_NO; 698 int triedcreate = 0;699 698 700 699 idata = (IMAP_DATA*) ctx->data; … … 721 720 722 721 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, " "); 723 780 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 } 818 805 if (rc != 0) 819 806 {
