aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorKarl Heuer1997-12-04 06:44:56 +0000
committerKarl Heuer1997-12-04 06:44:56 +0000
commitd89d0243979a85456895e72e658116b760527bdc (patch)
tree3e357ac717eb51384fd85e44d0a21f4191649de7 /lib-src
parent070c25062342b2b299e644463fb6d95b9421694e (diff)
downloademacs-d89d0243979a85456895e72e658116b760527bdc.tar.gz
emacs-d89d0243979a85456895e72e658116b760527bdc.zip
Allow messages retrieved from the POP
server to contain embedded nulls.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/movemail.c9
-rw-r--r--lib-src/pop.c176
-rw-r--r--lib-src/pop.h3
3 files changed, 116 insertions, 72 deletions
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index b7b51d35061..e010d6f9806 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -795,12 +795,12 @@ pop_retr (server, msgno, arg)
795 return (NOTOK); 795 return (NOTOK);
796 } 796 }
797 797
798 while (! (ret = pop_retrieve_next (server, &line))) 798 while ((ret = pop_retrieve_next (server, &line)) >= 0)
799 { 799 {
800 if (! line) 800 if (! line)
801 break; 801 break;
802 802
803 if (mbx_write (line, arg) != OK) 803 if (mbx_write (line, ret, arg) != OK)
804 { 804 {
805 strcpy (Errmsg, strerror (errno)); 805 strcpy (Errmsg, strerror (errno));
806 pop_close (server); 806 pop_close (server);
@@ -826,8 +826,9 @@ pop_retr (server, msgno, arg)
826 && (a[4] == ' ')) 826 && (a[4] == ' '))
827 827
828int 828int
829mbx_write (line, mbf) 829mbx_write (line, len, mbf)
830 char *line; 830 char *line;
831 int len;
831 FILE *mbf; 832 FILE *mbf;
832{ 833{
833#ifdef MOVEMAIL_QUOTE_POP_FROM_LINES 834#ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
@@ -844,7 +845,7 @@ mbx_write (line, mbf)
844 line++; 845 line++;
845 len--; 846 len--;
846 } 847 }
847 if (fputs (line, mbf) == EOF) 848 if (fwrite (line, 1, len, mbf) != len)
848 return (NOTOK); 849 return (NOTOK);
849 if (fputc (0x0a, mbf) == EOF) 850 if (fputc (0x0a, mbf) == EOF)
850 return (NOTOK); 851 return (NOTOK);
diff --git a/lib-src/pop.c b/lib-src/pop.c
index 16823baa1d4..d74d16fa6d2 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -130,16 +130,24 @@ extern int h_errno;
130#endif 130#endif
131#endif 131#endif
132 132
133static int socket_connection (/* char *, int */); 133#ifndef _P
134static char *getline (/* popserver */); 134# ifdef __STDC__
135static int sendline (/* popserver, char * */); 135# define _P(a) a
136static int fullwrite (/* int, char *, int */); 136# else
137static int getok (/* popserver */); 137# define _P(a) ()
138# endif /* __STDC__ */
139#endif /* ! __P */
140
141static int socket_connection _P((char *, int));
142static int getline _P((popserver, char **));
143static int sendline _P((popserver, char *));
144static int fullwrite _P((int, char *, int));
145static int getok _P((popserver));
138#if 0 146#if 0
139static int gettermination (/* popserver */); 147static int gettermination _P((popserver));
140#endif 148#endif
141static void pop_trash (/* popserver */); 149static void pop_trash _P((popserver));
142static char *find_crlf (/* char * */); 150static char *find_crlf _P((char *, int));
143 151
144#define ERROR_MAX 80 /* a pretty arbitrary size */ 152#define ERROR_MAX 80 /* a pretty arbitrary size */
145#define POP_PORT 110 153#define POP_PORT 110
@@ -373,7 +381,7 @@ pop_stat (server, count, size)
373 return (-1); 381 return (-1);
374 } 382 }
375 383
376 if (sendline (server, "STAT") || (! (fromserver = getline (server)))) 384 if (sendline (server, "STAT") || (getline (server, &fromserver) < 0))
377 return (-1); 385 return (-1);
378 386
379 if (strncmp (fromserver, "+OK ", 4)) 387 if (strncmp (fromserver, "+OK ", 4))
@@ -469,7 +477,7 @@ pop_list (server, message, IDs, sizes)
469 free ((char *) *sizes); 477 free ((char *) *sizes);
470 return (-1); 478 return (-1);
471 } 479 }
472 if (! (fromserver = getline (server))) 480 if (getline (server, &fromserver) < 0)
473 { 481 {
474 free ((char *) *IDs); 482 free ((char *) *IDs);
475 free ((char *) *sizes); 483 free ((char *) *sizes);
@@ -514,7 +522,7 @@ pop_list (server, message, IDs, sizes)
514 } 522 }
515 for (i = 0; i < how_many; i++) 523 for (i = 0; i < how_many; i++)
516 { 524 {
517 if (pop_multi_next (server, &fromserver)) 525 if (pop_multi_next (server, &fromserver) <= 0)
518 { 526 {
519 free ((char *) *IDs); 527 free ((char *) *IDs);
520 free ((char *) *sizes); 528 free ((char *) *sizes);
@@ -533,7 +541,7 @@ pop_list (server, message, IDs, sizes)
533 } 541 }
534 (*sizes)[i] = atoi (fromserver); 542 (*sizes)[i] = atoi (fromserver);
535 } 543 }
536 if (pop_multi_next (server, &fromserver)) 544 if (pop_multi_next (server, &fromserver) < 0)
537 { 545 {
538 free ((char *) *IDs); 546 free ((char *) *IDs);
539 free ((char *) *sizes); 547 free ((char *) *sizes);
@@ -563,17 +571,21 @@ pop_list (server, message, IDs, sizes)
563 * markfrom 571 * markfrom
564 * If true, then mark the string "From " at the beginning 572 * If true, then mark the string "From " at the beginning
565 * of lines with '>'. 573 * of lines with '>'.
574 * msg_buf Output parameter to which a buffer containing the
575 * message is assigned.
566 * 576 *
567 * Return value: A string pointing to the message, if successful, or 577 * Return value: The number of bytes in msg_buf, which may contain
568 * null with pop_error set if not. 578 * embedded nulls, not including its final null, or -1 on error
579 * with pop_error set.
569 * 580 *
570 * Side effects: May kill connection on error. 581 * Side effects: May kill connection on error.
571 */ 582 */
572char * 583int
573pop_retrieve (server, message, markfrom) 584pop_retrieve (server, message, markfrom, msg_buf)
574 popserver server; 585 popserver server;
575 int message; 586 int message;
576 int markfrom; 587 int markfrom;
588 char **msg_buf;
577{ 589{
578 int *IDs, *sizes, bufsize, fromcount = 0, cp = 0; 590 int *IDs, *sizes, bufsize, fromcount = 0, cp = 0;
579 char *ptr, *fromserver; 591 char *ptr, *fromserver;
@@ -582,15 +594,15 @@ pop_retrieve (server, message, markfrom)
582 if (server->in_multi) 594 if (server->in_multi)
583 { 595 {
584 strcpy (pop_error, "In multi-line query in pop_retrieve"); 596 strcpy (pop_error, "In multi-line query in pop_retrieve");
585 return (0); 597 return (-1);
586 } 598 }
587 599
588 if (pop_list (server, message, &IDs, &sizes)) 600 if (pop_list (server, message, &IDs, &sizes))
589 return (0); 601 return (-1);
590 602
591 if (pop_retrieve_first (server, message, &fromserver)) 603 if (pop_retrieve_first (server, message, &fromserver))
592 { 604 {
593 return (0); 605 return (-1);
594 } 606 }
595 607
596 /* 608 /*
@@ -608,17 +620,16 @@ pop_retrieve (server, message, markfrom)
608 { 620 {
609 strcpy (pop_error, "Out of memory in pop_retrieve"); 621 strcpy (pop_error, "Out of memory in pop_retrieve");
610 pop_retrieve_flush (server); 622 pop_retrieve_flush (server);
611 return (0); 623 return (-1);
612 } 624 }
613 625
614 while (! (ret = pop_retrieve_next (server, &fromserver))) 626 while ((ret = pop_retrieve_next (server, &fromserver)) >= 0)
615 { 627 {
616 int linesize;
617
618 if (! fromserver) 628 if (! fromserver)
619 { 629 {
620 ptr[cp] = '\0'; 630 ptr[cp] = '\0';
621 return (ptr); 631 *msg_buf = ptr;
632 return (cp);
622 } 633 }
623 if (markfrom && fromserver[0] == 'F' && fromserver[1] == 'r' && 634 if (markfrom && fromserver[0] == 'F' && fromserver[1] == 'r' &&
624 fromserver[2] == 'o' && fromserver[3] == 'm' && 635 fromserver[2] == 'o' && fromserver[3] == 'm' &&
@@ -632,23 +643,19 @@ pop_retrieve (server, message, markfrom)
632 { 643 {
633 strcpy (pop_error, "Out of memory in pop_retrieve"); 644 strcpy (pop_error, "Out of memory in pop_retrieve");
634 pop_retrieve_flush (server); 645 pop_retrieve_flush (server);
635 return (0); 646 return (-1);
636 } 647 }
637 fromcount = 0; 648 fromcount = 0;
638 } 649 }
639 ptr[cp++] = '>'; 650 ptr[cp++] = '>';
640 } 651 }
641 linesize = strlen (fromserver); 652 bcopy (fromserver, &ptr[cp], ret);
642 bcopy (fromserver, &ptr[cp], linesize); 653 cp += ret;
643 cp += linesize;
644 ptr[cp++] = '\n'; 654 ptr[cp++] = '\n';
645 } 655 }
646 656
647 if (ret) 657 free (ptr);
648 { 658 return (-1);
649 free (ptr);
650 return (0);
651 }
652} 659}
653 660
654int 661int
@@ -661,6 +668,14 @@ pop_retrieve_first (server, message, response)
661 return (pop_multi_first (server, pop_error, response)); 668 return (pop_multi_first (server, pop_error, response));
662} 669}
663 670
671/*
672 Returns a negative number on error, 0 to indicate that the data has
673 all been read (i.e., the server has returned a "." termination
674 line), or a positive number indicating the number of bytes in the
675 returned buffer (which is null-terminated and may contain embedded
676 nulls, but the returned bytecount doesn't include the final null).
677 */
678
664int 679int
665pop_retrieve_next (server, line) 680pop_retrieve_next (server, line)
666 popserver server; 681 popserver server;
@@ -686,6 +701,14 @@ pop_top_first (server, message, lines, response)
686 return (pop_multi_first (server, pop_error, response)); 701 return (pop_multi_first (server, pop_error, response));
687} 702}
688 703
704/*
705 Returns a negative number on error, 0 to indicate that the data has
706 all been read (i.e., the server has returned a "." termination
707 line), or a positive number indicating the number of bytes in the
708 returned buffer (which is null-terminated and may contain embedded
709 nulls, but the returned bytecount doesn't include the final null).
710 */
711
689int 712int
690pop_top_next (server, line) 713pop_top_next (server, line)
691 popserver server; 714 popserver server;
@@ -714,7 +737,7 @@ pop_multi_first (server, command, response)
714 return (-1); 737 return (-1);
715 } 738 }
716 739
717 if (sendline (server, command) || (! (*response = getline (server)))) 740 if (sendline (server, command) || (getline (server, response) < 0))
718 { 741 {
719 return (-1); 742 return (-1);
720 } 743 }
@@ -738,12 +761,22 @@ pop_multi_first (server, command, response)
738 } 761 }
739} 762}
740 763
764/*
765 Read the next line of data from SERVER and place a pointer to it
766 into LINE. Return -1 on error, 0 if there are no more lines to read
767 (i.e., the server has returned a line containing only "."), or a
768 positive number indicating the number of bytes in the LINE buffer
769 (not including the final null). The data in that buffer may contain
770 embedded nulls, but does not contain the final CRLF. When returning
771 0, LINE is set to null. */
772
741int 773int
742pop_multi_next (server, line) 774pop_multi_next (server, line)
743 popserver server; 775 popserver server;
744 char **line; 776 char **line;
745{ 777{
746 char *fromserver; 778 char *fromserver;
779 int ret;
747 780
748 if (! server->in_multi) 781 if (! server->in_multi)
749 { 782 {
@@ -751,8 +784,7 @@ pop_multi_next (server, line)
751 return (-1); 784 return (-1);
752 } 785 }
753 786
754 fromserver = getline (server); 787 if ((ret = getline (server, &fromserver)) < 0)
755 if (! fromserver)
756 { 788 {
757 return (-1); 789 return (-1);
758 } 790 }
@@ -768,13 +800,13 @@ pop_multi_next (server, line)
768 else 800 else
769 { 801 {
770 *line = fromserver + 1; 802 *line = fromserver + 1;
771 return (0); 803 return (ret - 1);
772 } 804 }
773 } 805 }
774 else 806 else
775 { 807 {
776 *line = fromserver; 808 *line = fromserver;
777 return (0); 809 return (ret);
778 } 810 }
779} 811}
780 812
@@ -783,21 +815,20 @@ pop_multi_flush (server)
783 popserver server; 815 popserver server;
784{ 816{
785 char *line; 817 char *line;
818 int ret;
786 819
787 if (! server->in_multi) 820 if (! server->in_multi)
788 { 821 {
789 return (0); 822 return (0);
790 } 823 }
791 824
792 while (! pop_multi_next (server, &line)) 825 while ((ret = pop_multi_next (server, &line)))
793 { 826 {
794 if (! line) 827 if (ret < 0)
795 { 828 return (-1);
796 return (0);
797 }
798 } 829 }
799 830
800 return (-1); 831 return (0);
801} 832}
802 833
803/* Function: pop_delete 834/* Function: pop_delete
@@ -888,7 +919,7 @@ pop_last (server)
888 if (sendline (server, "LAST")) 919 if (sendline (server, "LAST"))
889 return (-1); 920 return (-1);
890 921
891 if (! (fromserver = getline (server))) 922 if (getline (server, &fromserver) < 0)
892 return (-1); 923 return (-1);
893 924
894 if (! strncmp (fromserver, "-ERR", 4)) 925 if (! strncmp (fromserver, "-ERR", 4))
@@ -1234,16 +1265,22 @@ socket_connection (host, flags)
1234 * Arguments: 1265 * Arguments:
1235 * server The server from which to get the line of text. 1266 * server The server from which to get the line of text.
1236 * 1267 *
1237 * Returns: A non-null pointer if successful, or a null pointer on any 1268 * Returns: The number of characters in the line, which is returned in
1238 * error, with an error message copied into pop_error. 1269 * LINE, not including the final null. A return value of 0
1270 * indicates a blank line. A negative return value indicates an
1271 * error (in which case the contents of LINE are undefined. In
1272 * case of error, an error message is copied into pop_error.
1239 * 1273 *
1240 * Notes: The line returned is overwritten with each call to getline. 1274 * Notes: The line returned is overwritten with each call to getline.
1241 * 1275 *
1242 * Side effects: Closes the connection on error. 1276 * Side effects: Closes the connection on error.
1277 *
1278 * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS!
1243 */ 1279 */
1244static char * 1280static int
1245getline (server) 1281getline (server, line)
1246 popserver server; 1282 popserver server;
1283 char **line;
1247{ 1284{
1248#define GETLINE_ERROR "Error reading from server: " 1285#define GETLINE_ERROR "Error reading from server: "
1249 1286
@@ -1252,7 +1289,8 @@ getline (server)
1252 1289
1253 if (server->data) 1290 if (server->data)
1254 { 1291 {
1255 char *cp = find_crlf (server->buffer + server->buffer_index); 1292 char *cp = find_crlf (server->buffer + server->buffer_index,
1293 server->data);
1256 if (cp) 1294 if (cp)
1257 { 1295 {
1258 int found; 1296 int found;
@@ -1266,8 +1304,11 @@ getline (server)
1266 server->buffer_index += data_used; 1304 server->buffer_index += data_used;
1267 1305
1268 if (pop_debug) 1306 if (pop_debug)
1307 /* Embedded nulls will truncate this output prematurely,
1308 but that's OK because it's just for debugging anyway. */
1269 fprintf (stderr, "<<< %s\n", server->buffer + found); 1309 fprintf (stderr, "<<< %s\n", server->buffer + found);
1270 return (server->buffer + found); 1310 *line = server->buffer + found;
1311 return (data_used - 2);
1271 } 1312 }
1272 else 1313 else
1273 { 1314 {
@@ -1302,7 +1343,7 @@ getline (server)
1302 { 1343 {
1303 strcpy (pop_error, "Out of memory in getline"); 1344 strcpy (pop_error, "Out of memory in getline");
1304 pop_trash (server); 1345 pop_trash (server);
1305 return (0); 1346 return (-1);
1306 } 1347 }
1307 } 1348 }
1308 ret = RECV (server->file, server->buffer + server->data, 1349 ret = RECV (server->file, server->buffer + server->data,
@@ -1313,13 +1354,13 @@ getline (server)
1313 strncat (pop_error, strerror (errno), 1354 strncat (pop_error, strerror (errno),
1314 ERROR_MAX - sizeof (GETLINE_ERROR)); 1355 ERROR_MAX - sizeof (GETLINE_ERROR));
1315 pop_trash (server); 1356 pop_trash (server);
1316 return (0); 1357 return (-1);
1317 } 1358 }
1318 else if (ret == 0) 1359 else if (ret == 0)
1319 { 1360 {
1320 strcpy (pop_error, "Unexpected EOF from server in getline"); 1361 strcpy (pop_error, "Unexpected EOF from server in getline");
1321 pop_trash (server); 1362 pop_trash (server);
1322 return (0); 1363 return (-1);
1323 } 1364 }
1324 else 1365 else
1325 { 1366 {
@@ -1327,7 +1368,8 @@ getline (server)
1327 server->data += ret; 1368 server->data += ret;
1328 server->buffer[server->data] = '\0'; 1369 server->buffer[server->data] = '\0';
1329 1370
1330 cp = find_crlf (server->buffer + search_offset); 1371 cp = find_crlf (server->buffer + search_offset,
1372 server->data - search_offset);
1331 if (cp) 1373 if (cp)
1332 { 1374 {
1333 int data_used = (cp + 2) - server->buffer; 1375 int data_used = (cp + 2) - server->buffer;
@@ -1337,7 +1379,8 @@ getline (server)
1337 1379
1338 if (pop_debug) 1380 if (pop_debug)
1339 fprintf (stderr, "<<< %s\n", server->buffer); 1381 fprintf (stderr, "<<< %s\n", server->buffer);
1340 return (server->buffer); 1382 *line = server->buffer;
1383 return (data_used - 2);
1341 } 1384 }
1342 /* As above, the "- 1" here is to account for the fact that 1385 /* As above, the "- 1" here is to account for the fact that
1343 we may have read a CR without its accompanying LF. */ 1386 we may have read a CR without its accompanying LF. */
@@ -1442,7 +1485,7 @@ getok (server)
1442{ 1485{
1443 char *fromline; 1486 char *fromline;
1444 1487
1445 if (! (fromline = getline (server))) 1488 if (getline (server, &fromline) < 0)
1446 { 1489 {
1447 return (-1); 1490 return (-1);
1448 } 1491 }
@@ -1481,8 +1524,7 @@ gettermination (server)
1481{ 1524{
1482 char *fromserver; 1525 char *fromserver;
1483 1526
1484 fromserver = getline (server); 1527 if (getline (server, &fromserver) < 0)
1485 if (! fromserver)
1486 return (-1); 1528 return (-1);
1487 1529
1488 if (strcmp (fromserver, ".")) 1530 if (strcmp (fromserver, "."))
@@ -1555,18 +1597,18 @@ pop_trash (server)
1555#endif 1597#endif
1556} 1598}
1557 1599
1558/* Return a pointer to the first CRLF in IN_STRING, 1600/* Return a pointer to the first CRLF in IN_STRING, which can contain
1559 or 0 if it does not contain one. */ 1601 embedded nulls and has LEN characters in it not including the final
1602 null, or 0 if it does not contain one. */
1560 1603
1561static char * 1604static char *
1562find_crlf (in_string) 1605find_crlf (in_string, len)
1563 char *in_string; 1606 char *in_string;
1607 int len;
1564{ 1608{
1565 while (1) 1609 while (len--)
1566 { 1610 {
1567 if (! *in_string) 1611 if (*in_string == '\r')
1568 return (0);
1569 else if (*in_string == '\r')
1570 { 1612 {
1571 if (*++in_string == '\n') 1613 if (*++in_string == '\n')
1572 return (in_string - 1); 1614 return (in_string - 1);
@@ -1574,7 +1616,7 @@ find_crlf (in_string)
1574 else 1616 else
1575 in_string++; 1617 in_string++;
1576 } 1618 }
1577 /* NOTREACHED */ 1619 return (0);
1578} 1620}
1579 1621
1580#endif /* MAIL_USE_POP */ 1622#endif /* MAIL_USE_POP */
diff --git a/lib-src/pop.h b/lib-src/pop.h
index 9121425661a..cfd333ccafc 100644
--- a/lib-src/pop.h
+++ b/lib-src/pop.h
@@ -59,7 +59,8 @@ extern popserver pop_open _ARGS((char *host, char *username, char *password,
59extern int pop_stat _ARGS((popserver server, int *count, int *size)); 59extern int pop_stat _ARGS((popserver server, int *count, int *size));
60extern int pop_list _ARGS((popserver server, int message, int **IDs, 60extern int pop_list _ARGS((popserver server, int message, int **IDs,
61 int **size)); 61 int **size));
62extern char *pop_retrieve _ARGS((popserver server, int message, int markfrom)); 62extern int pop_retrieve _ARGS((popserver server, int message, int markfrom,
63 char **));
63extern int pop_retrieve_first _ARGS((popserver server, int message, 64extern int pop_retrieve_first _ARGS((popserver server, int message,
64 char **response)); 65 char **response));
65extern int pop_retrieve_next _ARGS((popserver server, char **line)); 66extern int pop_retrieve_next _ARGS((popserver server, char **line));