* mailbox/folder_imap.c (imap_flags): Bailout at the matching
LPAREN. * mailbox/header.c (header_get_fvalue): Return 0 in the number of byte return argument even when no header is found. (header_get_value): Likewised. * mailbox/mbx_imap.c (imap_header_get_fvalue): Also cache the message size and the FLAGS. (imap_message_size): If we already have the size do not request it again.
Showing
4 changed files
with
64 additions
and
28 deletions
1 | 2001-10-05 Alain Magloire | ||
2 | |||
3 | * mailbox/folder_imap.c (imap_flags): Bailout at the matching | ||
4 | LPAREN. | ||
5 | * mailbox/header.c (header_get_fvalue): Return 0 in the | ||
6 | number of byte return argument even when no header is found. | ||
7 | (header_get_value): Likewised. | ||
8 | |||
9 | * mailbox/mbx_imap.c (imap_header_get_fvalue): Also cache | ||
10 | the message size and the FLAGS. | ||
11 | (imap_message_size): If we already have the size do not request | ||
12 | it again. | ||
13 | |||
1 | 2001-10-05 Sergey Poznyakoff | 14 | 2001-10-05 Sergey Poznyakoff |
2 | 15 | ||
3 | * guimb/scm/Makefile.am: Added reject.scm. | 16 | * guimb/scm/Makefile.am: Added reject.scm. | ... | ... |
... | @@ -1232,34 +1232,42 @@ imap_bodystructure (f_imap_t f_imap, char **ptr) | ... | @@ -1232,34 +1232,42 @@ imap_bodystructure (f_imap_t f_imap, char **ptr) |
1232 | static int | 1232 | static int |
1233 | imap_flags (f_imap_t f_imap, char **ptr) | 1233 | imap_flags (f_imap_t f_imap, char **ptr) |
1234 | { | 1234 | { |
1235 | char *flag; | 1235 | char *start_flag; |
1236 | char *end_flag; | ||
1236 | /* msg_imap may be null for an untag response deal with it. */ | 1237 | /* msg_imap may be null for an untag response deal with it. */ |
1237 | msg_imap_t msg_imap = f_imap->callback.msg_imap; | 1238 | msg_imap_t msg_imap = f_imap->callback.msg_imap; |
1238 | 1239 | ||
1239 | /* Skip space. */ | 1240 | /* Skip space. */ |
1240 | while (**ptr == ' ') | 1241 | while (**ptr == ' ') |
1241 | (*ptr)++; | 1242 | (*ptr)++; |
1243 | |||
1242 | /* Skip LPAREN. */ | 1244 | /* Skip LPAREN. */ |
1243 | if (**ptr == '(') | 1245 | if (**ptr == '(') |
1244 | (*ptr)++; | 1246 | (*ptr)++; |
1245 | for (;**ptr && **ptr != ')'; ++(*ptr)) | 1247 | |
1248 | /* Go through the list and break on ')' */ | ||
1249 | do | ||
1246 | { | 1250 | { |
1247 | /* Skip space before next word. */ | 1251 | /* Skip space before next word. */ |
1248 | while (**ptr == ' ') | 1252 | while (**ptr == ' ') |
1249 | (*ptr)++; | 1253 | (*ptr)++; |
1254 | |||
1250 | /* Save the beginning of the word. */ | 1255 | /* Save the beginning of the word. */ |
1251 | flag = *ptr; | 1256 | start_flag = *ptr; |
1257 | |||
1252 | /* Get the next word boundary. */ | 1258 | /* Get the next word boundary. */ |
1253 | while (**ptr && **ptr != ' ' && **ptr != ')') | 1259 | while (**ptr && **ptr != ' ' && **ptr != ')') |
1254 | ++*ptr; | 1260 | ++(*ptr); |
1261 | |||
1255 | /* Make a C string for the strcasecmp. */ | 1262 | /* Make a C string for the strcasecmp. */ |
1256 | **ptr = '\0'; | 1263 | end_flag = *ptr; |
1264 | |||
1257 | /* Bail out. */ | 1265 | /* Bail out. */ |
1258 | if (*flag == '\0') | 1266 | if (*start_flag == '\0') |
1259 | break; | 1267 | break; |
1260 | 1268 | ||
1261 | /* Guess the flag. */ | 1269 | /* Guess the flag. */ |
1262 | if (strcasecmp (flag, "\\Seen") == 0) | 1270 | if (strncasecmp (start_flag, "\\Seen", end_flag - start_flag) == 0) |
1263 | { | 1271 | { |
1264 | if (msg_imap) | 1272 | if (msg_imap) |
1265 | { | 1273 | { |
... | @@ -1269,28 +1277,28 @@ imap_flags (f_imap_t f_imap, char **ptr) | ... | @@ -1269,28 +1277,28 @@ imap_flags (f_imap_t f_imap, char **ptr) |
1269 | else | 1277 | else |
1270 | f_imap->flags |= MU_ATTRIBUTE_SEEN; | 1278 | f_imap->flags |= MU_ATTRIBUTE_SEEN; |
1271 | } | 1279 | } |
1272 | else if (strcasecmp (flag, "\\Answered") == 0) | 1280 | else if (strncasecmp (start_flag, "\\Answered", end_flag - start_flag) == 0) |
1273 | { | 1281 | { |
1274 | if (msg_imap) | 1282 | if (msg_imap) |
1275 | msg_imap->flags |= MU_ATTRIBUTE_ANSWERED; | 1283 | msg_imap->flags |= MU_ATTRIBUTE_ANSWERED; |
1276 | else | 1284 | else |
1277 | f_imap->flags |= MU_ATTRIBUTE_ANSWERED; | 1285 | f_imap->flags |= MU_ATTRIBUTE_ANSWERED; |
1278 | } | 1286 | } |
1279 | else if (strcasecmp (flag, "\\Flagged") == 0) | 1287 | else if (strncasecmp (start_flag, "\\Flagged", end_flag - start_flag) == 0) |
1280 | { | 1288 | { |
1281 | if (msg_imap) | 1289 | if (msg_imap) |
1282 | msg_imap->flags |= MU_ATTRIBUTE_FLAGGED; | 1290 | msg_imap->flags |= MU_ATTRIBUTE_FLAGGED; |
1283 | else | 1291 | else |
1284 | f_imap->flags |= MU_ATTRIBUTE_FLAGGED; | 1292 | f_imap->flags |= MU_ATTRIBUTE_FLAGGED; |
1285 | } | 1293 | } |
1286 | else if (strcasecmp (flag, "\\Deleted") == 0) | 1294 | else if (strncasecmp (start_flag, "\\Deleted", end_flag - start_flag) == 0) |
1287 | { | 1295 | { |
1288 | if (msg_imap) | 1296 | if (msg_imap) |
1289 | msg_imap->flags |= MU_ATTRIBUTE_DELETED; | 1297 | msg_imap->flags |= MU_ATTRIBUTE_DELETED; |
1290 | else | 1298 | else |
1291 | f_imap->flags |= MU_ATTRIBUTE_DELETED; | 1299 | f_imap->flags |= MU_ATTRIBUTE_DELETED; |
1292 | } | 1300 | } |
1293 | else if (strcasecmp (flag, "\\Draft") == 0) | 1301 | else if (strncasecmp (start_flag, "\\Draft", end_flag - start_flag) == 0) |
1294 | { | 1302 | { |
1295 | if (msg_imap) | 1303 | if (msg_imap) |
1296 | msg_imap->flags |= MU_ATTRIBUTE_DRAFT; | 1304 | msg_imap->flags |= MU_ATTRIBUTE_DRAFT; |
... | @@ -1298,6 +1306,9 @@ imap_flags (f_imap_t f_imap, char **ptr) | ... | @@ -1298,6 +1306,9 @@ imap_flags (f_imap_t f_imap, char **ptr) |
1298 | f_imap->flags |= MU_ATTRIBUTE_DRAFT; | 1306 | f_imap->flags |= MU_ATTRIBUTE_DRAFT; |
1299 | } | 1307 | } |
1300 | } | 1308 | } |
1309 | while (**ptr && **ptr != ')'); | ||
1310 | if (**ptr == ')') | ||
1311 | (*ptr)++; | ||
1301 | return 0; | 1312 | return 0; |
1302 | } | 1313 | } |
1303 | 1314 | ||
... | @@ -1306,6 +1317,7 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1306,6 +1317,7 @@ imap_body (f_imap_t f_imap, char **ptr) |
1306 | { | 1317 | { |
1307 | int status; | 1318 | int status; |
1308 | 1319 | ||
1320 | /* Skip leading spaces. */ | ||
1309 | while (**ptr && **ptr == ' ') | 1321 | while (**ptr && **ptr == ' ') |
1310 | (*ptr)++; | 1322 | (*ptr)++; |
1311 | 1323 | ||
... | @@ -1322,8 +1334,10 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1322,8 +1334,10 @@ imap_body (f_imap_t f_imap, char **ptr) |
1322 | section[len] = '\0'; | 1334 | section[len] = '\0'; |
1323 | /* strupper. */ | 1335 | /* strupper. */ |
1324 | for (; *p; p++) | 1336 | for (; *p; p++) |
1337 | { | ||
1325 | if (isalpha((unsigned)*p)) | 1338 | if (isalpha((unsigned)*p)) |
1326 | *p = toupper ((unsigned)*p); | 1339 | *p = toupper ((unsigned)*p); |
1340 | } | ||
1327 | /* Check to see the callback type to update the line count. */ | 1341 | /* Check to see the callback type to update the line count. */ |
1328 | if (!strstr (section, "FIELD")) | 1342 | if (!strstr (section, "FIELD")) |
1329 | { | 1343 | { | ... | ... |
... | @@ -409,23 +409,24 @@ header_get_fvalue (header_t header, const char *name, char *buffer, | ... | @@ -409,23 +409,24 @@ header_get_fvalue (header_t header, const char *name, char *buffer, |
409 | for (i = 0, name_len = strlen (name); i < header->fhdr_count; i++) | 409 | for (i = 0, name_len = strlen (name); i < header->fhdr_count; i++) |
410 | { | 410 | { |
411 | fn_len = header->fhdr[i].fn_end - header->fhdr[i].fn; | 411 | fn_len = header->fhdr[i].fn_end - header->fhdr[i].fn; |
412 | if (fn_len == name_len | 412 | if (fn_len == name_len && strcasecmp (header->fhdr[i].fn, name) == 0) |
413 | && strcasecmp (header->fhdr[i].fn, name) == 0) | ||
414 | { | 413 | { |
415 | fv_len = header->fhdr[i].fv_end - header->fhdr[i].fv; | 414 | fv_len = header->fhdr[i].fv_end - header->fhdr[i].fv; |
416 | 415 | ||
417 | /* Permanent failure. */ | 416 | /* Permanent failure: If the field exist but the value is NULL |
417 | It is a way to notify that the field dow not exist. | ||
418 | The value EINVAL is return no ENOENT to let header_get_value() | ||
419 | know about the error. */ | ||
418 | if (fv_len == 0) | 420 | if (fv_len == 0) |
419 | return EINVAL; | 421 | err = EINVAL; |
420 | 422 | else if (buffer && buflen > 0) | |
421 | if (buffer && buflen > 0) | ||
422 | { | 423 | { |
423 | buflen--; | 424 | buflen--; |
424 | fv_len = (fv_len < buflen) ? fv_len : buflen; | 425 | fv_len = (fv_len < buflen) ? fv_len : buflen; |
425 | memcpy (buffer, header->fhdr[i].fv, fv_len); | 426 | memcpy (buffer, header->fhdr[i].fv, fv_len); |
426 | buffer[fv_len] = '\0'; | 427 | buffer[fv_len] = '\0'; |
427 | } | ||
428 | err = 0; | 428 | err = 0; |
429 | } | ||
429 | break; | 430 | break; |
430 | } | 431 | } |
431 | } | 432 | } |
... | @@ -452,11 +453,13 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -452,11 +453,13 @@ header_get_value (header_t header, const char *name, char *buffer, |
452 | err = header_get_fvalue (header, name, buffer, buflen, pn); | 453 | err = header_get_fvalue (header, name, buffer, buflen, pn); |
453 | switch (err) | 454 | switch (err) |
454 | { | 455 | { |
456 | case ENOENT: | ||
457 | break; /* Do not give up just yet. */ | ||
455 | case EINVAL: /* Permanent failure. */ | 458 | case EINVAL: /* Permanent failure. */ |
456 | return ENOENT; | 459 | err = ENOENT; |
457 | case 0: | 460 | default: |
458 | return 0; | 461 | if (err && pn) |
459 | case ENOMEM: | 462 | *pn = 0; |
460 | return err; | 463 | return err; |
461 | } | 464 | } |
462 | 465 | ... | ... |
... | @@ -1008,7 +1008,7 @@ imap_message_size (message_t msg, size_t *psize) | ... | @@ -1008,7 +1008,7 @@ imap_message_size (message_t msg, size_t *psize) |
1008 | msg_imap_t msg_imap = message_get_owner (msg); | 1008 | msg_imap_t msg_imap = message_get_owner (msg); |
1009 | m_imap_t m_imap = msg_imap->m_imap; | 1009 | m_imap_t m_imap = msg_imap->m_imap; |
1010 | f_imap_t f_imap = m_imap->f_imap; | 1010 | f_imap_t f_imap = m_imap->f_imap; |
1011 | int status; | 1011 | int status = 0;; |
1012 | 1012 | ||
1013 | /* If there is a parent it means it is a sub message, IMAP does not give | 1013 | /* If there is a parent it means it is a sub message, IMAP does not give |
1014 | the full size of mime messages, so the message_size retrieved from | 1014 | the full size of mime messages, so the message_size retrieved from |
... | @@ -1018,14 +1018,17 @@ imap_message_size (message_t msg, size_t *psize) | ... | @@ -1018,14 +1018,17 @@ imap_message_size (message_t msg, size_t *psize) |
1018 | return imap_submessage_size (msg_imap, psize); | 1018 | return imap_submessage_size (msg_imap, psize); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | if (msg_imap->message_size == 0) | ||
1022 | { | ||
1021 | /* Select first. */ | 1023 | /* Select first. */ |
1022 | if (f_imap->state == IMAP_NO_STATE) | 1024 | if (f_imap->state == IMAP_NO_STATE) |
1023 | { | 1025 | { |
1024 | status = imap_messages_count (m_imap->mailbox, NULL); | 1026 | status = imap_messages_count (m_imap->mailbox, NULL); |
1025 | if (status != 0) | 1027 | if (status != 0) |
1026 | return status; | 1028 | return status; |
1027 | /* We strip the \r, but the offset/size on the imap server is with that | 1029 | /* We strip the \r, but the offset/size on the imap server is with |
1028 | octet so add it in the offset, since it's the number of lines. */ | 1030 | that octet so add it in the offset, since it's the number of |
1031 | lines. */ | ||
1029 | status = imap_writeline (f_imap, | 1032 | status = imap_writeline (f_imap, |
1030 | "g%d FETCH %d RFC822.SIZE\r\n", | 1033 | "g%d FETCH %d RFC822.SIZE\r\n", |
1031 | f_imap->seq++, msg_imap->num); | 1034 | f_imap->seq++, msg_imap->num); |
... | @@ -1034,6 +1037,8 @@ imap_message_size (message_t msg, size_t *psize) | ... | @@ -1034,6 +1037,8 @@ imap_message_size (message_t msg, size_t *psize) |
1034 | f_imap->state = IMAP_FETCH; | 1037 | f_imap->state = IMAP_FETCH; |
1035 | } | 1038 | } |
1036 | status = message_operation (f_imap, msg_imap, 0, 0, 0); | 1039 | status = message_operation (f_imap, msg_imap, 0, 0, 0); |
1040 | } | ||
1041 | |||
1037 | if (status == 0) | 1042 | if (status == 0) |
1038 | { | 1043 | { |
1039 | if (psize) | 1044 | if (psize) |
... | @@ -1583,10 +1588,11 @@ imap_header_get_fvalue (header_t header, const char *field, char * buffer, | ... | @@ -1583,10 +1588,11 @@ imap_header_get_fvalue (header_t header, const char *field, char * buffer, |
1583 | status = imap_messages_count (m_imap->mailbox, NULL); | 1588 | status = imap_messages_count (m_imap->mailbox, NULL); |
1584 | if (status != 0) | 1589 | if (status != 0) |
1585 | return status; | 1590 | return status; |
1586 | #define CACHE_HEADERS "Bcc Cc Content-Language Content-Transfer-Encoding Content-Type Date From In-Reply-To Message-ID Reference Reply-To Sender Subject To X-UIDL" | 1591 | #define MU_IMAP_CACHE_HEADERS "Bcc Cc Content-Language Content-Transfer-Encoding Content-Type Date From In-Reply-To Message-ID Reference Reply-To Sender Subject To X-UIDL" |
1587 | status = imap_writeline (f_imap, | 1592 | status = imap_writeline (f_imap, |
1588 | "g%d FETCH %d BODY.PEEK[HEADER.FIELDS (%s)]\r\n", | 1593 | "g%d FETCH %d FLAGS RFC822.SIZE BODY.PEEK[HEADER.FIELDS (%s)]\r\n", |
1589 | f_imap->seq++, msg_imap->num, CACHE_HEADERS); | 1594 | f_imap->seq++, msg_imap->num, |
1595 | MU_IMAP_CACHE_HEADERS); | ||
1590 | CHECK_ERROR (f_imap, status); | 1596 | CHECK_ERROR (f_imap, status); |
1591 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); | 1597 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); |
1592 | f_imap->state = IMAP_FETCH; | 1598 | f_imap->state = IMAP_FETCH; | ... | ... |
-
Please register or sign in to post a comment