Commit b29a384e b29a384e0ca4b2fa93db7b8b7f36ff454b8098b1 by Wojciech Polak

Added the CAPA support (to determine any protocol extension).

1 parent f136c82d
...@@ -79,6 +79,7 @@ enum pop_state ...@@ -79,6 +79,7 @@ enum pop_state
79 POP_NO_STATE, POP_STATE_DONE, 79 POP_NO_STATE, POP_STATE_DONE,
80 POP_OPEN_CONNECTION, 80 POP_OPEN_CONNECTION,
81 POP_GREETINGS, 81 POP_GREETINGS,
82 POP_CAPA, POP_CAPA_ACK,
82 POP_APOP, POP_APOP_ACK, 83 POP_APOP, POP_APOP_ACK,
83 POP_DELE, POP_DELE_ACK, 84 POP_DELE, POP_DELE_ACK,
84 POP_LIST, POP_LIST_ACK, POP_LIST_RX, 85 POP_LIST, POP_LIST_ACK, POP_LIST_RX,
...@@ -87,6 +88,7 @@ enum pop_state ...@@ -87,6 +88,7 @@ enum pop_state
87 POP_RETR, POP_RETR_ACK, POP_RETR_RX_HDR, POP_RETR_RX_BODY, 88 POP_RETR, POP_RETR_ACK, POP_RETR_RX_HDR, POP_RETR_RX_BODY,
88 POP_RSET, POP_RSET_ACK, 89 POP_RSET, POP_RSET_ACK,
89 POP_STAT, POP_STAT_ACK, 90 POP_STAT, POP_STAT_ACK,
91 POP_STLS, POP_STLS_ACK,
90 POP_TOP, POP_TOP_ACK, POP_TOP_RX, 92 POP_TOP, POP_TOP_ACK, POP_TOP_RX,
91 POP_UIDL, POP_UIDL_ACK, 93 POP_UIDL, POP_UIDL_ACK,
92 POP_AUTH, POP_AUTH_DONE, 94 POP_AUTH, POP_AUTH_DONE,
...@@ -94,6 +96,19 @@ enum pop_state ...@@ -94,6 +96,19 @@ enum pop_state
94 POP_AUTH_PASS, POP_AUTH_PASS_ACK 96 POP_AUTH_PASS, POP_AUTH_PASS_ACK
95 }; 97 };
96 98
99 /* POP3 capabilities */
100 #define CAPA_TOP 0x00000001
101 #define CAPA_USER 0x00000002
102 #define CAPA_UIDL 0x00000004
103 #define CAPA_RESP_CODES 0x00000008
104 #define CAPA_LOGIN_DELAY 0x00000010
105 #define CAPA_PIPELINING 0x00000020
106 #define CAPA_EXPIRE 0x00000040
107 #define CAPA_SASL 0x00000080
108 #define CAPA_STLS 0x00000100
109 #define CAPA_IMPLEMENTATION 0x00000200
110 static unsigned long capa;
111
97 static void pop_destroy __P ((mailbox_t)); 112 static void pop_destroy __P ((mailbox_t));
98 113
99 /* Functions/Methods that implements the mailbox_t API. */ 114 /* Functions/Methods that implements the mailbox_t API. */
...@@ -540,9 +555,7 @@ _pop_apop (authority_t auth) ...@@ -540,9 +555,7 @@ _pop_apop (authority_t auth)
540 } 555 }
541 556
542 557
543 /* Open the connection to the sever, and send the authentication. 558 /* Open the connection to the sever, and send the authentication. */
544 FIXME: Should also send the CAPA command to detect for example the suport
545 for TOP, APOP, ... and DTRT(Do The Right Thing). */
546 static int 559 static int
547 pop_open (mailbox_t mbox, int flags) 560 pop_open (mailbox_t mbox, int flags)
548 { 561 {
...@@ -633,9 +646,60 @@ pop_open (mailbox_t mbox, int flags) ...@@ -633,9 +646,60 @@ pop_open (mailbox_t mbox, int flags)
633 { 646 {
634 CHECK_ERROR_CLOSE (mbox, mpd, EACCES); 647 CHECK_ERROR_CLOSE (mbox, mpd, EACCES);
635 } 648 }
636 mpd->state = POP_AUTH; 649 status = pop_writeline (mpd, "CAPA\r\n");
650 CHECK_ERROR (mpd, status);
651 MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer);
652 mpd->state = POP_CAPA;
637 } 653 }
638 654
655 case POP_CAPA:
656 status = pop_write (mpd);
657 CHECK_EAGAIN (mpd, status);
658 mpd->state = POP_CAPA_ACK;
659
660 case POP_CAPA_ACK:
661 status = pop_read_ack (mpd);
662 CHECK_EAGAIN (mpd, status);
663 MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer);
664
665 if (!strncasecmp (mpd->buffer, "+OK", 3))
666 {
667 capa = 0;
668 do
669 {
670 status = pop_read_ack (mpd);
671 MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer);
672
673 /* Here we check some common capabilities like TOP, USER, UIDL,
674 and STLS. The rest are ignored. Please note that some
675 capabilities might have an extra arguments. For instance,
676 SASL can have CRAM-MD5 and/or KERBEROS_V4, and etc.
677 This is why I suggest adding (in a future) an extra variable,
678 for example `capa_sasl'. It would hold the following flags:
679 SASL_CRAM_MD5, SASL_KERBEROS_V4, and so on. Also the EXPIRE
680 and LOGIN-DELAY capabilities have an extra arguments!
681 Note that there is no APOP capability, even though APOP
682 is an optional command in POP3. -- W.P. */
683
684 if (!strncasecmp (mpd->buffer, "TOP", 3))
685 capa |= CAPA_TOP;
686 else if (!strncasecmp (mpd->buffer, "USER", 4))
687 capa |= CAPA_USER;
688 else if (!strncasecmp (mpd->buffer, "UIDL", 4))
689 capa |= CAPA_UIDL;
690 else if (!strncasecmp (mpd->buffer, "STLS", 4))
691 capa |= CAPA_STLS;
692 }
693 while (mpd->nl);
694 }
695 /* else
696 mu_error ("CAPA not implemented\n"); */ /* FIXME */
697
698 case POP_STLS:
699 case POP_STLS_ACK:
700
701 mpd->state = POP_AUTH;
702
639 case POP_AUTH: 703 case POP_AUTH:
640 case POP_AUTH_USER: 704 case POP_AUTH_USER:
641 case POP_AUTH_USER_ACK: 705 case POP_AUTH_USER_ACK:
...@@ -1317,7 +1381,7 @@ pop_uid (message_t msg, size_t *puid) ...@@ -1317,7 +1381,7 @@ pop_uid (message_t msg, size_t *puid)
1317 1381
1318 /* Get the UIDL. Client should be prepare since it may fail. UIDL is 1382 /* Get the UIDL. Client should be prepare since it may fail. UIDL is
1319 optional on many POP servers. 1383 optional on many POP servers.
1320 FIXME: We should check this with CAPA and fall back to a md5 scheme ? 1384 FIXME: We should check the "capa & CAPA_UIDL" and fall back to a md5 scheme ?
1321 Or maybe check for "X-UIDL" a la Qpopper ? */ 1385 Or maybe check for "X-UIDL" a la Qpopper ? */
1322 static int 1386 static int
1323 pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) 1387 pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
...@@ -1419,7 +1483,7 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) ...@@ -1419,7 +1483,7 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
1419 } 1483 }
1420 1484
1421 /* How we retrieve the headers. If it fails we jump to the pop_retr() 1485 /* How we retrieve the headers. If it fails we jump to the pop_retr()
1422 code .i.e send a RETR and skip the body, ugly. 1486 code i.e. send a RETR and skip the body, ugly.
1423 NOTE: if the offset is different, flag an error, offset is meaningless 1487 NOTE: if the offset is different, flag an error, offset is meaningless
1424 on a socket but we better warn them, some stuff like mime_t may try to 1488 on a socket but we better warn them, some stuff like mime_t may try to
1425 read ahead, for example for the headers. */ 1489 read ahead, for example for the headers. */
...@@ -1454,13 +1518,20 @@ pop_top (header_t header, char *buffer, size_t buflen, ...@@ -1454,13 +1518,20 @@ pop_top (header_t header, char *buffer, size_t buflen,
1454 switch (mpd->state) 1518 switch (mpd->state)
1455 { 1519 {
1456 case POP_NO_STATE: 1520 case POP_NO_STATE:
1457 /* TOP is an optionnal command, if we want to be compliant we can not 1521 if (capa & CAPA_TOP)
1458 count on it to exists. So we should be prepare when it fails and 1522 {
1459 fall to a second scheme. */
1460 status = pop_writeline (mpd, "TOP %d 0\r\n", mpm->num); 1523 status = pop_writeline (mpd, "TOP %d 0\r\n", mpm->num);
1461 CHECK_ERROR (mpd, status); 1524 CHECK_ERROR (mpd, status);
1462 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1525 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1463 mpd->state = POP_TOP; 1526 mpd->state = POP_TOP;
1527 }
1528 else /* Fall back to RETR call. */
1529 {
1530 mpd->state = POP_NO_STATE;
1531 mpm->skip_header = 0;
1532 mpm->skip_body = 1;
1533 return pop_retr (mpm, buffer, buflen, offset, pnread);
1534 }
1464 1535
1465 case POP_TOP: 1536 case POP_TOP:
1466 /* Send the TOP. */ 1537 /* Send the TOP. */
...@@ -1473,15 +1544,8 @@ pop_top (header_t header, char *buffer, size_t buflen, ...@@ -1473,15 +1544,8 @@ pop_top (header_t header, char *buffer, size_t buflen,
1473 status = pop_read_ack (mpd); 1544 status = pop_read_ack (mpd);
1474 CHECK_EAGAIN (mpd, status); 1545 CHECK_EAGAIN (mpd, status);
1475 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer); 1546 MAILBOX_DEBUG0 (mpd->mbox, MU_DEBUG_PROT, mpd->buffer);
1476 if (strncasecmp (mpd->buffer, "+OK", 3) != 0) 1547 /* if (strncasecmp (mpd->buffer, "+OK", 3) != 0)
1477 { 1548 mu_error ("TOP not implemented\n"); */ /* FIXME */
1478 /* mu_error ("TOP not implemented\n"); */
1479 /* Fall back to RETR call. */
1480 mpd->state = POP_NO_STATE;
1481 mpm->skip_header = 0;
1482 mpm->skip_body = 1;
1483 return pop_retr (mpm, buffer, buflen, offset, pnread);
1484 }
1485 mpd->state = POP_TOP_RX; 1549 mpd->state = POP_TOP_RX;
1486 1550
1487 case POP_TOP_RX: 1551 case POP_TOP_RX:
......