]> granicus.if.org Git - curl/commitdiff
David McCreedy's "transfer.c fixes for CURL_DO_LINEEND_CONV and non-ASCII platform...
authorYang Tse <yangsita@gmail.com>
Mon, 4 May 2009 09:47:02 +0000 (09:47 +0000)
committerYang Tse <yangsita@gmail.com>
Mon, 4 May 2009 09:47:02 +0000 (09:47 +0000)
CHANGES
RELEASE-NOTES
TODO-RELEASE
lib/transfer.c

diff --git a/CHANGES b/CHANGES
index 13806a89939b46eff1effbceef61ca4bf97539e7..c7a8ab3754054040f4b3d0dbbdf2383f2e934f73 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,14 @@
 
                                   Changelog
 
+Yang Tse (4 May 2009)
+- Applied David McCreedy's "transfer.c fixes for CURL_DO_LINEEND_CONV and
+  non-ASCII platform HTTP requests" patch addressing two HTTP PUT problems:
+  1) On non-ASCII platforms not all of the protocol portions of the PUT are
+  being translated to ASCII.  2) On all platforms the line endings of part of
+  the protocol portions are mangled from CRLF to CRCRLF if data->set.crlf or
+  data->set.prefer_ascii are set (depending on CURL_DO_LINEEND_CONV).
+
 Daniel Fandrich (3 May 2009)
 - Added and disabled test case 563 which shows KNOWN_BUGS #59.  The bug
   report failed to mention that a proxy must be used to reproduce it.
index be289f07f25aa4273bc142a27d9a43a4e580fbac..11e3a66487f7097ffd86f85dfbc87e4526721fef 100644 (file)
@@ -38,6 +38,7 @@ This release includes the following bugfixes:
  o Enhanced upload speeds on Windows
  o TFTP problems after a failed transfer to the same host
  o improved out of the box TPF compatibility
+ o HTTP PUT protocol line endings portions mangled from CRLF to CRCRLF
 
 This release includes the following known bugs:
 
index ca90e76262662a88cd4eeb17f80c9191803281f1..9041157183571f9c29c0a00b09e0bdab70b2ed9c 100644 (file)
@@ -9,9 +9,6 @@ To be addressed in 7.19.5 (planned release: May 2009)
 
 228 - rpath problems in linking with custom openssl
 
-232 - [PATCH] transfer.c fixes for CURL_DO_LINEEND_CONV and non-ASCII 
-      platform HTTP requests
-
 233 - [PATCH] Allow Curl test suite test #251 to work if client and server 
       are on different machines
 
index 0056792e727f861d9c625d26aad376fff015c0eb..6403384bfff32ad9505b74c1bf92c2f94688e623 100644 (file)
@@ -130,12 +130,19 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
   struct SessionHandle *data = conn->data;
   size_t buffersize = (size_t)bytes;
   int nread;
+  int sending_http_headers = FALSE;
 
   if(data->req.upload_chunky) {
     /* if chunked Transfer-Encoding */
     buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
     data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
   }
+  if((data->state.proto.http)
+  && (data->state.proto.http->sending == HTTPSEND_REQUEST)) {
+     /* We're sending the HTTP request headers, not the data.
+        Remember that so we don't re-translate them into garbage. */
+     sending_http_headers = TRUE;
+  }
 
   /* this function returns a size_t, so we typecast to int to prevent warnings
      with picky compilers */
@@ -166,10 +173,40 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
   }
 
   if(!data->req.forbidchunk && data->req.upload_chunky) {
-    /* if chunked Transfer-Encoding */
+    /* if chunked Transfer-Encoding 
+     *    build chunk:
+     *
+     *        <HEX SIZE> CRLF
+     *        <DATA> CRLF
+     */
+    /* On non-ASCII platforms the <DATA> may or may not be
+       translated based on set.prefer_ascii while the protocol
+       portion must always be translated to the network encoding.
+       To further complicate matters, line end conversion might be
+       done later on, so we need to prevent CRLFs from becoming
+       CRCRLFs if that's the case.  To do this we use bare LFs
+       here, knowing they'll become CRLFs later on.
+     */
+
     char hexbuffer[11];
-    int hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
-                          "%x\r\n", nread);
+    const char *endofline_native;
+    const char *endofline_network;
+    int hexlen;
+#ifdef CURL_DO_LINEEND_CONV
+    if((data->set.crlf) || (data->set.prefer_ascii)) {
+#else
+    if(data->set.crlf) {
+#endif /* CURL_DO_LINEEND_CONV */
+      /* \n will become \r\n later on */
+      endofline_native  = "\n";
+      endofline_network = "\x0a";
+    } else {
+      endofline_native  = "\r\n";
+      endofline_network = "\x0d\x0a";
+    }
+    hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
+                      "%x%s", nread, endofline_native);
+
     /* move buffer pointer */
     data->req.upload_fromhere -= hexlen;
     nread += hexlen;
@@ -177,29 +214,48 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
     /* copy the prefix to the buffer, leaving out the NUL */
     memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
 
-    /* always append CRLF to the data */
-    memcpy(data->req.upload_fromhere + nread, "\r\n", 2);
+    /* always append ASCII CRLF to the data */  
+    memcpy(data->req.upload_fromhere + nread, 
+           endofline_network, 
+           strlen(endofline_network));
+
+#ifdef CURL_DOES_CONVERSIONS
+    CURLcode res;
+    int length;
+    if(data->set.prefer_ascii) {
+      /* translate the protocol and data */
+      length = nread;
+    } else {
+      /* just translate the protocol portion */
+      length = strlen(hexbuffer);
+    }
+    res = Curl_convert_to_network(data, data->req.upload_fromhere, length);
+    /* Curl_convert_to_network calls failf if unsuccessful */
+    if(res != CURLE_OK) {
+      return(res);
+    }
+#endif /* CURL_DOES_CONVERSIONS */
 
     if((nread - hexlen) == 0) {
       /* mark this as done once this chunk is transfered */
       data->req.upload_done = TRUE;
     }
 
-    nread+=2; /* for the added CRLF */
-  }
-
-  *nreadp = nread;
-
+    nread+=strlen(endofline_native); /* for the added end of line */
 #ifdef CURL_DOES_CONVERSIONS
-  if(data->set.prefer_ascii) {
-    CURLcode res;
-    res = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
-    /* Curl_convert_to_network calls failf if unsuccessful */
-    if(res != CURLE_OK) {
-      return(res);
+  } else {
+    if((data->set.prefer_ascii) && (!sending_http_headers)) {
+      CURLcode res;
+      res = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
+      /* Curl_convert_to_network calls failf if unsuccessful */
+      if(res != CURLE_OK) {
+        return(res);
+      }
     }
-  }
 #endif /* CURL_DOES_CONVERSIONS */
+  }
+
+  *nreadp = nread;
 
   return CURLE_OK;
 }
@@ -1404,6 +1460,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
   ssize_t bytes_written;
   CURLcode result;
   ssize_t nread; /* number of bytes read */
+  int sending_http_headers = FALSE;
 
   if((k->bytecount == 0) && (k->writebytecount == 0))
     Curl_pgrsTime(data, TIMER_STARTTRANSFER);
@@ -1439,6 +1496,15 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
           break;
         }
 
+        if(data->state.proto.http) {
+          if(data->state.proto.http->sending == HTTPSEND_REQUEST) {
+            /* We're sending the HTTP request headers, not the data.
+               Remember that so we don't change the line endings. */
+               sending_http_headers = TRUE;
+          } else {
+            sending_http_headers = FALSE;
+          }
+        }
         result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
         if(result)
           return result;
@@ -1470,11 +1536,11 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
       /* convert LF to CRLF if so asked */
 #ifdef CURL_DO_LINEEND_CONV
       /* always convert if we're FTPing in ASCII mode */
-      if((data->set.crlf) || (data->set.prefer_ascii))
+        if(((data->set.crlf) || (data->set.prefer_ascii))
 #else
-        if(data->set.crlf)
+        if((data->set.crlf)
 #endif /* CURL_DO_LINEEND_CONV */
-        {
+        && (!sending_http_headers)) {
           if(data->state.scratch == NULL)
             data->state.scratch = malloc(2*BUFSIZE);
           if(data->state.scratch == NULL) {