Changeset 5498:e68f79fef249 for imap
Legend:
- Unmodified
- Added
- Removed
-
imap/command.c
r5495 r5498 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. 199 200 * Return 0 on success, -1 on Failure, -2 on OK Failure 200 201 */ -
imap/imap.c
r5496 r5498 857 857 } 858 858 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 */ 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; 871 865 int count = 0; /* number of messages in message set */ 872 866 int match = 0; /* whether current message matches flag condition */ 873 867 unsigned int setstart = 0; /* start of current message range */ 874 868 int n; 875 short oldsort; /* we clobber reverse, must restore it */876 869 int started = 0; 877 870 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; 871 hdrs = idata->ctx->hdrs; 891 872 892 for (n = 0; n < idata->ctx->msgcount; n++) 873 for (n = *pos; 874 n < idata->ctx->msgcount && buf->dptr - buf->data < IMAP_MAX_CMDLEN; 875 n++) 893 876 { 894 877 match = 0; … … 952 935 } 953 936 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); 954 1009 if (Sort != SORT_ORDER) 955 1010 FREE (&hdrs); 956 1011 957 return count;1012 return rc; 958 1013 } 959 1014 … … 978 1033 979 1034 /* Update the IMAP server to reflect the flags a single message. */ 980 981 1035 int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, 982 1036 int *err_continue) … … 1056 1110 } 1057 1111 1058 static int sync_helper (IMAP_DATA* idata, BUFFER* buf, int right, int flag, 1059 const char* name) 1060 { 1061 int rc = 0; 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]; 1062 1118 1063 1119 if (!mutt_bit_isset (idata->ctx->rights, right)) 1064 1120 return 0; 1065 1121 1066 1122 if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name)) 1067 1123 return 0; 1068 1124 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; 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; 1087 1136 } 1088 1137 … … 1096 1145 IMAP_DATA* idata; 1097 1146 CONTEXT* appendctx = NULL; 1098 BUFFER cmd;1099 1147 HEADER* h; 1100 1148 HEADER** hdrs = NULL; 1101 1149 int oldsort; 1102 int deleted;1103 1150 int n; 1104 1151 int rc; … … 1119 1166 return rc; 1120 1167 1121 memset (&cmd, 0, sizeof (cmd));1122 1123 1168 /* if we are expunging anyway, we can do deleted messages very quickly... */ 1124 1169 if (expunge && mutt_bit_isset (idata->ctx->rights, M_ACL_DELETE)) 1125 1170 { 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)"); 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 { 1134 1181 /* mark these messages as unchanged so second pass ignores them. Done 1135 1182 * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */ 1136 1183 for (n = 0; n < ctx->msgcount; n++) 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 } 1184 if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed) 1185 ctx->hdrs[n]->active = 0; 1186 mutt_message (_("Marking %d messages deleted..."), rc); 1146 1187 } 1147 1188 } … … 1177 1218 appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL); 1178 1219 if (!appendctx) 1179 {1180 1220 dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n")); 1181 }1182 1221 else 1183 1222 _mutt_save_message (h, appendctx, 1, 0, 0); … … 1193 1232 rc = 0; 1194 1233 1195 /* presort here to avoid doing 10 resorts in imap_ make_msg_set */1234 /* presort here to avoid doing 10 resorts in imap_exec_msgset */ 1196 1235 oldsort = Sort; 1197 1236 if (Sort != SORT_ORDER) … … 1207 1246 } 1208 1247 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");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"); 1214 1253 1215 1254 if (oldsort != Sort) … … 1220 1259 } 1221 1260 1222 if (rc )1223 { 1224 if ( (rc = imap_exec (idata, NULL, 0)) != IMAP_CMD_OK)1225 { 1226 if ( ctx->closing)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) 1227 1266 { 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 } 1267 rc = 0; 1268 idata->state = IMAP_AUTHENTICATED; 1269 goto out; 1234 1270 } 1235 else 1236 mutt_error _("Error saving flags"); 1237 goto out; 1238 } 1239 } 1271 } 1272 else 1273 mutt_error _("Error saving flags"); 1274 goto out; 1275 } 1276 1240 1277 for (n = 0; n < ctx->msgcount; n++) 1241 1278 ctx->hdrs[n]->changed = 0; … … 1269 1306 1270 1307 out: 1271 if (cmd.data)1272 FREE (&cmd.data);1273 1308 if (appendctx) 1274 1309 { -
imap/imap_private.h
r5495 r5498 56 56 57 57 #define SEQLEN 5 58 /* maximum length of command lines before they must be split (for 59 * lazy servers) */ 60 #define IMAP_MAX_CMDLEN 1024 58 61 59 62 #define IMAP_REOPEN_ALLOW (1<<0) … … 226 229 int create); 227 230 void imap_mboxcache_free (IMAP_DATA* idata); 228 int imap_ make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed,229 int invert);231 int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post, 232 int flag, int changed, int invert); 230 233 int imap_open_connection (IMAP_DATA* idata); 231 234 void imap_close_connection (IMAP_DATA* idata); -
imap/message.c
r5494 r5498 689 689 IMAP_DATA* idata; 690 690 BUFFER cmd, sync_cmd; 691 char uid[11];692 691 char mbox[LONG_STRING]; 693 692 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; 698 699 699 700 idata = (IMAP_DATA*) ctx->data; … … 720 721 721 722 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) 723 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++) 736 738 { 737 dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); 738 return 1; 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 } 739 755 } 740 756 741 if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active &&742 ctx->hdrs[n]->changed)757 rc = imap_exec_msgset (idata, "UID COPY", mmbox, M_TAG, 0, 0); 758 if (!rc) 743 759 { 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 } 760 dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n")); 761 goto fail; 750 762 } 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) 763 else if (rc < 0) 771 764 { 772 dprint (1, (debugfile, "imap_copy_messages: could not sync\n"));773 goto fail;765 dprint (1, (debugfile, "could not queue copy\n")); 766 goto fail; 774 767 } 775 } 776 } 777 778 /* let's get it on */ 779 mutt_buffer_addstr (&cmd, " "); 780 imap_munge_mbox_name (mmbox, sizeof (mmbox), mbox); 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 } 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 805 818 if (rc != 0) 806 819 {
