Changeset 4465:11d366f0c81a
- Timestamp:
- 2005-12-11 14:51:29 (3 years ago)
- Branch:
- HEAD
- Files:
-
- 6 modified
-
buffy.c (modified) (3 diffs)
-
imap/command.c (modified) (8 diffs)
-
imap/imap.c (modified) (3 diffs)
-
imap/imap.h (modified) (1 diff)
-
imap/imap_private.h (modified) (3 diffs)
-
imap/util.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
buffy.c
r4439 r4465 287 287 288 288 #ifdef USE_IMAP 289 BuffyCount += imap_buffy_check (force); 290 289 291 if (!Context || Context->magic != M_IMAP) 290 292 #endif … … 301 303 for (tmp = Incoming; tmp; tmp = tmp->next) 302 304 { 305 #ifndef USE_IMAP 303 306 tmp->new = 0; 304 305 #ifdef USE_IMAP 306 if (mx_is_imap (tmp->path)) 307 tmp->magic = M_IMAP; 308 else 309 #endif 307 #endif 308 310 309 #ifdef USE_POP 311 310 if (mx_is_pop (tmp->path)) … … 399 398 BuffyCount++; 400 399 break; 401 402 #ifdef USE_IMAP403 case M_IMAP:404 if ((tmp->new = imap_mailbox_check (tmp->path, 1)) > 0)405 BuffyCount++;406 else407 tmp->new = 0;408 409 break;410 #endif411 412 #ifdef USE_POP413 case M_POP:414 break;415 #endif416 400 } 417 401 } -
imap/command.c
r4464 r4465 30 30 #include "message.h" 31 31 #include "mx.h" 32 #include "buffy.h" 32 33 33 34 #include <ctype.h> … … 47 48 static void cmd_parse_myrights (IMAP_DATA* idata, const char* s); 48 49 static void cmd_parse_search (IMAP_DATA* idata, const char* s); 50 static void cmd_parse_status (IMAP_DATA* idata, char* s); 49 51 50 52 static char *Capabilities[] = { … … 63 65 }; 64 66 65 /* imap_cmd_start: Given an IMAP command, send it to the server. 66 * Currently a minor convenience, but helps to route all IMAP commands 67 * through a single interface. */ 68 int imap_cmd_start (IMAP_DATA* idata, const char* cmdstr) 67 /* imap_cmd_queue: Add command to command queue. Fails if the queue is full. */ 68 int imap_cmd_queue (IMAP_DATA* idata, const char* cmdstr) 69 69 { 70 70 IMAP_COMMAND* cmd; 71 char* out; 72 int outlen; 73 int rc; 71 unsigned int cmdlen; 74 72 75 73 if (idata->status == IMAP_FATAL) … … 81 79 if (!(cmd = cmd_new (idata))) 82 80 return IMAP_CMD_BAD; 83 81 84 82 /* seq, space, cmd, \r\n\0 */ 85 outlen = strlen (cmd->seq) + strlen (cmdstr) + 4; 86 out = (char*) safe_malloc (outlen); 87 snprintf (out, outlen, "%s %s\r\n", cmd->seq, cmdstr); 88 89 rc = mutt_socket_write (idata->conn, out); 90 91 FREE (&out); 83 cmdlen = strlen (cmd->seq) + strlen (cmdstr) + 4; 84 if (idata->cmdbuflen < cmdlen + (idata->cmdtail - idata->cmdbuf)) 85 { 86 unsigned int tailoff = idata->cmdtail - idata->cmdbuf; 87 safe_realloc (&idata->cmdbuf, tailoff + cmdlen); 88 idata->cmdbuflen = tailoff + cmdlen; 89 idata->cmdtail = idata->cmdbuf + tailoff; 90 } 91 snprintf (idata->cmdtail, cmdlen, "%s %s\r\n", cmd->seq, cmdstr); 92 idata->cmdtail += cmdlen - 1; 93 94 return 0; 95 } 96 97 /* imap_cmd_start: Given an IMAP command, send it to the server. 98 * If cmdstr is NULL, sends queued commands. */ 99 int imap_cmd_start (IMAP_DATA* idata, const char* cmdstr) 100 { 101 int rc; 102 103 if (cmdstr && (rc = imap_cmd_queue (idata, cmdstr)) < 0) 104 return rc; 105 106 /* don't write old or empty commands */ 107 if (idata->cmdtail == idata->cmdbuf) 108 return IMAP_CMD_BAD; 109 110 rc = mutt_socket_write (idata->conn, idata->cmdbuf); 111 idata->cmdtail = idata->cmdbuf; 92 112 93 113 return (rc < 0) ? IMAP_CMD_BAD : 0; … … 190 210 int imap_exec (IMAP_DATA* idata, const char* cmdstr, int flags) 191 211 { 192 IMAP_COMMAND* cmd;193 char* out;194 int outlen;195 212 int rc; 196 213 … … 201 218 } 202 219 203 if (!(cmd = cmd_new (idata))) 204 return -1; 205 206 /* seq, space, cmd, \r\n\0 */ 207 outlen = strlen (cmd->seq) + strlen (cmdstr) + 4; 208 out = (char*) safe_malloc (outlen); 209 snprintf (out, outlen, "%s %s\r\n", cmd->seq, cmdstr); 210 211 rc = mutt_socket_write_d (idata->conn, out, 220 if (cmdstr && (rc = imap_cmd_queue (idata, cmdstr)) < 0) 221 return rc; 222 223 /* don't write old or empty commands */ 224 if (idata->cmdtail == idata->cmdbuf) 225 return IMAP_CMD_BAD; 226 227 rc = mutt_socket_write_d (idata->conn, idata->cmdbuf, 212 228 flags & IMAP_CMD_PASS ? IMAP_LOG_PASS : IMAP_LOG_CMD); 213 FREE (&out);229 idata->cmdtail = idata->cmdbuf; 214 230 215 231 if (rc < 0) … … 408 424 else if (ascii_strncasecmp ("SEARCH", s, 6) == 0) 409 425 cmd_parse_search (idata, s); 426 else if (ascii_strncasecmp ("STATUS", s, 6) == 0) 427 cmd_parse_status (idata, s); 410 428 else if (ascii_strncasecmp ("BYE", s, 3) == 0) 411 429 { … … 689 707 } 690 708 } 709 710 /* first cut: just do buffy update. Later we may wish to cache all 711 * mailbox information, even that not desired by buffy */ 712 static void cmd_parse_status (IMAP_DATA* idata, char* s) 713 { 714 char* mailbox; 715 BUFFY* inc; 716 IMAP_MBOX mx; 717 int count; 718 719 dprint (2, (debugfile, "Handling STATUS\n")); 720 721 mailbox = imap_next_word (s); 722 s = imap_next_word (mailbox); 723 *(s - 1) = '\0'; 724 725 imap_unmunge_mbox_name (mailbox); 726 727 for (inc = Incoming; inc; inc = inc->next) 728 { 729 if (inc->magic != M_IMAP) 730 continue; 731 732 if (imap_parse_path (inc->path, &mx) < 0) 733 { 734 dprint (1, (debugfile, "Error parsing mailbox %s, skipping\n", inc->path)); 735 continue; 736 } 737 738 if (mutt_account_match (&idata->conn->account, &mx.account) && mx.mbox 739 && strncmp (mailbox, mx.mbox, strlen (mailbox)) == 0) 740 { 741 if (*s++ != '(') 742 { 743 dprint (1, (debugfile, "Error parsing STATUS\n")); 744 FREE (&mx.mbox); 745 return; 746 } 747 748 while (*s && *s != ')') 749 { 750 if (!ascii_strncmp ("RECENT", s, 6)) 751 { 752 s = imap_next_word (s); 753 count = strtol (s, &s, 10); 754 dprint (2, (debugfile, "%d recent in %s\n", count, mx.mbox)); 755 inc->new = count; 756 } 757 else if (!ascii_strncmp ("UNSEEN", s, 6)) 758 { 759 s = imap_next_word (s); 760 count = strtol (s, &s, 10); 761 dprint (2, (debugfile, "%d unseen in %s\n", count, mx.mbox)); 762 } 763 else if (!ascii_strncmp ("MESSAGES", s, 8)) 764 { 765 s = imap_next_word (s); 766 count = strtol (s, &s, 10); 767 dprint (2, (debugfile, "%d messages in %s\n", count, mx.mbox)); 768 } 769 } 770 771 return; 772 } 773 774 FREE (&mx.mbox); 775 } 776 } -
imap/imap.c
r4464 r4465 1205 1205 } 1206 1206 1207 /* split path into (idata,mailbox name) */ 1208 static int imap_buffy_split (const char* path, IMAP_DATA** hidata, char* buf, size_t blen) 1209 { 1210 IMAP_MBOX mx; 1211 1212 if (imap_parse_path (path, &mx)) 1213 { 1214 dprint (1, (debugfile, "imap_split_path: Error parsing %s\n", path)); 1215 return -1; 1216 } 1217 if (!(*hidata = imap_conn_find (&(mx.account), option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0))) 1218 { 1219 FREE (&mx.mbox); 1220 return -1; 1221 } 1222 1223 imap_fix_path (*hidata, mx.mbox, buf, blen); 1224 FREE (&mx.mbox); 1225 1226 return 0; 1227 } 1228 1229 /* check for new mail in any subscribed mailboxes. Given a list of mailboxes 1230 * rather than called once for each so that it can batch the commands and 1231 * save on round trips. Returns number of mailboxes with new mail. */ 1232 int imap_buffy_check (int force) 1233 { 1234 IMAP_DATA* idata; 1235 IMAP_DATA* lastdata = NULL; 1236 BUFFY* mailbox; 1237 char name[LONG_STRING]; 1238 char command[LONG_STRING]; 1239 char munged[LONG_STRING]; 1240 int buffies = 0; 1241 int rc; 1242 1243 for (mailbox = Incoming; mailbox; mailbox = mailbox->next) 1244 { 1245 /* Init newly-added mailboxes */ 1246 if (! mailbox->magic) 1247 { 1248 if (mx_is_imap (mailbox->path)) 1249 mailbox->magic = M_IMAP; 1250 } 1251 1252 if (mailbox->magic != M_IMAP) 1253 continue; 1254 1255 mailbox->new = 0; 1256 1257 if (imap_buffy_split (mailbox->path, &idata, name, sizeof (name)) < 0) 1258 continue; 1259 1260 /* Don't issue STATUS on the selected mailbox, it will be NOOPed or 1261 * IDLEd elsewhere */ 1262 if (mutt_strcmp (name, idata->mailbox) == 0 1263 || (ascii_strcasecmp (name, "INBOX") == 0 1264 && mutt_strcasecmp (name, idata->mailbox) == 0)) 1265 continue; 1266 1267 if (!lastdata) 1268 lastdata = idata; 1269 1270 if (idata != lastdata) 1271 { 1272 /* Send commands to previous server. Sorting the buffy list 1273 * may prevent some infelicitous interleavings */ 1274 if (imap_exec (lastdata, NULL, 0) != IMAP_CMD_OK) 1275 dprint (1, (debugfile, "Error polling mailboxes\n")); 1276 1277 lastdata = NULL; 1278 } 1279 1280 if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) && 1281 !mutt_bit_isset (idata->capabilities, STATUS)) 1282 { 1283 dprint (2, (debugfile, "Server doesn't support STATUS\n")); 1284 continue; 1285 } 1286 1287 imap_munge_mbox_name (munged, sizeof (munged), name); 1288 /* we need a better way to detect new mail... */ 1289 snprintf (command, sizeof (command), "STATUS %s (RECENT)", munged); 1290 1291 if (imap_cmd_queue (idata, command) < 0) 1292 { 1293 /* pipeline must be full, drain it */ 1294 dprint (2, (debugfile, "IMAP command pipeline full, draining\n")); 1295 1296 if (imap_exec (idata, NULL, 0) != IMAP_CMD_OK) 1297 dprint (1, (debugfile, "Error polling mailboxes\n")); 1298 1299 if (imap_cmd_queue (idata, command) < 0) { 1300 /* real trouble */ 1301 dprint (1, (debugfile, "Error queueing command\n")); 1302 return 0; 1303 } 1304 } 1305 } 1306 1307 if (lastdata && (imap_exec (lastdata, NULL, 0) != IMAP_CMD_OK)) 1308 { 1309 dprint (1, (debugfile, "Error polling mailboxes")); 1310 return 0; 1311 } 1312 1313 /* collect results */ 1314 for (mailbox = Incoming; mailbox; mailbox = mailbox->next) 1315 { 1316 if (mailbox->magic == M_IMAP && mailbox->new) 1317 buffies++; 1318 } 1319 1320 return buffies; 1321 } 1322 1207 1323 /* returns count of recent messages if new = 1, else count of total messages. 1208 1324 * (useful for at least postponed function) … … 1218 1334 char mbox[LONG_STRING]; 1219 1335 char mbox_unquoted[LONG_STRING]; 1220 char *s;1221 int msgcount = 0;1222 1336 int connflags = 0; 1223 1337 IMAP_MBOX mx; 1224 1338 int rc; 1339 BUFFY* buffy; 1225 1340 1226 1341 if (imap_parse_path (path, &mx)) … … 1267 1382 imap_cmd_start (idata, buf); 1268 1383 1269 do 1270 { 1271 if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) 1272 break; 1273 1274 s = imap_next_word (idata->buf); 1275 if (ascii_strncasecmp ("STATUS", s, 6) == 0) 1276 { 1277 s = imap_next_word (s); 1278 /* The mailbox name may or may not be quoted here. We could try to 1279 * munge the server response and compare with quoted (or vise versa) 1280 * but it is probably more efficient to just strncmp against both. */ 1281 if (mutt_strncmp (mbox_unquoted, s, mutt_strlen (mbox_unquoted)) == 0 1282 || mutt_strncmp (mbox, s, mutt_strlen (mbox)) == 0) 1283 { 1284 s = imap_next_word (s); 1285 s = imap_next_word (s); 1286 if (isdigit ((unsigned char) *s)) 1287 { 1288 if (*s != '0') 1289 { 1290 msgcount = atoi(s); 1291 dprint (2, (debugfile, "%d new messages in %s\n", msgcount, path)); 1292 } 1293 } 1294 } 1295 else 1296 dprint (1, (debugfile, "imap_mailbox_check: STATUS response doesn't match requested mailbox.\n")); 1297 } 1298 } 1384 do 1385 rc = imap_cmd_step (idata); 1299 1386 while (rc == IMAP_CMD_CONTINUE); 1300 1387 1301 return msgcount; 1388 for (buffy = Incoming; buffy; buffy = buffy->next) 1389 { 1390 if (!strncmp (buffy->path, path, strlen (path))) 1391 return buffy->new; 1392 } 1393 1394 return 0; 1302 1395 } 1303 1396 -
imap/imap.h
r4343 r4465 40 40 int imap_sync_mailbox (CONTEXT *ctx, int expunge, int *index_hint); 41 41 void imap_close_mailbox (CONTEXT *ctx); 42 int imap_buffy_check ( char *path);42 int imap_buffy_check (int force); 43 43 int imap_mailbox_check (char *path, int new); 44 44 int imap_search (CONTEXT* ctx, const pattern_t* pat); -
imap/imap_private.h
r4464 r4465 51 51 #define IMAP_CACHE_LEN 10 52 52 53 /* number of commands that can be batched into a single request */ 54 #define IMAP_PIPELINE_DEPTH 10 53 /* number of commands that can be batched into a single request 54 * ( - 1, for the easy way to detect ring buffer wrap) */ 55 #define IMAP_PIPELINE_DEPTH 11 55 56 56 57 #define SEQLEN 5 … … 178 179 int nextcmd; 179 180 int lastcmd; 181 char* cmdbuf; 182 char* cmdtail; 183 unsigned int cmdbuflen; 180 184 181 185 /* The following data is all specific to the currently SELECTED mbox */ … … 219 223 220 224 /* command.c */ 225 int imap_cmd_queue (IMAP_DATA* idata, const char* cmdstr); 221 226 int imap_cmd_start (IMAP_DATA* idata, const char* cmd); 222 227 int imap_cmd_step (IMAP_DATA* idata); -
imap/util.c
r4464 r4465 326 326 char* imap_get_qualifier (char* buf) 327 327 { 328 c onst char *s = buf;328 char *s = buf; 329 329 330 330 /* skip tag */
