]> Pileus Git - ~andy/fetchmail/blobdiff - transact.c
Merge branch 'legacy_63'
[~andy/fetchmail] / transact.c
index 0f0cd35378a4c4f5f053b8db9093562e899a1d52..2b8d04f8ec15e8b5256d90f2aa5545954340d722 100644 (file)
@@ -472,13 +472,13 @@ int readheaders(int sock,
            do {
                char    *sp, *tp;
 
-               SockTimeout(sock, mytimeout);
-               n = SockRead(sock, buf, sizeof(buf) - 1);
-
-               if (n == -1) {
+               set_timeout(mytimeout);
+               if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) {
+                   set_timeout(0);
                    free(line);
                    return(PS_SOCKET);
                }
+               set_timeout(0);
 
                /*
                 * Smash out any NULs, they could wreak havoc later on.
@@ -603,8 +603,9 @@ eoh:
            }
 
            /* check for RFC822 continuations */
-           SockTimeout(sock, mytimeout);
+           set_timeout(mytimeout);
            ch = SockPeek(sock);
+           set_timeout(0);
        } while
            (ch == ' ' || ch == '\t');  /* continuation to next line? */
 
@@ -1341,6 +1342,28 @@ process_headers:
        return PS_SOCKET;
 }
 
+/** Convenience function factored out from readbody(): 
+ * send buffer \a buf via stuffline() and handle errors and progress.
+ * Store return value in \a *n, and return PS_IOERR for failure or
+ * PS_SUCCESS otherwise. */
+static int rb_send(struct query *ctl, char *buf, int *n)
+{
+    *n = stuffline(ctl, buf);
+
+    if (*n < 0)
+    {
+       report(stdout, GT_("error writing message text\n"));
+       release_sink(ctl);
+       return(PS_IOERR);
+    }
+    else if (want_progress())
+    {
+       fputc('*', stdout);
+       fflush(stdout);
+    }
+    return PS_SUCCESS;
+}
+
 int readbody(int sock, struct query *ctl, flag forward, int len)
 /** read and dispose of a message body presented on \a sock */
 /** \param ctl         query control record */
@@ -1365,16 +1388,17 @@ int readbody(int sock, struct query *ctl, flag forward, int len)
      */
     while (protocol->delimited || len > 0)
     {
-       SockTimeout(sock, mytimeout);
+       set_timeout(mytimeout);
        /* XXX FIXME: for undelimited protocols that ship the size, such
         * as IMAP, we might want to use the count of remaining characters
         * instead of the buffer size -- not for fetchmail 6.3.X though */
-       linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf));
-       if (linelen == -1)
+       if ((linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf)))==-1)
        {
+           set_timeout(0);
            release_sink(ctl);
            return(PS_SOCKET);
        }
+       set_timeout(0);
 
        /* write the message size dots */
        if (linelen > 0)
@@ -1392,7 +1416,15 @@ int readbody(int sock, struct query *ctl, flag forward, int len)
         * so we might end truncating messages prematurely.
         */
        if (!protocol->delimited && linelen > len) {
+           /* FIXME: HACK ALERT! This \r\n is only here to make sure the
+            * \n\0 hunt works later on. The \n generated here was not
+            * part of the original message!
+            * The real fix will be to use buffer + length strings,
+            * rather than 0-terminated C strings. */
+           inbufp[len++] = '\r';
+           inbufp[len++] = '\n';
            inbufp[len] = '\0';
+           linelen = len;
        }
 
        len -= linelen;
@@ -1427,7 +1459,7 @@ int readbody(int sock, struct query *ctl, flag forward, int len)
        /* ship out the text line */
        if (forward && (!issoftline))
        {
-           int n;
+           int n, err;
            inbufp = buf;
 
            /* guard against very long lines */
@@ -1435,22 +1467,31 @@ int readbody(int sock, struct query *ctl, flag forward, int len)
            buf[MSGBUFSIZE+2] = '\n';
            buf[MSGBUFSIZE+3] = '\0';
 
-           n = stuffline(ctl, buf);
-
-           if (n < 0)
-           {
-               report(stdout, GT_("error writing message text\n"));
-               release_sink(ctl);
-               return(PS_IOERR);
-           }
-           else if (want_progress())
-           {
-               fputc('*', stdout);
-               fflush(stdout);
-           }
+           err = rb_send(ctl, buf, &n);
+           if (err != PS_SUCCESS)
+               return err;
        }
     }
 
+    /* Flush buffer -- bug introduced by ESR on 1998-03-20 before
+     * release 4.4.1 when ESR did not sufficiently audit Henrik
+     * Storner's patch.
+     * Trouble reported in June 2011 by Lars Hecking, with
+     * text/html quoted-printable messages generated by
+     * Outlook/Exchange that got mutilated by fetchmail.
+     */
+    if (forward && issoftline)
+    {
+       int n;
+
+       /* force proper line termination */
+       inbufp[0] = '\r';
+       inbufp[1] = '\n';
+       inbufp[2] = '\0';
+
+       return rb_send(ctl, buf, &n);
+    }
+
     return(PS_SUCCESS);
 }
 
@@ -1516,15 +1557,13 @@ int gen_recv(int sock  /** socket to which server is connected */,
 {
     size_t n;
     int oldphase = phase;      /* we don't have to be re-entrant */
-    int retval;
 
     phase = SERVER_WAIT;
-    SockTimeout(sock, mytimeout);
-    retval = SockRead(sock, buf, size);
-    phase = oldphase;
-
-    if (retval == -1)
+    set_timeout(mytimeout);
+    if (SockRead(sock, buf, size) == -1)
     {
+       set_timeout(0);
+       phase = oldphase;
        if(is_idletimeout())
        {
          resetidletimeout();
@@ -1543,6 +1582,7 @@ int gen_recv(int sock  /** socket to which server is connected */,
            buf[--n] = '\0';
        if (outlevel >= O_MONITOR)
            report(stdout, "%s< %s\n", protocol->name, buf);
+       phase = oldphase;
        return(PS_SUCCESS);
     }
 }