~ubuntu-branches/ubuntu/lucid/curl/lucid-201101212007

« back to all changes in this revision

Viewing changes to lib/http.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2008-02-08 11:20:41 UTC
  • mto: (3.1.1 lenny) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20080208112041-hed7sb5r6ghmjf8v
Tags: upstream-7.18.0
ImportĀ upstreamĀ versionĀ 7.18.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: http.c,v 1.344 2007-10-23 10:14:24 yangtse Exp $
 
21
 * $Id: http.c,v 1.359 2008-01-25 23:33:45 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
109
109
 * Forward declarations.
110
110
 */
111
111
 
112
 
static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
 
112
static CURLcode https_connecting(struct connectdata *conn, bool *done);
113
113
#ifdef USE_SSL
114
 
static int Curl_https_getsock(struct connectdata *conn,
 
114
static int https_getsock(struct connectdata *conn,
115
115
                              curl_socket_t *socks,
116
116
                              int numsocks);
117
117
#endif
146
146
  Curl_http_done,                       /* done */
147
147
  ZERO_NULL,                            /* do_more */
148
148
  Curl_http_connect,                    /* connect_it */
149
 
  Curl_https_connecting,                /* connecting */
 
149
  https_connecting,                /* connecting */
150
150
  ZERO_NULL,                            /* doing */
151
 
  Curl_https_getsock,                   /* proto_getsock */
 
151
  https_getsock,                   /* proto_getsock */
152
152
  ZERO_NULL,                            /* doing_getsock */
153
153
  ZERO_NULL,                            /* disconnect */
154
154
  PORT_HTTPS,                           /* defport */
176
176
}
177
177
 
178
178
/*
179
 
 * Curl_output_basic() sets up an Authorization: header (or the proxy version)
 
179
 * http_output_basic() sets up an Authorization: header (or the proxy version)
180
180
 * for HTTP Basic authentication.
181
181
 *
182
182
 * Returns CURLcode.
183
183
 */
184
 
static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
 
184
static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
185
185
{
186
186
  char *authorization;
187
187
  struct SessionHandle *data=conn->data;
275
275
static CURLcode perhapsrewind(struct connectdata *conn)
276
276
{
277
277
  struct SessionHandle *data = conn->data;
278
 
  struct HTTP *http = data->reqdata.proto.http;
279
 
  struct Curl_transfer_keeper *k = &data->reqdata.keep;
 
278
  struct HTTP *http = data->state.proto.http;
280
279
  curl_off_t bytessent;
281
280
  curl_off_t expectsend = -1; /* default is unknown */
282
281
 
338
337
    /* This is not NTLM or NTLM with many bytes left to send: close
339
338
     */
340
339
    conn->bits.close = TRUE;
341
 
    k->size = 0; /* don't download any more than 0 bytes */
 
340
    data->req.size = 0; /* don't download any more than 0 bytes */
342
341
  }
343
342
 
344
343
  if(bytessent)
361
360
  bool pickproxy = FALSE;
362
361
  CURLcode code = CURLE_OK;
363
362
 
364
 
  if(100 == data->reqdata.keep.httpcode)
 
363
  if(100 == data->req.httpcode)
365
364
    /* this is a transient response code, ignore */
366
365
    return CURLE_OK;
367
366
 
369
368
    return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
370
369
 
371
370
  if(conn->bits.user_passwd &&
372
 
     ((data->reqdata.keep.httpcode == 401) ||
373
 
      (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
 
371
     ((data->req.httpcode == 401) ||
 
372
      (conn->bits.authneg && data->req.httpcode < 300))) {
374
373
    pickhost = pickoneauth(&data->state.authhost);
375
374
    if(!pickhost)
376
375
      data->state.authproblem = TRUE;
377
376
  }
378
377
  if(conn->bits.proxy_user_passwd &&
379
 
     ((data->reqdata.keep.httpcode == 407) ||
380
 
      (conn->bits.authneg && data->reqdata.keep.httpcode < 300))) {
 
378
     ((data->req.httpcode == 407) ||
 
379
      (conn->bits.authneg && data->req.httpcode < 300))) {
381
380
    pickproxy = pickoneauth(&data->state.authproxy);
382
381
    if(!pickproxy)
383
382
      data->state.authproblem = TRUE;
384
383
  }
385
384
 
386
385
  if(pickhost || pickproxy) {
387
 
    data->reqdata.newurl = strdup(data->change.url); /* clone URL */
388
 
    if (!data->reqdata.newurl)
 
386
    data->req.newurl = strdup(data->change.url); /* clone URL */
 
387
    if(!data->req.newurl)
389
388
      return CURLE_OUT_OF_MEMORY;
390
389
 
391
390
    if((data->set.httpreq != HTTPREQ_GET) &&
397
396
    }
398
397
  }
399
398
 
400
 
  else if((data->reqdata.keep.httpcode < 300) &&
 
399
  else if((data->req.httpcode < 300) &&
401
400
          (!data->state.authhost.done) &&
402
401
          conn->bits.authneg) {
403
402
    /* no (known) authentication available,
406
405
       we didn't try HEAD or GET */
407
406
    if((data->set.httpreq != HTTPREQ_GET) &&
408
407
       (data->set.httpreq != HTTPREQ_HEAD)) {
409
 
      data->reqdata.newurl = strdup(data->change.url); /* clone URL */
410
 
      if (!data->reqdata.newurl)
 
408
      data->req.newurl = strdup(data->change.url); /* clone URL */
 
409
      if(!data->req.newurl)
411
410
        return CURLE_OUT_OF_MEMORY;
412
411
      data->state.authhost.done = TRUE;
413
412
    }
414
413
  }
415
 
  if (Curl_http_should_fail(conn)) {
 
414
  if(Curl_http_should_fail(conn)) {
416
415
    failf (data, "The requested URL returned error: %d",
417
 
           data->reqdata.keep.httpcode);
 
416
           data->req.httpcode);
418
417
    code = CURLE_HTTP_RETURNED_ERROR;
419
418
  }
420
419
 
436
435
 * @returns CURLcode
437
436
 */
438
437
static CURLcode
439
 
Curl_http_output_auth(struct connectdata *conn,
440
 
                      const char *request,
441
 
                      const char *path,
442
 
                      bool proxytunnel) /* TRUE if this is the request setting
443
 
                                           up the proxy tunnel */
 
438
http_output_auth(struct connectdata *conn,
 
439
                 const char *request,
 
440
                 const char *path,
 
441
                 bool proxytunnel) /* TRUE if this is the request setting
 
442
                                      up the proxy tunnel */
444
443
{
445
444
  CURLcode result = CURLE_OK;
446
445
  struct SessionHandle *data = conn->data;
475
474
    authproxy->picked = authproxy->want;
476
475
 
477
476
  /* Send proxy authentication header if needed */
478
 
  if (conn->bits.httpproxy &&
 
477
  if(conn->bits.httpproxy &&
479
478
      (conn->bits.tunnel_proxy == proxytunnel)) {
480
479
#ifdef HAVE_GSSAPI
481
480
    if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) &&
483
482
       !GSS_ERROR(data->state.negotiate.status)) {
484
483
      auth="GSS-Negotiate";
485
484
      result = Curl_output_negotiate(conn, TRUE);
486
 
      if (result)
 
485
      if(result)
487
486
        return result;
488
487
      authproxy->done = TRUE;
489
488
    } 
503
502
        if(conn->bits.proxy_user_passwd &&
504
503
           !checkheaders(data, "Proxy-authorization:")) {
505
504
          auth="Basic";
506
 
          result = Curl_output_basic(conn, TRUE);
 
505
          result = http_output_basic(conn, TRUE);
507
506
          if(result)
508
507
            return result;
509
508
        }
510
 
        /* NOTE: Curl_output_basic() should set 'done' TRUE, as the other auth
 
509
        /* NOTE: http_output_basic() should set 'done' TRUE, as the other auth
511
510
           functions work that way */
512
511
        authproxy->done = TRUE;
513
512
      }
552
551
         !GSS_ERROR(data->state.negotiate.status)) {
553
552
        auth="GSS-Negotiate";
554
553
        result = Curl_output_negotiate(conn, FALSE);
555
 
        if (result)
 
554
        if(result)
556
555
          return result;
557
556
        authhost->done = TRUE;
558
557
      }
583
582
          if(conn->bits.user_passwd &&
584
583
             !checkheaders(data, "Authorization:")) {
585
584
            auth="Basic";
586
 
            result = Curl_output_basic(conn, FALSE);
 
585
            result = http_output_basic(conn, FALSE);
587
586
            if(result)
588
587
              return result;
589
588
          }
627
626
  const char *start;
628
627
  struct auth *authp;
629
628
 
630
 
  if (httpcode == 407) {
 
629
  if(httpcode == 407) {
631
630
    start = header+strlen("Proxy-authenticate:");
632
631
    availp = &data->info.proxyauthavail;
633
632
    authp = &data->state.authproxy;
652
651
   */
653
652
 
654
653
#ifdef HAVE_GSSAPI
655
 
  if (checkprefix("GSS-Negotiate", start) ||
 
654
  if(checkprefix("GSS-Negotiate", start) ||
656
655
      checkprefix("Negotiate", start)) {
657
656
    *availp |= CURLAUTH_GSSNEGOTIATE;
658
657
    authp->avail |= CURLAUTH_GSSNEGOTIATE;
659
658
    if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
660
659
      /* if exactly this is wanted, go */
661
660
      int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
662
 
      if (neg == 0) {
663
 
        data->reqdata.newurl = strdup(data->change.url);
664
 
        data->state.authproblem = (data->reqdata.newurl == NULL);
 
661
      if(neg == 0) {
 
662
        data->req.newurl = strdup(data->change.url);
 
663
        data->state.authproblem = (data->req.newurl == NULL);
665
664
      }
666
665
      else {
667
666
        infof(data, "Authentication problem. Ignoring this.\n");
743
742
int Curl_http_should_fail(struct connectdata *conn)
744
743
{
745
744
  struct SessionHandle *data;
746
 
  struct Curl_transfer_keeper *k;
 
745
  int httpcode;
747
746
 
748
747
  DEBUGASSERT(conn);
749
748
  data = conn->data;
750
749
  DEBUGASSERT(data);
751
750
 
752
 
  /*
753
 
  ** For readability
754
 
  */
755
 
  k = &data->reqdata.keep;
 
751
  httpcode = data->req.httpcode;
756
752
 
757
753
  /*
758
754
  ** If we haven't been asked to fail on error,
759
755
  ** don't fail.
760
756
  */
761
 
  if (!data->set.http_fail_on_error)
 
757
  if(!data->set.http_fail_on_error)
762
758
    return 0;
763
759
 
764
760
  /*
765
761
  ** Any code < 400 is never terminal.
766
762
  */
767
 
  if (k->httpcode < 400)
 
763
  if(httpcode < 400)
768
764
    return 0;
769
765
 
770
 
  if (data->reqdata.resume_from &&
771
 
      (data->set.httpreq==HTTPREQ_GET) &&
772
 
      (k->httpcode == 416)) {
 
766
  if(data->state.resume_from &&
 
767
     (data->set.httpreq==HTTPREQ_GET) &&
 
768
     (httpcode == 416)) {
773
769
    /* "Requested Range Not Satisfiable", just proceed and
774
770
       pretend this is no error */
775
771
    return 0;
779
775
  ** Any code >= 400 that's not 401 or 407 is always
780
776
  ** a terminal error
781
777
  */
782
 
  if ((k->httpcode != 401) &&
783
 
      (k->httpcode != 407))
 
778
  if((httpcode != 401) &&
 
779
      (httpcode != 407))
784
780
    return 1;
785
781
 
786
782
  /*
787
783
  ** All we have left to deal with is 401 and 407
788
784
  */
789
 
  DEBUGASSERT((k->httpcode == 401) || (k->httpcode == 407));
 
785
  DEBUGASSERT((httpcode == 401) || (httpcode == 407));
790
786
 
791
787
  /*
792
788
  ** Examine the current authentication state to see if this
807
803
  infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail);
808
804
  infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode);
809
805
  infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone);
810
 
  infof(data,"%s: newurl = %s\n",__FUNCTION__,data->reqdata.newurl ? data->reqdata.newurl : "(null)");
 
806
  infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ?
 
807
        data->req.newurl : "(null)");
811
808
  infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem);
812
809
#endif
813
810
 
815
812
  ** Either we're not authenticating, or we're supposed to
816
813
  ** be authenticating something else.  This is an error.
817
814
  */
818
 
  if((k->httpcode == 401) && !conn->bits.user_passwd)
 
815
  if((httpcode == 401) && !conn->bits.user_passwd)
819
816
    return TRUE;
820
 
  if((k->httpcode == 407) && !conn->bits.proxy_user_passwd)
 
817
  if((httpcode == 407) && !conn->bits.proxy_user_passwd)
821
818
    return TRUE;
822
819
 
823
820
  return data->state.authproblem;
837
834
                           void *userp)
838
835
{
839
836
  struct connectdata *conn = (struct connectdata *)userp;
840
 
  struct HTTP *http = conn->data->reqdata.proto.http;
 
837
  struct HTTP *http = conn->data->state.proto.http;
841
838
  size_t fullsize = size * nitems;
842
839
 
843
840
  if(0 == http->postsize)
929
926
  CURLcode res;
930
927
  char *ptr;
931
928
  size_t size;
932
 
  struct HTTP *http = conn->data->reqdata.proto.http;
 
929
  struct HTTP *http = conn->data->state.proto.http;
933
930
  size_t sendsize;
934
931
  curl_socket_t sockfd;
 
932
  size_t headersize;
935
933
 
936
934
  DEBUGASSERT(socketindex <= SECONDARYSOCKET);
937
935
 
943
941
  ptr = in->buffer;
944
942
  size = in->size_used;
945
943
 
 
944
  headersize = size - included_body_bytes; /* the initial part that isn't body
 
945
                                              is header */
 
946
 
 
947
  DEBUGASSERT(size > included_body_bytes);
 
948
 
946
949
#ifdef CURL_DOES_CONVERSIONS
947
 
  if(size - included_body_bytes > 0) {
948
 
    res = Curl_convert_to_network(conn->data, ptr, size - included_body_bytes);
949
 
    /* Curl_convert_to_network calls failf if unsuccessful */
950
 
    if(res != CURLE_OK) {
951
 
      /* conversion failed, free memory and return to the caller */
952
 
      if(in->buffer)
953
 
        free(in->buffer);
954
 
      free(in);
955
 
      return res;
956
 
    }
 
950
  res = Curl_convert_to_network(conn->data, ptr, headersize);
 
951
  /* Curl_convert_to_network calls failf if unsuccessful */
 
952
  if(res != CURLE_OK) {
 
953
    /* conversion failed, free memory and return to the caller */
 
954
    if(in->buffer)
 
955
      free(in->buffer);
 
956
    free(in);
 
957
    return res;
957
958
  }
958
959
#endif /* CURL_DOES_CONVERSIONS */
959
960
 
981
982
  res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
982
983
 
983
984
  if(CURLE_OK == res) {
 
985
    /*
 
986
     * Note that we may not send the entire chunk at once, and we have a set
 
987
     * number of data bytes at the end of the big buffer (out of which we may
 
988
     * only send away a part).
 
989
     */
 
990
    /* how much of the header that was sent */
 
991
    size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
 
992
    size_t bodylen = amount - headlen;
984
993
 
985
994
    if(conn->data->set.verbose) {
986
995
      /* this data _may_ contain binary stuff */
987
 
      Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
988
 
                 (size_t)(amount-included_body_bytes), conn);
989
 
      if (included_body_bytes)
 
996
      Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
 
997
      if((size_t)amount > headlen) {
 
998
        /* there was body data sent beyond the initial header part, pass that
 
999
           on to the debug callback too */
990
1000
        Curl_debug(conn->data, CURLINFO_DATA_OUT,
991
 
                   ptr+amount-included_body_bytes,
992
 
                   (size_t)included_body_bytes, conn);
 
1001
                   ptr+headlen, bodylen, conn);
 
1002
      }
993
1003
    }
994
 
    if (included_body_bytes)
 
1004
    if(bodylen)
995
1005
      /* since we sent a piece of the body here, up the byte counter for it
996
1006
         accordingly */
997
 
      http->writebytecount = included_body_bytes;
 
1007
      http->writebytecount += bodylen;
998
1008
 
999
1009
    *bytes_written += amount;
1000
1010
 
1083
1093
  char *new_rb;
1084
1094
  size_t new_size;
1085
1095
 
 
1096
  if(~size < in->size_used) {
 
1097
    /* If resulting used size of send buffer would wrap size_t, cleanup
 
1098
       the whole buffer and return error. Otherwise the required buffer
 
1099
       size will fit into a single allocatable memory chunk */
 
1100
    Curl_safefree(in->buffer);
 
1101
    free(in);
 
1102
    return CURLE_OUT_OF_MEMORY;
 
1103
  }
 
1104
 
1086
1105
  if(!in->buffer ||
1087
1106
     ((in->size_used + size) > (in->size_max - 1))) {
1088
 
    new_size = (in->size_used+size)*2;
 
1107
 
 
1108
    /* If current buffer size isn't enough to hold the result, use a
 
1109
       buffer size that doubles the required size. If this new size
 
1110
       would wrap size_t, then just use the largest possible one */
 
1111
 
 
1112
    if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
 
1113
       (~(size*2) < (in->size_used*2)))
 
1114
      new_size = (size_t)-1;
 
1115
    else
 
1116
      new_size = (in->size_used+size)*2;
 
1117
 
1089
1118
    if(in->buffer)
1090
1119
      /* we have a buffer, enlarge the existing one */
1091
1120
      new_rb = (char *)realloc(in->buffer, new_size);
1188
1217
{
1189
1218
  int subversion=0;
1190
1219
  struct SessionHandle *data=conn->data;
1191
 
  struct Curl_transfer_keeper *k = &data->reqdata.keep;
 
1220
  struct SingleRequest *k = &data->req;
1192
1221
  CURLcode result;
1193
1222
  int res;
1194
1223
  long timeout =
1207
1236
  conn->bits.proxy_connect_closed = FALSE;
1208
1237
 
1209
1238
  do {
1210
 
    if (!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
 
1239
    if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */
1211
1240
      char *host_port;
1212
1241
      send_buffer *req_buffer;
1213
1242
 
1214
1243
      infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
1215
1244
            hostname, remote_port);
1216
1245
 
1217
 
      if(data->reqdata.newurl) {
 
1246
      if(data->req.newurl) {
1218
1247
        /* This only happens if we've looped here due to authentication
1219
1248
           reasons, and we don't really use the newly cloned URL here
1220
1249
           then. Just free() it. */
1221
 
        free(data->reqdata.newurl);
1222
 
        data->reqdata.newurl = NULL;
 
1250
        free(data->req.newurl);
 
1251
        data->req.newurl = NULL;
1223
1252
      }
1224
1253
 
1225
1254
      /* initialize a dynamic send-buffer */
1235
1264
      }
1236
1265
 
1237
1266
      /* Setup the proxy-authorization header, if any */
1238
 
      result = Curl_http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
 
1267
      result = http_output_auth(conn, (char *)"CONNECT", host_port, TRUE);
1239
1268
 
1240
1269
      if(CURLE_OK == result) {
1241
1270
        char *host=(char *)"";
1314
1343
    }
1315
1344
 
1316
1345
    /* if we're in multi-mode and we would block, return instead for a retry */
1317
 
    if (Curl_if_multi == data->state.used_interface) {
1318
 
      if (0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
 
1346
    if(Curl_if_multi == data->state.used_interface) {
 
1347
      if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
1319
1348
        /* return so we'll be called again polling-style */
1320
1349
        return CURLE_OK;
1321
1350
      else {
1380
1409
            keepon = FALSE;
1381
1410
          else if(gotbytes <= 0) {
1382
1411
            keepon = FALSE;
1383
 
            error = SELECT_ERROR;
1384
 
            failf(data, "Proxy CONNECT aborted");
 
1412
            if(data->set.proxyauth && data->state.authproxy.avail) {
 
1413
              /* proxy auth was requested and there was proxy auth available,
 
1414
                 then deem this as "mere" proxy disconnect */
 
1415
              conn->bits.proxy_connect_closed = TRUE;
 
1416
            }
 
1417
            else {
 
1418
              error = SELECT_ERROR;
 
1419
              failf(data, "Proxy CONNECT aborted");
 
1420
            }
1385
1421
          }
1386
1422
          else {
1387
1423
            /*
1561
1597
          }
1562
1598
          break;
1563
1599
        } /* switch */
 
1600
        if(Curl_pgrsUpdate(conn))
 
1601
          return CURLE_ABORTED_BY_CALLBACK;
1564
1602
      } /* while there's buffer left and loop is requested */
1565
1603
 
1566
1604
      if(error)
1571
1609
           headers. 'newurl' is set to a new URL if we must loop. */
1572
1610
        Curl_http_auth_act(conn);
1573
1611
 
1574
 
      if (closeConnection && data->reqdata.newurl) {
 
1612
      if(closeConnection && data->req.newurl) {
1575
1613
        /* Connection closed by server. Don't use it anymore */
1576
1614
        sclose(conn->sock[sockindex]);
1577
1615
        conn->sock[sockindex] = CURL_SOCKET_BAD;
1578
1616
        break;
1579
1617
      }
1580
1618
    } /* END NEGOTIATION PHASE */
1581
 
  } while(data->reqdata.newurl);
 
1619
  } while(data->req.newurl);
1582
1620
 
1583
 
  if(200 != k->httpcode) {
 
1621
  if(200 != data->req.httpcode) {
1584
1622
    failf(data, "Received HTTP code %d from proxy after CONNECT",
1585
 
          k->httpcode);
 
1623
          data->req.httpcode);
1586
1624
 
1587
 
    if (closeConnection && data->reqdata.newurl)
 
1625
    if(closeConnection && data->req.newurl)
1588
1626
      conn->bits.proxy_connect_closed = TRUE;
1589
1627
 
1590
1628
    return CURLE_RECV_ERROR;
1599
1637
  data->state.authproxy.done = TRUE;
1600
1638
 
1601
1639
  infof (data, "Proxy replied OK to CONNECT request\n");
1602
 
  k->ignorebody = FALSE; /* put it (back) to non-ignore state */
 
1640
  data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
1603
1641
  return CURLE_OK;
1604
1642
}
1605
1643
 
1634
1672
      return result;
1635
1673
  }
1636
1674
 
1637
 
  if (conn->bits.tunnel_connecting) {
 
1675
  if(conn->bits.tunnel_connecting) {
1638
1676
    /* nothing else to do except wait right now - we're not done here. */
1639
1677
    return CURLE_OK;
1640
1678
  }
1641
1679
 
1642
1680
  if(!data->state.this_is_a_follow) {
1643
1681
    /* this is not a followed location, get the original host name */
1644
 
    if (data->state.first_host)
 
1682
    if(data->state.first_host)
1645
1683
      /* Free to avoid leaking memory on multiple requests*/
1646
1684
      free(data->state.first_host);
1647
1685
 
1653
1691
  if(conn->protocol & PROT_HTTPS) {
1654
1692
    /* perform SSL initialization */
1655
1693
    if(data->state.used_interface == Curl_if_multi) {
1656
 
      result = Curl_https_connecting(conn, done);
 
1694
      result = https_connecting(conn, done);
1657
1695
      if(result)
1658
1696
        return result;
1659
1697
    }
1672
1710
  return CURLE_OK;
1673
1711
}
1674
1712
 
1675
 
static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
 
1713
static CURLcode https_connecting(struct connectdata *conn, bool *done)
1676
1714
{
1677
1715
  CURLcode result;
1678
1716
  DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS));
1688
1726
#ifdef USE_SSLEAY
1689
1727
/* This function is OpenSSL-specific. It should be made to query the generic
1690
1728
   SSL layer instead. */
1691
 
static int Curl_https_getsock(struct connectdata *conn,
 
1729
static int https_getsock(struct connectdata *conn,
1692
1730
                              curl_socket_t *socks,
1693
1731
                              int numsocks)
1694
1732
{
1695
 
  if (conn->protocol & PROT_HTTPS) {
 
1733
  if(conn->protocol & PROT_HTTPS) {
1696
1734
    struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1697
1735
 
1698
1736
    if(!numsocks)
1699
1737
      return GETSOCK_BLANK;
1700
1738
 
1701
 
    if (connssl->connecting_state == ssl_connect_2_writing) {
 
1739
    if(connssl->connecting_state == ssl_connect_2_writing) {
1702
1740
      /* write mode */
1703
1741
      socks[0] = conn->sock[FIRSTSOCKET];
1704
1742
      return GETSOCK_WRITESOCK(0);
1705
1743
    }
1706
 
    else if (connssl->connecting_state == ssl_connect_2_reading) {
 
1744
    else if(connssl->connecting_state == ssl_connect_2_reading) {
1707
1745
      /* read mode */
1708
1746
      socks[0] = conn->sock[FIRSTSOCKET];
1709
1747
      return GETSOCK_READSOCK(0);
1713
1751
}
1714
1752
#else
1715
1753
#ifdef USE_GNUTLS
1716
 
int Curl_https_getsock(struct connectdata *conn,
 
1754
int https_getsock(struct connectdata *conn,
1717
1755
                       curl_socket_t *socks,
1718
1756
                       int numsocks)
1719
1757
{
1724
1762
}
1725
1763
#else
1726
1764
#ifdef USE_NSS
1727
 
int Curl_https_getsock(struct connectdata *conn,
 
1765
int https_getsock(struct connectdata *conn,
1728
1766
                       curl_socket_t *socks,
1729
1767
                       int numsocks)
1730
1768
{
1735
1773
}
1736
1774
#else
1737
1775
#ifdef USE_QSOSSL
1738
 
int Curl_https_getsock(struct connectdata *conn,
 
1776
int https_getsock(struct connectdata *conn,
1739
1777
                       curl_socket_t *socks,
1740
1778
                       int numsocks)
1741
1779
{
1758
1796
                        CURLcode status, bool premature)
1759
1797
{
1760
1798
  struct SessionHandle *data = conn->data;
1761
 
  struct HTTP *http =data->reqdata.proto.http;
1762
 
  struct Curl_transfer_keeper *k = &data->reqdata.keep;
 
1799
  struct HTTP *http =data->state.proto.http;
1763
1800
  (void)premature; /* not used */
1764
1801
 
1765
1802
  /* set the proper values (possibly modified on POST) */
1766
1803
  conn->fread_func = data->set.fread_func; /* restore */
1767
1804
  conn->fread_in = data->set.in; /* restore */
 
1805
  conn->seek_func = data->set.seek_func; /* restore */
 
1806
  conn->seek_client = data->set.seek_client; /* restore */
1768
1807
 
1769
 
  if (http == NULL)
 
1808
  if(http == NULL)
1770
1809
    return CURLE_OK;
1771
1810
 
1772
1811
  if(http->send_buffer) {
1778
1817
  }
1779
1818
 
1780
1819
  if(HTTPREQ_POST_FORM == data->set.httpreq) {
1781
 
    k->bytecount = http->readbytecount + http->writebytecount;
 
1820
    data->req.bytecount = http->readbytecount + http->writebytecount;
1782
1821
 
1783
1822
    Curl_formclean(&http->sendit); /* Now free that whole lot */
1784
1823
    if(http->form.fp) {
1788
1827
    }
1789
1828
  }
1790
1829
  else if(HTTPREQ_PUT == data->set.httpreq)
1791
 
    k->bytecount = http->readbytecount + http->writebytecount;
 
1830
    data->req.bytecount = http->readbytecount + http->writebytecount;
1792
1831
 
1793
 
  if (status != CURLE_OK)
 
1832
  if(status != CURLE_OK)
1794
1833
    return (status);
1795
1834
 
1796
1835
  if(!conn->bits.retry &&
1797
1836
     ((http->readbytecount +
1798
 
       data->reqdata.keep.headerbytecount -
1799
 
       data->reqdata.keep.deductheadercount)) <= 0) {
 
1837
       data->req.headerbytecount -
 
1838
       data->req.deductheadercount)) <= 0) {
1800
1839
    /* If this connection isn't simply closed to be retried, AND nothing was
1801
1840
       read from the HTTP server (that counts), this can't be right so we
1802
1841
       return an error here */
1879
1918
  char *buf = data->state.buffer; /* this is a short cut to the buffer */
1880
1919
  CURLcode result=CURLE_OK;
1881
1920
  struct HTTP *http;
1882
 
  char *ppath = data->reqdata.path;
 
1921
  char *ppath = data->state.path;
1883
1922
  char ftp_typecode[sizeof(";type=?")] = "";
1884
1923
  char *host = conn->host.name;
1885
1924
  const char *te = ""; /* transfer-encoding */
1898
1937
     sessionhandle, deal with it */
1899
1938
  Curl_reset_reqproto(conn);
1900
1939
 
1901
 
  if(!data->reqdata.proto.http) {
 
1940
  if(!data->state.proto.http) {
1902
1941
    /* Only allocate this struct if we don't already have it! */
1903
1942
 
1904
1943
    http = (struct HTTP *)calloc(sizeof(struct HTTP), 1);
1905
1944
    if(!http)
1906
1945
      return CURLE_OUT_OF_MEMORY;
1907
 
    data->reqdata.proto.http = http;
 
1946
    data->state.proto.http = http;
1908
1947
  }
1909
1948
  else
1910
 
    http = data->reqdata.proto.http;
 
1949
    http = data->state.proto.http;
1911
1950
 
1912
 
  if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
 
1951
  if( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
1913
1952
       data->set.upload) {
1914
1953
    httpreq = HTTPREQ_PUT;
1915
1954
  }
1951
1990
  }
1952
1991
 
1953
1992
  /* setup the authentication headers */
1954
 
  result = Curl_http_output_auth(conn, request, ppath, FALSE);
 
1993
  result = http_output_auth(conn, request, ppath, FALSE);
1955
1994
  if(result)
1956
1995
    return result;
1957
1996
 
1990
2029
      Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
1991
2030
  }
1992
2031
  else {
1993
 
    if (httpreq == HTTPREQ_GET)
 
2032
    if(httpreq == HTTPREQ_GET)
1994
2033
      conn->bits.upload_chunky = FALSE;
1995
2034
    if(conn->bits.upload_chunky)
1996
2035
      te = "Transfer-Encoding: chunked\r\n";
2035
2074
 
2036
2075
    if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
2037
2076
       (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
2038
 
      /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
 
2077
      /* if(HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
2039
2078
         the port number in the host string */
2040
2079
      conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2041
2080
                                    conn->bits.ipv6_ip?"[":"",
2053
2092
      return CURLE_OUT_OF_MEMORY;
2054
2093
  }
2055
2094
 
2056
 
  if (conn->bits.httpproxy && !conn->bits.tunnel_proxy)  {
 
2095
  if(conn->bits.httpproxy && !conn->bits.tunnel_proxy)  {
2057
2096
    /* Using a proxy but does not tunnel through it */
2058
2097
 
2059
2098
    /* The path sent to the proxy is in fact the entire URL. But if the remote
2094
2133
      }
2095
2134
    }
2096
2135
    ppath = data->change.url;
2097
 
    /* when doing ftp, append ;type=<a|i> if not present */
2098
 
    if (checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
2099
 
      char *p = strstr(ppath, ";type=");
2100
 
      if (p && p[6] && p[7] == 0) {
2101
 
        switch (toupper((int)((unsigned char)p[6]))) {
2102
 
        case 'A':
2103
 
        case 'D':
2104
 
        case 'I':
2105
 
          break;
2106
 
        default:
2107
 
          p = NULL;
 
2136
    if (data->set.proxy_transfer_mode) {
 
2137
      /* when doing ftp, append ;type=<a|i> if not present */
 
2138
      if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
 
2139
        char *p = strstr(ppath, ";type=");
 
2140
        if(p && p[6] && p[7] == 0) {
 
2141
          switch (toupper((int)((unsigned char)p[6]))) {
 
2142
          case 'A':
 
2143
          case 'D':
 
2144
          case 'I':
 
2145
            break;
 
2146
          default:
 
2147
            p = NULL;
 
2148
          }
2108
2149
        }
 
2150
        if(!p)
 
2151
          snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c",
 
2152
                   data->set.prefer_ascii ? 'a' : 'i');
2109
2153
      }
2110
 
      if (!p)
2111
 
        snprintf(ftp_typecode, sizeof(ftp_typecode), ";type=%c",
2112
 
                 data->set.prefer_ascii ? 'a' : 'i');
2113
2154
    }
2114
2155
  }
2115
2156
  if(HTTPREQ_POST_FORM == httpreq) {
2137
2178
  if(( (HTTPREQ_POST == httpreq) ||
2138
2179
       (HTTPREQ_POST_FORM == httpreq) ||
2139
2180
       (HTTPREQ_PUT == httpreq) ) &&
2140
 
     data->reqdata.resume_from) {
 
2181
     data->state.resume_from) {
2141
2182
    /**********************************************************************
2142
2183
     * Resuming upload in HTTP means that we PUT or POST and that we have
2143
2184
     * got a resume_from value set. The resume value has already created
2146
2187
     * file size before we continue this venture in the dark lands of HTTP.
2147
2188
     *********************************************************************/
2148
2189
 
2149
 
    if(data->reqdata.resume_from < 0 ) {
 
2190
    if(data->state.resume_from < 0 ) {
2150
2191
      /*
2151
2192
       * This is meant to get the size of the present remote-file by itself.
2152
2193
       * We don't support this now. Bail out!
2153
2194
       */
2154
 
       data->reqdata.resume_from = 0;
 
2195
       data->state.resume_from = 0;
2155
2196
    }
2156
2197
 
2157
 
    if(data->reqdata.resume_from && !data->state.this_is_a_follow) {
 
2198
    if(data->state.resume_from && !data->state.this_is_a_follow) {
2158
2199
      /* do we still game? */
2159
 
      curl_off_t passed=0;
2160
2200
 
2161
2201
      /* Now, let's read off the proper amount of bytes from the
2162
 
         input. If we knew it was a proper file we could've just
2163
 
         fseek()ed but we only have a stream here */
2164
 
      do {
2165
 
        size_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed);
2166
 
        size_t actuallyread;
2167
 
 
2168
 
        if(readthisamountnow > BUFSIZE)
2169
 
          readthisamountnow = BUFSIZE;
2170
 
 
2171
 
        actuallyread =
2172
 
          data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow,
2173
 
                          data->set.in);
2174
 
 
2175
 
        passed += actuallyread;
2176
 
        if(actuallyread != readthisamountnow) {
2177
 
          failf(data, "Could only read %" FORMAT_OFF_T
2178
 
                " bytes from the input",
2179
 
                passed);
 
2202
         input. */
 
2203
      if(conn->seek_func) {
 
2204
        curl_off_t readthisamountnow = data->state.resume_from;
 
2205
 
 
2206
        if(conn->seek_func(conn->seek_client,
 
2207
                           readthisamountnow, SEEK_SET) != 0) {
 
2208
          failf(data, "Could not seek stream");
2180
2209
          return CURLE_READ_ERROR;
2181
2210
        }
2182
 
      } while(passed != data->reqdata.resume_from); /* loop until done */
 
2211
      }
 
2212
      else {
 
2213
        curl_off_t passed=0;
 
2214
 
 
2215
        do {
 
2216
          size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
 
2217
          size_t actuallyread;
 
2218
 
 
2219
          if(readthisamountnow > BUFSIZE)
 
2220
            readthisamountnow = BUFSIZE;
 
2221
 
 
2222
          actuallyread = data->set.fread_func(data->state.buffer, 1,
 
2223
                                              (size_t)readthisamountnow,
 
2224
                                              data->set.in);
 
2225
 
 
2226
          passed += actuallyread;
 
2227
          if(actuallyread != readthisamountnow) {
 
2228
            failf(data, "Could only read %" FORMAT_OFF_T
 
2229
                  " bytes from the input",
 
2230
                  passed);
 
2231
            return CURLE_READ_ERROR;
 
2232
          }
 
2233
        } while(passed != data->state.resume_from); /* loop until done */
 
2234
      }
2183
2235
 
2184
2236
      /* now, decrease the size of the read */
2185
2237
      if(data->set.infilesize>0) {
2186
 
        data->set.infilesize -= data->reqdata.resume_from;
 
2238
        data->set.infilesize -= data->state.resume_from;
2187
2239
 
2188
2240
        if(data->set.infilesize <= 0) {
2189
2241
          failf(data, "File already completely uploaded");
2193
2245
      /* we've passed, proceed as normal */
2194
2246
    }
2195
2247
  }
2196
 
  if(data->reqdata.use_range) {
 
2248
  if(data->state.use_range) {
2197
2249
    /*
2198
2250
     * A range is selected. We use different headers whether we're downloading
2199
2251
     * or uploading and we always let customized headers override our internal
2205
2257
      if(conn->allocptr.rangeline)
2206
2258
        free(conn->allocptr.rangeline);
2207
2259
      conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2208
 
                                         data->reqdata.range);
 
2260
                                         data->state.range);
2209
2261
    }
2210
2262
    else if((httpreq != HTTPREQ_GET) &&
2211
2263
            !checkheaders(data, "Content-Range:")) {
2214
2266
      if(conn->allocptr.rangeline)
2215
2267
        free(conn->allocptr.rangeline);
2216
2268
 
2217
 
      if(data->reqdata.resume_from) {
 
2269
      if(data->state.resume_from) {
2218
2270
        /* This is because "resume" was selected */
2219
2271
        curl_off_t total_expected_size=
2220
 
          data->reqdata.resume_from + data->set.infilesize;
 
2272
          data->state.resume_from + data->set.infilesize;
2221
2273
        conn->allocptr.rangeline =
2222
2274
            aprintf("Content-Range: bytes %s%" FORMAT_OFF_T
2223
2275
                    "/%" FORMAT_OFF_T "\r\n",
2224
 
                    data->reqdata.range, total_expected_size-1,
 
2276
                    data->state.range, total_expected_size-1,
2225
2277
                    total_expected_size);
2226
2278
      }
2227
2279
      else {
2229
2281
           append total size */
2230
2282
        conn->allocptr.rangeline =
2231
2283
            aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n",
2232
 
                    data->reqdata.range, data->set.infilesize);
 
2284
                    data->state.range, data->set.infilesize);
2233
2285
      }
2234
2286
      if(!conn->allocptr.rangeline)
2235
2287
        return CURLE_OUT_OF_MEMORY;
2274
2326
                conn->allocptr.proxyuserpwd?
2275
2327
                conn->allocptr.proxyuserpwd:"",
2276
2328
                conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2277
 
                (data->reqdata.use_range && conn->allocptr.rangeline)?
 
2329
                (data->state.use_range && conn->allocptr.rangeline)?
2278
2330
                conn->allocptr.rangeline:"",
2279
2331
                (data->set.str[STRING_USERAGENT] &&
2280
2332
                 *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
2307
2359
        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2308
2360
        co = Curl_cookie_getlist(data->cookies,
2309
2361
                                 conn->allocptr.cookiehost?
2310
 
                                 conn->allocptr.cookiehost:host, data->reqdata.path,
 
2362
                                 conn->allocptr.cookiehost:host,
 
2363
                                 data->state.path,
2311
2364
                                 (bool)(conn->protocol&PROT_HTTPS?TRUE:FALSE));
2312
2365
        Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2313
2366
      }
2330
2383
          }
2331
2384
          co = co->next; /* next cookie please */
2332
2385
        }
2333
 
        Curl_cookie_freelist(store); /* free the cookie list */
 
2386
        Curl_cookie_freelist(store, FALSE); /* free the cookie list */
2334
2387
      }
2335
2388
      if(addcookies && (CURLE_OK == result)) {
2336
2389
        if(!count)
2582
2635
          return result;
2583
2636
      }
2584
2637
 
 
2638
      /* For really small posts we don't use Expect: headers at all, and for
 
2639
         the somewhat bigger ones we allow the app to disable it. Just make
 
2640
         sure that the expect100header is always set to the preferred value
 
2641
         here. */
 
2642
      if(postsize > TINY_INITIAL_POST_SIZE) {
 
2643
        result = expect100(data, req_buffer);
 
2644
        if(result)
 
2645
          return result;
 
2646
      }
 
2647
      else
 
2648
        data->state.expect100header = FALSE;
 
2649
 
2585
2650
      if(data->set.postfields) {
2586
2651
 
2587
 
        /* for really small posts we don't use Expect: headers at all, and for
2588
 
           the somewhat bigger ones we allow the app to disable it */
2589
 
        if(postsize > TINY_INITIAL_POST_SIZE) {
2590
 
          result = expect100(data, req_buffer);
2591
 
          if(result)
2592
 
            return result;
2593
 
        }
2594
 
        else
2595
 
          data->state.expect100header = FALSE;
2596
 
 
2597
2652
        if(!data->state.expect100header &&
2598
2653
           (postsize < MAX_INITIAL_POST_SIZE))  {
2599
2654
          /* if we don't use expect: 100  AND
2656
2711
          /* set the upload size to the progress meter */
2657
2712
          Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
2658
2713
 
2659
 
          /* set the pointer to mark that we will send the post body using
2660
 
             the read callback */
2661
 
          http->postdata = (char *)&http->postdata;
 
2714
          /* set the pointer to mark that we will send the post body using the
 
2715
             read callback, but only if we're not in authenticate
 
2716
             negotiation  */
 
2717
          if(!conn->bits.authneg) {
 
2718
            http->postdata = (char *)&http->postdata;
 
2719
            http->postsize = postsize;
 
2720
          }
2662
2721
        }
2663
2722
      }
2664
2723
      /* issue the request */