Commit e7ce526d e7ce526d1f0903065333ffd88bb9379be3d78c34 by Alain Magloire

* 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.
1 parent 0de08a30
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;
......