Factored out Curl_copy_header_value
authorDan Fandrich <dan@coneharvesters.com>
Wed, 30 Jul 2008 20:11:51 +0000 (20:11 +0000)
committerDan Fandrich <dan@coneharvesters.com>
Wed, 30 Jul 2008 20:11:51 +0000 (20:11 +0000)
lib/http.c
lib/http.h
lib/transfer.c

index c65b0cf..0da7156 100644 (file)
@@ -181,6 +181,60 @@ static char *checkheaders(struct SessionHandle *data, const char *thisheader)
 }
 
 /*
+ * Strip off leading and trailing whitespace from the value in the
+ * given HTTP header line and return a strdupped copy. Returns NULL in
+ * case of allocation failure. Returns an empty string if the header value
+ * consists entirely of whitespace.
+ */
+char *Curl_copy_header_value(const char *h)
+{
+  const char *start;
+  const char *end;
+  char *value;
+  size_t len;
+
+  DEBUGASSERT(h);
+
+  /* Find the end of the header name */
+  while (*h && (*h != ':'))
+    ++h;
+
+  if (*h)
+    /* Skip over colon */
+    ++h;
+
+  /* Find the first non-space letter */
+  for(start=h;
+      *start && ISSPACE(*start);
+      start++)
+    ;  /* empty loop */
+
+  /* data is in the host encoding so
+     use '\r' and '\n' instead of 0x0d and 0x0a */
+  end = strchr(start, '\r');
+  if(!end)
+    end = strchr(start, '\n');
+  if(!end)
+    end = strchr(start, '\0');
+
+  /* skip all trailing space letters */
+  for(; ISSPACE(*end) && (end > start); end--)
+    ;  /* empty loop */
+
+  /* get length of the type */
+  len = end-start+1;
+
+  value = malloc(len + 1);
+  if(!value)
+    return NULL;
+
+  memcpy(value, start, len);
+  value[len] = 0; /* zero terminate */
+
+  return value;
+}
+
+/*
  * http_output_basic() sets up an Authorization: header (or the proxy version)
  * for HTTP Basic authentication.
  *
@@ -668,6 +722,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
       /* if exactly this is wanted, go */
       int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
       if(neg == 0) {
+        DEBUGASSERT(!data->req.newurl);
         data->req.newurl = strdup(data->change.url);
         data->state.authproblem = (data->req.newurl == NULL);
       }
@@ -2094,23 +2149,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
        custom Host: header if this is NOT a redirect, as setting Host: in the
        redirected request is being out on thin ice. Except if the host name
        is the same as the first one! */
-    char *start = ptr+strlen("Host:");
-    while(*start && ISSPACE(*start ))
-      start++;
-    ptr = start; /* start host-scanning here */
-
-    /* scan through the string to find the end (space or colon) */
-    while(*ptr && !ISSPACE(*ptr) && !(':'==*ptr))
-      ptr++;
-
-    if(ptr != start) {
-      size_t len=ptr-start;
+    char *cookiehost = Curl_copy_header_value(ptr);
+    if (!cookiehost)
+      return CURLE_OUT_OF_MEMORY;
+    if (!*cookiehost)
+      /* ignore empty data */
+      free(cookiehost);
+    else {
+      char *colon = strchr(cookiehost, ':');
+      if (colon)
+        *colon = 0; /* The host must not include an embedded port number */
       Curl_safefree(conn->allocptr.cookiehost);
-      conn->allocptr.cookiehost = malloc(len+1);
-      if(!conn->allocptr.cookiehost)
-        return CURLE_OUT_OF_MEMORY;
-      memcpy(conn->allocptr.cookiehost, start, len);
-      conn->allocptr.cookiehost[len]=0;
+      conn->allocptr.cookiehost = cookiehost;
     }
 #endif
 
index f41ebb6..5a04f8c 100644 (file)
@@ -35,6 +35,8 @@ bool Curl_compareheader(const char *headerline,  /* line to check */
                         const char *header,   /* header keyword _with_ colon */
                         const char *content); /* content string to find */
 
+char *Curl_copy_header_value(const char *h);
+
 /* ftp can use this as well */
 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
                            int tunnelsocket,
index 4201ad1..7f59be8 100644 (file)
 
 #define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */
 
+
 /*
  * This function will call the read callback to fill our buffer with data
  * to upload.
@@ -927,42 +928,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
                     ", closing after transfer\n", contentlength);
             }
           }
-          /* check for Content-Type: header lines to get the mime-type */
+          /* check for Content-Type: header lines to get the MIME-type */
           else if(checkprefix("Content-Type:", k->p)) {
-            char *start;
-            char *end;
-            size_t len;
-
-            /* Find the first non-space letter */
-            for(start=k->p+13;
-                *start && ISSPACE(*start);
-                start++)
-              ;  /* empty loop */
-
-            /* data is now in the host encoding so
-               use '\r' and '\n' instead of 0x0d and 0x0a */
-            end = strchr(start, '\r');
-            if(!end)
-              end = strchr(start, '\n');
-
-            if(end) {
-              /* skip all trailing space letters */
-              for(; ISSPACE(*end) && (end > start); end--)
-                ;  /* empty loop */
-
-              /* get length of the type */
-              len = end-start+1;
-
-              /* allocate memory of a cloned copy */
+            char *contenttype = Curl_copy_header_value(k->p);
+            if (!contenttype)
+              return CURLE_OUT_OF_MEMORY;
+            if (!*contenttype)
+              /* ignore empty data */
+              free(contenttype);
+            else {
               Curl_safefree(data->info.contenttype);
-
-              data->info.contenttype = malloc(len + 1);
-              if(NULL == data->info.contenttype)
-                return CURLE_OUT_OF_MEMORY;
-
-              /* copy the content-type string */
-              memcpy(data->info.contenttype, start, len);
-              data->info.contenttype[len] = 0; /* zero terminate */
+              data->info.contenttype = contenttype;
             }
           }
 #ifndef CURL_DISABLE_HTTP
@@ -1123,36 +1099,19 @@ CURLcode Curl_readwrite(struct connectdata *conn,
           }
           else if((k->httpcode >= 300 && k->httpcode < 400) &&
                   checkprefix("Location:", k->p)) {
-            /* this is the URL that the server advices us to use instead */
-            char *ptr;
-            char *start=k->p;
-            char backup;
-
-            start += 9; /* pass "Location:" */
-
-            /* Skip spaces and tabs. We do this to support multiple
-               white spaces after the "Location:" keyword. */
-            while(*start && ISSPACE(*start ))
-              start++;
-
-            /* Scan through the string from the end to find the last
-               non-space. k->end_ptr points to the actual terminating zero
-               letter, move pointer one letter back and start from
-               there. This logic strips off trailing whitespace, but keeps
-               any embedded whitespace. */
-            ptr = k->end_ptr-1;
-            while((ptr>=start) && ISSPACE(*ptr))
-              ptr--;
-            ptr++;
-
-            backup = *ptr; /* store the ending letter */
-            if(ptr != start) {
-              *ptr = '\0';   /* zero terminate */
-              data->req.location = strdup(start); /* clone string */
-              *ptr = backup; /* restore ending letter */
-              if(!data->req.location)
-                return CURLE_OUT_OF_MEMORY;
+            /* this is the URL that the server advises us to use instead */
+            char *location = Curl_copy_header_value(k->p);
+            if (!location)
+              return CURLE_OUT_OF_MEMORY;
+            if (!*location)
+              /* ignore empty data */
+              free(location);
+            else {
+              DEBUGASSERT(!data->req.location);
+              data->req.location = location;
+
               if(data->set.http_follow_location) {
+                DEBUGASSERT(!data->req.newurl);
                 data->req.newurl = strdup(data->req.location); /* clone */
                 if(!data->req.newurl)
                   return CURLE_OUT_OF_MEMORY;