Commit 5f649a16 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Move the URL concat code to Curl_follow(), and added a proto for that

function. For Location: following.
parent daea0562
Loading
Loading
Loading
Loading
+236 −229
Original line number Diff line number Diff line
@@ -1228,88 +1228,19 @@ CURLcode Curl_posttransfer(struct SessionHandle *data)
  return CURLE_OK;
}

CURLcode Curl_perform(struct SessionHandle *data)
CURLcode Curl_follow(struct SessionHandle *data,
                     char *newurl) /* this 'newurl' is the Location: string,
                                      and it must be malloc()ed before passed
                                      here */
{
  CURLcode res;
  CURLcode res2;
  struct connectdata *conn=NULL;
  char *newurl = NULL; /* possibly a new URL to follow to! */

  data->state.used_interface = Curl_if_easy;

  res = Curl_pretransfer(data);
  if(res)
    return res;

  /*
   * It is important that there is NO 'return' from this function at any other
   * place than falling down to the end of the function! This is because we
   * have cleanup stuff that must be done before we get back, and that is only
   * performed after this do-while loop.
   */

  do {
    Curl_pgrsTime(data, TIMER_STARTSINGLE);
    res = Curl_connect(data, &conn);
    if(res == CURLE_OK) {
      res = Curl_do(&conn);

      if(res == CURLE_OK) {
        CURLcode res2; /* just a local extra result container */

        if(conn->protocol&PROT_FTPS)
          /* FTPS, disable ssl while transfering data */
          conn->ssl.use = FALSE;
        res = Transfer(conn); /* now fetch that URL please */
        if(conn->protocol&PROT_FTPS)
          /* FTPS, enable ssl again after havving transferred data */
          conn->ssl.use = TRUE;

        if(res == CURLE_OK)
          /*
           * We must duplicate the new URL here as the connection data
           * may be free()ed in the Curl_done() function.
           */
          newurl = conn->newurl?strdup(conn->newurl):NULL;
        else {
          /* The transfer phase returned error, we mark the connection to get
           * closed to prevent being re-used. This is becasue we can't
           * possibly know if the connection is in a good shape or not now. */
          conn->bits.close = TRUE;

          if(-1 !=conn->secondarysocket) {
            /* if we failed anywhere, we must clean up the secondary socket if
               it was used */
            sclose(conn->secondarysocket);
            conn->secondarysocket=-1;
          }
        }

        /* Always run Curl_done(), even if some of the previous calls
           failed, but return the previous (original) error code */
        res2 = Curl_done(conn);

        if(CURLE_OK == res)
          res = res2;
      }

      /*
       * Important: 'conn' cannot be used here, since it may have been closed
       * in 'Curl_done' or other functions.
       */

      if((res == CURLE_OK) && newurl) {
        /* Location: redirect
 
           This is assumed to happen for HTTP(S) only!
        */
  /* Location: redirect */
  char prot[16]; /* URL protocol string storage */
  char letter;   /* used for a silly sscanf */
  
	if (data->set.maxredirs && (data->set.followlocation >= data->set.maxredirs)) {
  if (data->set.maxredirs &&
      (data->set.followlocation >= data->set.maxredirs)) {
    failf(data,"Maximum (%d) redirects followed", data->set.maxredirs);
          res=CURLE_TOO_MANY_REDIRECTS;
	  break;
    return CURLE_TOO_MANY_REDIRECTS;
  }

  /* mark the next request as a followed location: */
@@ -1349,10 +1280,8 @@ CURLcode Curl_perform(struct SessionHandle *data)
       point to read-only data */
    char *url_clone=strdup(data->change.url);

          if(!url_clone) {
            res = CURLE_OUT_OF_MEMORY;
            break; /* skip out of this loop NOW */
          }
    if(!url_clone)
      return CURLE_OUT_OF_MEMORY; /* skip out of this NOW */

    /* protsep points to the start of the host name */
    protsep=strstr(url_clone, "//");
@@ -1422,10 +1351,9 @@ CURLcode Curl_perform(struct SessionHandle *data)
                           1 + /* possible slash */
                           strlen(useurl) + 1/* zero byte */);
    
          if(!newest) {
            res = CURLE_OUT_OF_MEMORY;
            break; /* go go go out from this loop */
          }
    if(!newest)
      return CURLE_OUT_OF_MEMORY; /* go out from this */

    sprintf(newest, "%s%s%s", url_clone,
            (('/' == useurl[0]) || !*protsep)?"":"/",
            useurl);
@@ -1528,9 +1456,88 @@ CURLcode Curl_perform(struct SessionHandle *data)
  }
  Curl_pgrsTime(data, TIMER_REDIRECT);
  Curl_pgrsResetTimes(data);

  return CURLE_OK;
}

CURLcode Curl_perform(struct SessionHandle *data)
{
  CURLcode res;
  CURLcode res2;
  struct connectdata *conn=NULL;
  char *newurl = NULL; /* possibly a new URL to follow to! */

  data->state.used_interface = Curl_if_easy;

  res = Curl_pretransfer(data);
  if(res)
    return res;

  /*
   * It is important that there is NO 'return' from this function at any other
   * place than falling down to the end of the function! This is because we
   * have cleanup stuff that must be done before we get back, and that is only
   * performed after this do-while loop.
   */

  do {
    Curl_pgrsTime(data, TIMER_STARTSINGLE);
    res = Curl_connect(data, &conn);
    if(res == CURLE_OK) {
      res = Curl_do(&conn);

      if(res == CURLE_OK) {
        CURLcode res2; /* just a local extra result container */

        if(conn->protocol&PROT_FTPS)
          /* FTPS, disable ssl while transfering data */
          conn->ssl.use = FALSE;
        res = Transfer(conn); /* now fetch that URL please */
        if(conn->protocol&PROT_FTPS)
          /* FTPS, enable ssl again after havving transferred data */
          conn->ssl.use = TRUE;

        if(res == CURLE_OK)
          /*
           * We must duplicate the new URL here as the connection data
           * may be free()ed in the Curl_done() function.
           */
          newurl = conn->newurl?strdup(conn->newurl):NULL;
        else {
          /* The transfer phase returned error, we mark the connection to get
           * closed to prevent being re-used. This is becasue we can't
           * possibly know if the connection is in a good shape or not now. */
          conn->bits.close = TRUE;

          if(-1 !=conn->secondarysocket) {
            /* if we failed anywhere, we must clean up the secondary socket if
               it was used */
            sclose(conn->secondarysocket);
            conn->secondarysocket=-1;
          }
        }

        /* Always run Curl_done(), even if some of the previous calls
           failed, but return the previous (original) error code */
        res2 = Curl_done(conn);

        if(CURLE_OK == res)
          res = res2;
      }

      /*
       * Important: 'conn' cannot be used here, since it may have been closed
       * in 'Curl_done' or other functions.
       */

      if((res == CURLE_OK) && newurl) {
        res = Curl_follow(data, newurl);
        if(CURLE_OK == res) {
          newurl = NULL;
          continue;
        }
      }
    }
    break; /* it only reaches here when this shouldn't loop */

  } while(1); /* loop if Location: */
+1 −2
Original line number Diff line number Diff line
@@ -23,10 +23,9 @@
 * $Id$
 ***************************************************************************/
CURLcode Curl_perform(struct SessionHandle *data);

CURLcode Curl_pretransfer(struct SessionHandle *data);
CURLcode Curl_posttransfer(struct SessionHandle *data);

CURLcode Curl_follow(struct SessionHandle *data, char *newurl);
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
void Curl_single_fdset(struct connectdata *conn, 
                       fd_set *read_fd_set,