Commit 0c89e510 0c89e510d67fdb5a0ff47d41280a49e15e2fda0e by Sergey Poznyakoff

Fix parsing of pop3 server replies.

Use mu_umaxtostr to format size_t and off_t values
1 parent 7ab6b81f
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
32 #include <unistd.h> 32 #include <unistd.h>
33 #include <fcntl.h> 33 #include <fcntl.h>
34 #include <stdarg.h> 34 #include <stdarg.h>
35 #include <ctype.h>
35 36
36 #ifdef HAVE_ALLOCA_H 37 #ifdef HAVE_ALLOCA_H
37 # include <alloca.h> 38 # include <alloca.h>
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
43 44
44 #include <md5.h> 45 #include <md5.h>
45 46
47 #include <mu_umaxtostr.h>
46 #include <mailutils/attribute.h> 48 #include <mailutils/attribute.h>
47 #include <mailutils/auth.h> 49 #include <mailutils/auth.h>
48 #include <mailutils/body.h> 50 #include <mailutils/body.h>
...@@ -1022,6 +1024,40 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) ...@@ -1022,6 +1024,40 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg)
1022 return 0; 1024 return 0;
1023 } 1025 }
1024 1026
1027 static int
1028 parse_answer0 (const char *buffer, size_t *n1, size_t *n2)
1029 {
1030 char *p;
1031 uintmax_t m;
1032 if (strlen (buffer) < 3 || memcmp (buffer, "+OK", 3))
1033 return 1;
1034 m = *n1 = strtoumax (buffer + 3, &p, 10);
1035 if (!isspace (*p) || m != *n1)
1036 return 1;
1037 m = *n2 = strtoumax (p, &p, 10);
1038 if (!(*p == 0 || isspace (*p)) || m != *n2)
1039 return 1;
1040 return 0;
1041 }
1042
1043 static int
1044 parse_answer1 (const char *buffer, size_t *n1, char *buf, size_t bufsize)
1045 {
1046 char *p;
1047 uintmax_t m;
1048 if (strlen (buffer) < 3 || memcmp (buffer, "+OK", 3))
1049 return 1;
1050 m = *n1 = strtoumax (buffer + 3, &p, 0);
1051 if (!isspace (*p) || m != *n1)
1052 return 1;
1053 while (*p && isspace (*p))
1054 p++;
1055 if (strlen (p) >= bufsize)
1056 return 1;
1057 strcpy (buf, p);
1058 return 0;
1059 }
1060
1025 /* There is no such thing in pop all messages should be consider recent. 1061 /* There is no such thing in pop all messages should be consider recent.
1026 FIXME: We could cheat and peek at the status if it was not strip 1062 FIXME: We could cheat and peek at the status if it was not strip
1027 by the server ... */ 1063 by the server ... */
...@@ -1099,14 +1135,13 @@ pop_messages_count (mu_mailbox_t mbox, size_t *pcount) ...@@ -1099,14 +1135,13 @@ pop_messages_count (mu_mailbox_t mbox, size_t *pcount)
1099 1135
1100 1136
1101 /* Parse the answer. */ 1137 /* Parse the answer. */
1102 status = sscanf (mpd->buffer, "+OK %d %d", &(mpd->messages_count),
1103 &(mpd->size));
1104 1138
1139 status = parse_answer0 (mpd->buffer, &mpd->messages_count, &mpd->size);
1105 /* Clear the state _after_ the scanf, since another thread could 1140 /* Clear the state _after_ the scanf, since another thread could
1106 start writing over mpd->buffer. */ 1141 start writing over mpd->buffer. */
1107 CLEAR_STATE (mpd); 1142 CLEAR_STATE (mpd);
1108 1143
1109 if (status == EOF || status != 2) 1144 if (status)
1110 return EIO; 1145 return EIO;
1111 1146
1112 if (pcount) 1147 if (pcount)
...@@ -1182,8 +1217,9 @@ pop_expunge (mu_mailbox_t mbox) ...@@ -1182,8 +1217,9 @@ pop_expunge (mu_mailbox_t mbox)
1182 switch (mpd->state) 1217 switch (mpd->state)
1183 { 1218 {
1184 case POP_NO_STATE: 1219 case POP_NO_STATE:
1185 status = pop_writeline (mpd, "DELE %d\r\n", 1220 status = pop_writeline (mpd, "DELE %s\r\n",
1186 mpd->pmessages[i]->num); 1221 mu_umaxtostr (0,
1222 mpd->pmessages[i]->num));
1187 CHECK_ERROR (mpd, status); 1223 CHECK_ERROR (mpd, status);
1188 MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer); 1224 MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer);
1189 mpd->state = POP_DELE; 1225 mpd->state = POP_DELE;
...@@ -1277,7 +1313,7 @@ pop_message_size (mu_message_t msg, size_t *psize) ...@@ -1277,7 +1313,7 @@ pop_message_size (mu_message_t msg, size_t *psize)
1277 switch (mpd->state) 1313 switch (mpd->state)
1278 { 1314 {
1279 case POP_NO_STATE: 1315 case POP_NO_STATE:
1280 status = pop_writeline (mpd, "LIST %d\r\n", mpm->num); 1316 status = pop_writeline (mpd, "LIST %s\r\n", mu_umaxtostr (0, mpm->num));
1281 CHECK_ERROR (mpd, status); 1317 CHECK_ERROR (mpd, status);
1282 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1318 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1283 mpd->state = POP_LIST; 1319 mpd->state = POP_LIST;
...@@ -1302,10 +1338,11 @@ pop_message_size (mu_message_t msg, size_t *psize) ...@@ -1302,10 +1338,11 @@ pop_message_size (mu_message_t msg, size_t *psize)
1302 break; 1338 break;
1303 } 1339 }
1304 1340
1305 status = sscanf (mpd->buffer, "+OK %d %d\n", &num, &mpm->mu_message_size); 1341 /* FIXME */
1342 status = parse_answer0 (mpd->buffer, &num, &mpm->mu_message_size);
1306 CLEAR_STATE (mpd); 1343 CLEAR_STATE (mpd);
1307 1344
1308 if (status != 2) 1345 if (status != 0)
1309 status = MU_ERR_PARSE; 1346 status = MU_ERR_PARSE;
1310 1347
1311 /* The size of the message is with the extra '\r' octet for everyline. 1348 /* The size of the message is with the extra '\r' octet for everyline.
...@@ -1495,7 +1532,7 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten) ...@@ -1495,7 +1532,7 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
1495 switch (mpd->state) 1532 switch (mpd->state)
1496 { 1533 {
1497 case POP_NO_STATE: 1534 case POP_NO_STATE:
1498 status = pop_writeline (mpd, "UIDL %d\r\n", mpm->num); 1535 status = pop_writeline (mpd, "UIDL %s\r\n", mu_umaxtostr (0, mpm->num));
1499 CHECK_ERROR (mpd, status); 1536 CHECK_ERROR (mpd, status);
1500 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1537 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1501 mpd->state = POP_UIDL; 1538 mpd->state = POP_UIDL;
...@@ -1522,8 +1559,8 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten) ...@@ -1522,8 +1559,8 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
1522 1559
1523 /* FIXME: I should cache the result. */ 1560 /* FIXME: I should cache the result. */
1524 *uniq = '\0'; 1561 *uniq = '\0';
1525 status = sscanf (mpd->buffer, "+OK %d %127s\n", &num, uniq); 1562 status = parse_answer1 (mpd->buffer, &num, uniq, sizeof uniq);
1526 if (status != 2) 1563 if (status)
1527 { 1564 {
1528 status = MU_ERR_PARSE; 1565 status = MU_ERR_PARSE;
1529 buflen = 0; 1566 buflen = 0;
...@@ -1590,7 +1627,8 @@ pop_top (mu_header_t header, char *buffer, size_t buflen, ...@@ -1590,7 +1627,8 @@ pop_top (mu_header_t header, char *buffer, size_t buflen,
1590 case POP_NO_STATE: 1627 case POP_NO_STATE:
1591 if (mpd->capa & CAPA_TOP) 1628 if (mpd->capa & CAPA_TOP)
1592 { 1629 {
1593 status = pop_writeline (mpd, "TOP %d 0\r\n", mpm->num); 1630 status = pop_writeline (mpd, "TOP %s 0\r\n",
1631 mu_umaxtostr (0, mpm->num));
1594 CHECK_ERROR (mpd, status); 1632 CHECK_ERROR (mpd, status);
1595 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1633 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1596 mpd->state = POP_TOP; 1634 mpd->state = POP_TOP;
...@@ -1815,7 +1853,8 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, ...@@ -1815,7 +1853,8 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen,
1815 { 1853 {
1816 case POP_NO_STATE: 1854 case POP_NO_STATE:
1817 mpm->body_lines = mpm->body_size = 0; 1855 mpm->body_lines = mpm->body_size = 0;
1818 status = pop_writeline (mpd, "RETR %d\r\n", mpm->num); 1856 status = pop_writeline (mpd, "RETR %s\r\n",
1857 mu_umaxtostr (0, mpm->num));
1819 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1858 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1820 CHECK_ERROR (mpd, status); 1859 CHECK_ERROR (mpd, status);
1821 mpd->state = POP_RETR; 1860 mpd->state = POP_RETR;
......