~ubuntu-branches/ubuntu/jaunty/cmake/jaunty-security

« back to all changes in this revision

Viewing changes to Source/CTest/Curl/transfer.c

  • Committer: Bazaar Package Importer
  • Author(s): A. Maitland Bottoms
  • Date: 2006-06-18 16:34:11 UTC
  • mfrom: (1.4.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060618163411-pi234s3v6jwlcmof
Tags: 2.4.2-1
* New upstream release (Closes: #338324)
* Put cmake .vim files into /usr/share/vim/addons/plugin/
  where they can be used. (Closes: #366663)
* Install cmake-mode.el so it can be used. (Closes: #366664)
* Ensure cmake FindKDE locates KDE libraries on Debian
  based distributions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *                                  _   _ ____  _
 
3
 *  Project                     ___| | | |  _ \| |
 
4
 *                             / __| | | | |_) | |
 
5
 *                            | (__| |_| |  _ <| |___
 
6
 *                             \___|\___/|_| \_\_____|
 
7
 *
 
8
 * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
 
9
 *
 
10
 * This software is licensed as described in the file COPYING, which
 
11
 * you should have received as part of this distribution. The terms
 
12
 * are also available at http://curl.haxx.se/docs/copyright.html.
 
13
 *
 
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 
15
 * copies of the Software, and permit persons to whom the Software is
 
16
 * furnished to do so, under the terms of the COPYING file.
 
17
 *
 
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 
19
 * KIND, either express or implied.
 
20
 *
 
21
 * $Id: transfer.c,v 1.9 2004/10/13 14:45:30 andy Exp $
 
22
 ***************************************************************************/
 
23
 
 
24
#include "setup.h"
 
25
 
 
26
/* -- WIN32 approved -- */
 
27
#include <stdio.h>
 
28
#include <string.h>
 
29
#include <stdarg.h>
 
30
#include <stdlib.h>
 
31
#include <ctype.h>
 
32
#ifdef HAVE_SYS_TYPES_H
 
33
#include <sys/types.h>
 
34
#endif
 
35
#include <sys/stat.h>
 
36
 
 
37
#include <errno.h>
 
38
 
 
39
#include "strtoofft.h"
 
40
#include "strequal.h"
 
41
 
 
42
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
 
43
#include <time.h>
 
44
#include <io.h>
 
45
#else
 
46
#ifdef HAVE_SYS_SOCKET_H
 
47
#include <sys/socket.h>
 
48
#endif
 
49
#ifdef HAVE_NETINET_IN_H
 
50
#include <netinet/in.h>
 
51
#endif
 
52
#include <sys/time.h>
 
53
#ifdef HAVE_UNISTD_H
 
54
#include <unistd.h>
 
55
#endif
 
56
#include <netdb.h>
 
57
#ifdef HAVE_ARPA_INET_H
 
58
#include <arpa/inet.h>
 
59
#endif
 
60
#ifdef HAVE_NET_IF_H
 
61
#include <net/if.h>
 
62
#endif
 
63
#ifdef HAVE_SYS_IOCTL_H
 
64
#include <sys/ioctl.h>
 
65
#endif
 
66
#include <signal.h>
 
67
 
 
68
#ifdef HAVE_SYS_PARAM_H
 
69
#include <sys/param.h>
 
70
#endif
 
71
 
 
72
#ifdef HAVE_SYS_SELECT_H
 
73
#include <sys/select.h>
 
74
#endif
 
75
 
 
76
#ifndef HAVE_SELECT
 
77
#error "We can't compile without select() support!"
 
78
#endif
 
79
#ifndef HAVE_SOCKET
 
80
#error "We can't compile without socket() support!"
 
81
#endif
 
82
 
 
83
#endif
 
84
 
 
85
#include "urldata.h"
 
86
#include <curl/curl.h>
 
87
#include "netrc.h"
 
88
 
 
89
#include "content_encoding.h"
 
90
#include "hostip.h"
 
91
#include "transfer.h"
 
92
#include "sendf.h"
 
93
#include "speedcheck.h"
 
94
#include "progress.h"
 
95
#include "getdate.h"
 
96
#include "http.h"
 
97
#include "url.h"
 
98
#include "getinfo.h"
 
99
#include "ssluse.h"
 
100
#include "http_digest.h"
 
101
#include "http_ntlm.h"
 
102
#include "http_negotiate.h"
 
103
#include "share.h"
 
104
#include "curl_memory.h"
 
105
 
 
106
#define _MPRINTF_REPLACE /* use our functions only */
 
107
#include <curl/mprintf.h>
 
108
 
 
109
/* The last #include file should be: */
 
110
#include "memdebug.h"
 
111
 
 
112
#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */
 
113
 
 
114
enum {
 
115
  KEEP_NONE,
 
116
  KEEP_READ,
 
117
  KEEP_WRITE
 
118
};
 
119
 
 
120
/* We keep this static and global since this is read-only and NEVER
 
121
   changed. It should just remain a blanked-out timeout value. */
 
122
static struct timeval notimeout={0,0};
 
123
 
 
124
/*
 
125
 * This function will call the read callback to fill our buffer with data
 
126
 * to upload.
 
127
 */
 
128
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
 
129
{
 
130
  struct SessionHandle *data = conn->data;
 
131
  size_t buffersize = (size_t)bytes;
 
132
  int nread;
 
133
 
 
134
  if(conn->bits.upload_chunky) {
 
135
    /* if chunked Transfer-Encoding */
 
136
    buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
 
137
    conn->upload_fromhere += 10; /* 32bit hex + CRLF */
 
138
  }
 
139
 
 
140
  /* this function returns a size_t, so we typecast to int to prevent warnings
 
141
     with picky compilers */
 
142
  nread = (int)conn->fread(conn->upload_fromhere, 1,
 
143
                           buffersize, conn->fread_in);
 
144
 
 
145
  if(nread == CURL_READFUNC_ABORT) {
 
146
    failf(data, "operation aborted by callback\n");
 
147
    return CURLE_ABORTED_BY_CALLBACK;
 
148
  }
 
149
 
 
150
  if(!conn->bits.forbidchunk && conn->bits.upload_chunky) {
 
151
    /* if chunked Transfer-Encoding */
 
152
    char hexbuffer[11];
 
153
    int hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
 
154
                          "%x\r\n", nread);
 
155
    /* move buffer pointer */
 
156
    conn->upload_fromhere -= hexlen;
 
157
    nread += hexlen;
 
158
 
 
159
    /* copy the prefix to the buffer */
 
160
    memcpy(conn->upload_fromhere, hexbuffer, hexlen);
 
161
 
 
162
    /* always append CRLF to the data */
 
163
    memcpy(conn->upload_fromhere + nread, "\r\n", 2);
 
164
 
 
165
    if((nread - hexlen) == 0) {
 
166
      /* mark this as done once this chunk is transfered */
 
167
      conn->keep.upload_done = TRUE;
 
168
    }
 
169
 
 
170
    nread+=2; /* for the added CRLF */
 
171
  }
 
172
 
 
173
  *nreadp = nread;
 
174
 
 
175
  return CURLE_OK;
 
176
}
 
177
 
 
178
/*
 
179
 * checkhttpprefix()
 
180
 *
 
181
 * Returns TRUE if member of the list matches prefix of string
 
182
 */
 
183
static bool
 
184
checkhttpprefix(struct SessionHandle *data,
 
185
                const char *s)
 
186
{
 
187
  struct curl_slist *head = data->set.http200aliases;
 
188
 
 
189
  while (head) {
 
190
    if (checkprefix(head->data, s))
 
191
      return TRUE;
 
192
    head = head->next;
 
193
  }
 
194
 
 
195
  if(checkprefix("HTTP/", s))
 
196
    return TRUE;
 
197
 
 
198
  return FALSE;
 
199
}
 
200
 
 
201
 
 
202
/*
 
203
 * Curl_readwrite() is the low-level function to be called when data is to
 
204
 * be read and written to/from the connection.
 
205
 */
 
206
CURLcode Curl_readwrite(struct connectdata *conn,
 
207
                        bool *done)
 
208
{
 
209
  struct Curl_transfer_keeper *k = &conn->keep;
 
210
  struct SessionHandle *data = conn->data;
 
211
  CURLcode result;
 
212
  ssize_t nread; /* number of bytes read */
 
213
  int didwhat=0;
 
214
 
 
215
  /* These two are used only if no other select() or _fdset() have been
 
216
     invoked before this. This typicly happens if you use the multi interface
 
217
     and call curl_multi_perform() without calling curl_multi_fdset()
 
218
     first. */
 
219
  fd_set extrareadfd;
 
220
  fd_set extrawritefd;
 
221
 
 
222
  fd_set *readfdp = k->readfdp;
 
223
  fd_set *writefdp = k->writefdp;
 
224
  curl_off_t contentlength;
 
225
 
 
226
  if((k->keepon & KEEP_READ) && !readfdp) {
 
227
    /* reading is requested, but no socket descriptor pointer was set */
 
228
    FD_ZERO(&extrareadfd);
 
229
    FD_SET(conn->sockfd, &extrareadfd);
 
230
    readfdp = &extrareadfd;
 
231
 
 
232
    /* no write, no exceptions, no timeout */
 
233
    select(conn->sockfd+1, readfdp, NULL, NULL, &notimeout);
 
234
  }
 
235
  if((k->keepon & KEEP_WRITE) && !writefdp) {
 
236
    /* writing is requested, but no socket descriptor pointer was set */
 
237
    FD_ZERO(&extrawritefd);
 
238
    FD_SET(conn->writesockfd, &extrawritefd);
 
239
    writefdp = &extrawritefd;
 
240
 
 
241
    /* no read, no exceptions, no timeout */
 
242
    select(conn->writesockfd+1, NULL, writefdp, NULL, &notimeout);
 
243
  }
 
244
 
 
245
  do {
 
246
    /* If we still have reading to do, we check if we have a readable
 
247
       socket. Sometimes the reafdp is NULL, if no fd_set was done using
 
248
       the multi interface and then we can do nothing but to attempt a
 
249
       read to be sure. */
 
250
    if((k->keepon & KEEP_READ) &&
 
251
       (!readfdp || FD_ISSET(conn->sockfd, readfdp))) {
 
252
 
 
253
      bool readdone = TRUE;
 
254
 
 
255
      /* This is where we loop until we have read everything there is to
 
256
         read or we get a EWOULDBLOCK */
 
257
      do {
 
258
        size_t buffersize = data->set.buffer_size?
 
259
          data->set.buffer_size:BUFSIZE -1;
 
260
 
 
261
        /* receive data from the network! */
 
262
        int readrc = Curl_read(conn, conn->sockfd, k->buf, buffersize, &nread);
 
263
 
 
264
        /* subzero, this would've blocked */
 
265
        if(0>readrc)
 
266
          break; /* get out of loop */
 
267
 
 
268
        /* get the CURLcode from the int */
 
269
        result = (CURLcode)readrc;
 
270
 
 
271
        if(result>0)
 
272
          return result;
 
273
 
 
274
        if ((k->bytecount == 0) && (k->writebytecount == 0)) {
 
275
          Curl_pgrsTime(data, TIMER_STARTTRANSFER);
 
276
          if(k->wait100_after_headers)
 
277
            /* set time stamp to compare with when waiting for the 100 */
 
278
            k->start100 = Curl_tvnow();
 
279
        }
 
280
 
 
281
        didwhat |= KEEP_READ;
 
282
 
 
283
        /* NULL terminate, allowing string ops to be used */
 
284
        if (0 < nread)
 
285
          k->buf[nread] = 0;
 
286
 
 
287
        /* if we receive 0 or less here, the server closed the connection and
 
288
           we bail out from this! */
 
289
        else if (0 >= nread) {
 
290
          k->keepon &= ~KEEP_READ;
 
291
          FD_ZERO(&k->rkeepfd);
 
292
          readdone = TRUE;
 
293
          break;
 
294
        }
 
295
 
 
296
        /* Default buffer to use when we write the buffer, it may be changed
 
297
           in the flow below before the actual storing is done. */
 
298
        k->str = k->buf;
 
299
 
 
300
        /* Since this is a two-state thing, we check if we are parsing
 
301
           headers at the moment or not. */
 
302
        if (k->header) {
 
303
          /* we are in parse-the-header-mode */
 
304
          bool stop_reading = FALSE;
 
305
 
 
306
          /* header line within buffer loop */
 
307
          do {
 
308
            size_t hbufp_index;
 
309
            size_t rest_length;
 
310
            size_t full_length;
 
311
            int writetype;
 
312
 
 
313
            /* str_start is start of line within buf */
 
314
            k->str_start = k->str;
 
315
 
 
316
            k->end_ptr = strchr (k->str_start, '\n');
 
317
 
 
318
            if (!k->end_ptr) {
 
319
              /* Not a complete header line within buffer, append the data to
 
320
                 the end of the headerbuff. */
 
321
 
 
322
              if (k->hbuflen + nread >= data->state.headersize) {
 
323
                /* We enlarge the header buffer as it is too small */
 
324
                char *newbuff;
 
325
                size_t newsize=CURLMAX((k->hbuflen+nread)*3/2,
 
326
                                       data->state.headersize*2);
 
327
                hbufp_index = k->hbufp - data->state.headerbuff;
 
328
                newbuff = (char *)realloc(data->state.headerbuff, newsize);
 
329
                if(!newbuff) {
 
330
                  failf (data, "Failed to alloc memory for big header!");
 
331
                  return CURLE_OUT_OF_MEMORY;
 
332
                }
 
333
                data->state.headersize=newsize;
 
334
                data->state.headerbuff = newbuff;
 
335
                k->hbufp = data->state.headerbuff + hbufp_index;
 
336
              }
 
337
              memcpy(k->hbufp, k->str, nread);
 
338
              k->hbufp += nread;
 
339
              k->hbuflen += nread;
 
340
              if (!k->headerline && (k->hbuflen>5)) {
 
341
                /* make a first check that this looks like a HTTP header */
 
342
                if(!checkhttpprefix(data, data->state.headerbuff)) {
 
343
                  /* this is not the beginning of a HTTP first header line */
 
344
                  k->header = FALSE;
 
345
                  k->badheader = HEADER_ALLBAD;
 
346
                  break;
 
347
                }
 
348
              }
 
349
 
 
350
              break; /* read more and try again */
 
351
            }
 
352
 
 
353
            /* decrease the size of the remaining (supposed) header line */
 
354
            rest_length = (k->end_ptr - k->str)+1;
 
355
            nread -= rest_length;
 
356
 
 
357
            k->str = k->end_ptr + 1; /* move past new line */
 
358
 
 
359
            full_length = k->str - k->str_start;
 
360
 
 
361
            /*
 
362
             * We're about to copy a chunk of data to the end of the
 
363
             * already received header. We make sure that the full string
 
364
             * fit in the allocated header buffer, or else we enlarge
 
365
             * it.
 
366
             */
 
367
            if (k->hbuflen + full_length >=
 
368
                data->state.headersize) {
 
369
              char *newbuff;
 
370
              size_t newsize=CURLMAX((k->hbuflen+full_length)*3/2,
 
371
                                     data->state.headersize*2);
 
372
              hbufp_index = k->hbufp - data->state.headerbuff;
 
373
              newbuff = (char *)realloc(data->state.headerbuff, newsize);
 
374
              if(!newbuff) {
 
375
                failf (data, "Failed to alloc memory for big header!");
 
376
                return CURLE_OUT_OF_MEMORY;
 
377
              }
 
378
              data->state.headersize= newsize;
 
379
              data->state.headerbuff = newbuff;
 
380
              k->hbufp = data->state.headerbuff + hbufp_index;
 
381
            }
 
382
 
 
383
            /* copy to end of line */
 
384
            strncpy (k->hbufp, k->str_start, full_length);
 
385
            k->hbufp += full_length;
 
386
            k->hbuflen += full_length;
 
387
            *k->hbufp = 0;
 
388
            k->end_ptr = k->hbufp;
 
389
 
 
390
            k->p = data->state.headerbuff;
 
391
 
 
392
            /****
 
393
             * We now have a FULL header line that p points to
 
394
             *****/
 
395
 
 
396
            if(!k->headerline) {
 
397
              /* the first read header */
 
398
              if((k->hbuflen>5) &&
 
399
                 !checkhttpprefix(data, data->state.headerbuff)) {
 
400
                /* this is not the beginning of a HTTP first header line */
 
401
                k->header = FALSE;
 
402
                if(nread)
 
403
                  /* since there's more, this is a partial bad header */
 
404
                  k->badheader = HEADER_PARTHEADER;
 
405
                else {
 
406
                  /* this was all we read so its all a bad header */
 
407
                  k->badheader = HEADER_ALLBAD;
 
408
                  nread = (ssize_t)rest_length;
 
409
                }
 
410
                break;
 
411
              }
 
412
            }
 
413
 
 
414
            if (('\n' == *k->p) || ('\r' == *k->p)) {
 
415
              size_t headerlen;
 
416
              /* Zero-length header line means end of headers! */
 
417
 
 
418
              if ('\r' == *k->p)
 
419
                k->p++; /* pass the \r byte */
 
420
              if ('\n' == *k->p)
 
421
                k->p++; /* pass the \n byte */
 
422
 
 
423
              if(100 == k->httpcode) {
 
424
                /*
 
425
                 * We have made a HTTP PUT or POST and this is 1.1-lingo
 
426
                 * that tells us that the server is OK with this and ready
 
427
                 * to receive the data.
 
428
                 * However, we'll get more headers now so we must get
 
429
                 * back into the header-parsing state!
 
430
                 */
 
431
                k->header = TRUE;
 
432
                k->headerline = 0; /* restart the header line counter */
 
433
                /* if we did wait for this do enable write now! */
 
434
                if (k->write_after_100_header) {
 
435
 
 
436
                  k->write_after_100_header = FALSE;
 
437
                  FD_SET (conn->writesockfd, &k->writefd); /* write */
 
438
                  k->keepon |= KEEP_WRITE;
 
439
                  k->wkeepfd = k->writefd;
 
440
                }
 
441
              }
 
442
              else
 
443
                k->header = FALSE; /* no more header to parse! */
 
444
 
 
445
              if (417 == k->httpcode) {
 
446
                /*
 
447
                 * we got: "417 Expectation Failed" this means:
 
448
                 * we have made a HTTP call and our Expect Header
 
449
                 * seems to cause a problem => abort the write operations
 
450
                 * (or prevent them from starting).
 
451
                 */
 
452
                k->write_after_100_header = FALSE;
 
453
                k->keepon &= ~KEEP_WRITE;
 
454
                FD_ZERO(&k->wkeepfd);
 
455
              }
 
456
 
 
457
#ifndef CURL_DISABLE_HTTP
 
458
              /*
 
459
               * When all the headers have been parsed, see if we should give
 
460
               * up and return an error.
 
461
               */
 
462
              if (Curl_http_should_fail(conn)) {
 
463
                failf (data, "The requested URL returned error: %d",
 
464
                       k->httpcode);
 
465
                return CURLE_HTTP_RETURNED_ERROR;
 
466
              }
 
467
#endif   /* CURL_DISABLE_HTTP */
 
468
 
 
469
              /* now, only output this if the header AND body are requested:
 
470
               */
 
471
              writetype = CLIENTWRITE_HEADER;
 
472
              if (data->set.include_header)
 
473
                writetype |= CLIENTWRITE_BODY;
 
474
 
 
475
              headerlen = k->p - data->state.headerbuff;
 
476
 
 
477
              result = Curl_client_write(data, writetype,
 
478
                                         data->state.headerbuff,
 
479
                                         headerlen);
 
480
              if(result)
 
481
                return result;
 
482
 
 
483
              data->info.header_size += headerlen;
 
484
              conn->headerbytecount += headerlen;
 
485
 
 
486
              conn->deductheadercount =
 
487
                (100 == k->httpcode)?conn->headerbytecount:0;
 
488
 
 
489
              if (conn->resume_from &&
 
490
                  !k->content_range &&
 
491
                  (data->set.httpreq==HTTPREQ_GET)) {
 
492
                if(k->httpcode == 416) {
 
493
                  /* "Requested Range Not Satisfiable" */
 
494
                  stop_reading = TRUE;
 
495
                }
 
496
                else {
 
497
                  /* we wanted to resume a download, although the server
 
498
                   * doesn't seem to support this and we did this with a GET
 
499
                   * (if it wasn't a GET we did a POST or PUT resume) */
 
500
                  failf (data, "HTTP server doesn't seem to support "
 
501
                         "byte ranges. Cannot resume.");
 
502
                  return CURLE_HTTP_RANGE_ERROR;
 
503
                }
 
504
              }
 
505
#ifndef CURL_DISABLE_HTTP
 
506
              if(!stop_reading) {
 
507
                /* Curl_http_auth_act() checks what authentication methods
 
508
                 * that are available and decides which one (if any) to
 
509
                 * use. It will set 'newurl' if an auth metod was picked. */
 
510
                result = Curl_http_auth_act(conn);
 
511
 
 
512
                if(result)
 
513
                  return result;
 
514
              }
 
515
#endif   /* CURL_DISABLE_HTTP */
 
516
 
 
517
              if(!k->header) {
 
518
                /*
 
519
                 * really end-of-headers.
 
520
                 *
 
521
                 * If we requested a "no body", this is a good time to get
 
522
                 * out and return home.
 
523
                 */
 
524
                if(conn->bits.no_body)
 
525
                  stop_reading = TRUE;
 
526
                else {
 
527
                  /* If we know the expected size of this document, we set the
 
528
                     maximum download size to the size of the expected
 
529
                     document or else, we won't know when to stop reading!
 
530
 
 
531
                     Note that we set the download maximum even if we read a
 
532
                     "Connection: close" header, to make sure that
 
533
                     "Content-Length: 0" still prevents us from attempting to
 
534
                     read the (missing) response-body.
 
535
                  */
 
536
                  /* According to RFC2616 section 4.4, we MUST ignore
 
537
                     Content-Length: headers if we are now receiving data
 
538
                     using chunked Transfer-Encoding.
 
539
                  */
 
540
                  if(conn->bits.chunk)
 
541
                    conn->size=-1;
 
542
 
 
543
                }
 
544
                if(-1 != conn->size) {
 
545
                  /* We do this operation even if no_body is true, since this
 
546
                     data might be retrieved later with curl_easy_getinfo()
 
547
                     and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
 
548
 
 
549
                  Curl_pgrsSetDownloadSize(data, conn->size);
 
550
                  conn->maxdownload = conn->size;
 
551
                }
 
552
                /* If max download size is *zero* (nothing) we already
 
553
                   have nothing and can safely return ok now! */
 
554
                if(0 == conn->maxdownload)
 
555
                  stop_reading = TRUE;
 
556
 
 
557
                if(stop_reading) {
 
558
                  /* we make sure that this socket isn't read more now */
 
559
                  k->keepon &= ~KEEP_READ;
 
560
                  FD_ZERO(&k->rkeepfd);
 
561
                }
 
562
 
 
563
                break;          /* exit header line loop */
 
564
              }
 
565
 
 
566
              /* We continue reading headers, so reset the line-based
 
567
                 header parsing variables hbufp && hbuflen */
 
568
              k->hbufp = data->state.headerbuff;
 
569
              k->hbuflen = 0;
 
570
              continue;
 
571
            }
 
572
 
 
573
            /*
 
574
             * Checks for special headers coming up.
 
575
             */
 
576
 
 
577
            if (!k->headerline++) {
 
578
              /* This is the first header, it MUST be the error code line
 
579
                 or else we consiser this to be the body right away! */
 
580
              int httpversion_major;
 
581
              int nc=sscanf(k->p, " HTTP/%d.%d %3d",
 
582
                            &httpversion_major,
 
583
                            &k->httpversion,
 
584
                            &k->httpcode);
 
585
              if (nc==3) {
 
586
                k->httpversion += 10 * httpversion_major;
 
587
              }
 
588
              else {
 
589
                /* this is the real world, not a Nirvana
 
590
                   NCSA 1.5.x returns this crap when asked for HTTP/1.1
 
591
                */
 
592
                nc=sscanf(k->p, " HTTP %3d", &k->httpcode);
 
593
                k->httpversion = 10;
 
594
 
 
595
               /* If user has set option HTTP200ALIASES,
 
596
                  compare header line against list of aliases
 
597
               */
 
598
                if (!nc) {
 
599
                  if (checkhttpprefix(data, k->p)) {
 
600
                    nc = 1;
 
601
                    k->httpcode = 200;
 
602
                    k->httpversion =
 
603
                      (data->set.httpversion==CURL_HTTP_VERSION_1_0)? 10 : 11;
 
604
                  }
 
605
                }
 
606
              }
 
607
 
 
608
              if (nc) {
 
609
                data->info.httpcode = k->httpcode;
 
610
                data->info.httpversion = k->httpversion;
 
611
 
 
612
                /*
 
613
                 * This code executes as part of processing the header.  As a
 
614
                 * result, it's not totally clear how to interpret the
 
615
                 * response code yet as that depends on what other headers may
 
616
                 * be present.  401 and 407 may be errors, but may be OK
 
617
                 * depending on how authentication is working.  Other codes
 
618
                 * are definitely errors, so give up here.
 
619
                 */
 
620
                if (data->set.http_fail_on_error &&
 
621
                    (k->httpcode >= 400) &&
 
622
                    (k->httpcode != 401) &&
 
623
                    (k->httpcode != 407)) {
 
624
                  /* serious error, go home! */
 
625
                  failf (data, "The requested URL returned error: %d",
 
626
                         k->httpcode);
 
627
                  return CURLE_HTTP_RETURNED_ERROR;
 
628
                }
 
629
 
 
630
                if(k->httpversion == 10)
 
631
                  /* Default action for HTTP/1.0 must be to close, unless
 
632
                     we get one of those fancy headers that tell us the
 
633
                     server keeps it open for us! */
 
634
                  conn->bits.close = TRUE;
 
635
 
 
636
                switch(k->httpcode) {
 
637
                case 204:
 
638
                  /* (quote from RFC2616, section 10.2.5): The server has
 
639
                   * fulfilled the request but does not need to return an
 
640
                   * entity-body ... The 204 response MUST NOT include a
 
641
                   * message-body, and thus is always terminated by the first
 
642
                   * empty line after the header fields. */
 
643
                  /* FALLTHROUGH */
 
644
                case 416: /* Requested Range Not Satisfiable, it has the
 
645
                             Content-Length: set as the "real" document but no
 
646
                             actual response is sent. */
 
647
                case 304:
 
648
                  /* (quote from RFC2616, section 10.3.5): The 304 response
 
649
                   * MUST NOT contain a message-body, and thus is always
 
650
                   * terminated by the first empty line after the header
 
651
                   * fields.  */
 
652
                  conn->size=0;
 
653
                  conn->maxdownload=0;
 
654
                  break;
 
655
                default:
 
656
                  /* nothing */
 
657
                  break;
 
658
                }
 
659
              }
 
660
              else {
 
661
                k->header = FALSE;   /* this is not a header line */
 
662
                break;
 
663
              }
 
664
            }
 
665
 
 
666
            /* Check for Content-Length: header lines to get size. Ignore
 
667
               the header completely if we get a 416 response as then we're
 
668
               resuming a document that we don't get, and this header contains
 
669
               info about the true size of the document we didn't get now. */
 
670
            if ((k->httpcode != 416) &&
 
671
                checkprefix("Content-Length:", k->p)) {
 
672
              contentlength = curlx_strtoofft(k->p+15, NULL, 10);
 
673
              if (data->set.max_filesize &&
 
674
                  contentlength > data->set.max_filesize) {
 
675
                failf(data, "Maximum file size exceeded");
 
676
                return CURLE_FILESIZE_EXCEEDED;
 
677
              }
 
678
              if(contentlength >= 0)
 
679
                conn->size = contentlength;
 
680
              else {
 
681
                /* Negative Content-Length is really odd, and we know it
 
682
                   happens for example when older Apache servers send large
 
683
                   files */
 
684
                conn->bits.close = TRUE;
 
685
                infof(data, "Negative content-length: %" FORMAT_OFF_T
 
686
                      ", closing after transfer\n", contentlength);
 
687
              }
 
688
            }
 
689
            /* check for Content-Type: header lines to get the mime-type */
 
690
            else if (checkprefix("Content-Type:", k->p)) {
 
691
              char *start;
 
692
              char *end;
 
693
              size_t len;
 
694
 
 
695
              /* Find the first non-space letter */
 
696
              for(start=k->p+13;
 
697
                  *start && isspace((int)*start);
 
698
                  start++);
 
699
 
 
700
              end = strchr(start, '\r');
 
701
              if(!end)
 
702
                end = strchr(start, '\n');
 
703
 
 
704
              if(end) {
 
705
                /* skip all trailing space letters */
 
706
                for(; isspace((int)*end) && (end > start); end--);
 
707
 
 
708
                /* get length of the type */
 
709
                len = end-start+1;
 
710
 
 
711
                /* allocate memory of a cloned copy */
 
712
                Curl_safefree(data->info.contenttype);
 
713
 
 
714
                data->info.contenttype = malloc(len + 1);
 
715
                if (NULL == data->info.contenttype)
 
716
                  return CURLE_OUT_OF_MEMORY;
 
717
 
 
718
                /* copy the content-type string */
 
719
                memcpy(data->info.contenttype, start, len);
 
720
                data->info.contenttype[len] = 0; /* zero terminate */
 
721
              }
 
722
            }
 
723
#ifndef CURL_DISABLE_HTTP
 
724
            else if((k->httpversion == 10) &&
 
725
                    conn->bits.httpproxy &&
 
726
                    Curl_compareheader(k->p,
 
727
                                       "Proxy-Connection:", "keep-alive")) {
 
728
              /*
 
729
               * When a HTTP/1.0 reply comes when using a proxy, the
 
730
               * 'Proxy-Connection: keep-alive' line tells us the
 
731
               * connection will be kept alive for our pleasure.
 
732
               * Default action for 1.0 is to close.
 
733
               */
 
734
              conn->bits.close = FALSE; /* don't close when done */
 
735
              infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
 
736
            }
 
737
            else if((k->httpversion == 10) &&
 
738
                    Curl_compareheader(k->p, "Connection:", "keep-alive")) {
 
739
              /*
 
740
               * A HTTP/1.0 reply with the 'Connection: keep-alive' line
 
741
               * tells us the connection will be kept alive for our
 
742
               * pleasure.  Default action for 1.0 is to close.
 
743
               *
 
744
               * [RFC2068, section 19.7.1] */
 
745
              conn->bits.close = FALSE; /* don't close when done */
 
746
              infof(data, "HTTP/1.0 connection set to keep alive!\n");
 
747
            }
 
748
            else if (Curl_compareheader(k->p, "Connection:", "close")) {
 
749
              /*
 
750
               * [RFC 2616, section 8.1.2.1]
 
751
               * "Connection: close" is HTTP/1.1 language and means that
 
752
               * the connection will close when this request has been
 
753
               * served.
 
754
               */
 
755
              conn->bits.close = TRUE; /* close when done */
 
756
            }
 
757
            else if (Curl_compareheader(k->p,
 
758
                                        "Transfer-Encoding:", "chunked")) {
 
759
              /*
 
760
               * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
 
761
               * means that the server will send a series of "chunks". Each
 
762
               * chunk starts with line with info (including size of the
 
763
               * coming block) (terminated with CRLF), then a block of data
 
764
               * with the previously mentioned size. There can be any amount
 
765
               * of chunks, and a chunk-data set to zero signals the
 
766
               * end-of-chunks. */
 
767
              conn->bits.chunk = TRUE; /* chunks coming our way */
 
768
 
 
769
              /* init our chunky engine */
 
770
              Curl_httpchunk_init(conn);
 
771
            }
 
772
            else if (checkprefix("Content-Encoding:", k->p) &&
 
773
                     data->set.encoding) {
 
774
              /*
 
775
               * Process Content-Encoding. Look for the values: identity,
 
776
               * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
 
777
               * x-compress are the same as gzip and compress. (Sec 3.5 RFC
 
778
               * 2616). zlib cannot handle compress.  However, errors are
 
779
               * handled further down when the response body is processed
 
780
               */
 
781
              char *start;
 
782
 
 
783
              /* Find the first non-space letter */
 
784
              for(start=k->p+17;
 
785
                  *start && isspace((int)*start);
 
786
                  start++);
 
787
 
 
788
              /* Record the content-encoding for later use */
 
789
              if (checkprefix("identity", start))
 
790
                k->content_encoding = IDENTITY;
 
791
              else if (checkprefix("deflate", start))
 
792
                k->content_encoding = DEFLATE;
 
793
              else if (checkprefix("gzip", start)
 
794
                       || checkprefix("x-gzip", start))
 
795
                k->content_encoding = GZIP;
 
796
              else if (checkprefix("compress", start)
 
797
                       || checkprefix("x-compress", start))
 
798
                k->content_encoding = COMPRESS;
 
799
            }
 
800
            else if (Curl_compareheader(k->p, "Content-Range:", "bytes")) {
 
801
              /* Content-Range: bytes [num]-
 
802
                 Content-Range: bytes: [num]-
 
803
 
 
804
                 The second format was added August 1st 2000 by Igor
 
805
                 Khristophorov since Sun's webserver JavaWebServer/1.1.1
 
806
                 obviously sends the header this way! :-( */
 
807
 
 
808
              char *ptr = strstr(k->p, "bytes");
 
809
              ptr+=5;
 
810
 
 
811
              if(*ptr == ':')
 
812
                /* stupid colon skip */
 
813
                ptr++;
 
814
 
 
815
              k->offset = curlx_strtoofft(ptr, NULL, 10);
 
816
 
 
817
              if (conn->resume_from == k->offset)
 
818
                /* we asked for a resume and we got it */
 
819
                k->content_range = TRUE;
 
820
            }
 
821
            else if(data->cookies &&
 
822
                    checkprefix("Set-Cookie:", k->p)) {
 
823
              Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
 
824
                              CURL_LOCK_ACCESS_SINGLE);
 
825
              Curl_cookie_add(data,
 
826
                              data->cookies, TRUE, k->p+11,
 
827
                              /* If there is a custom-set Host: name, use it
 
828
                                 here, or else use real peer host name. */
 
829
                              conn->allocptr.cookiehost?
 
830
                              conn->allocptr.cookiehost:conn->host.name,
 
831
                              conn->path);
 
832
              Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
 
833
            }
 
834
            else if(checkprefix("Last-Modified:", k->p) &&
 
835
                    (data->set.timecondition || data->set.get_filetime) ) {
 
836
              time_t secs=time(NULL);
 
837
              k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
 
838
                                          &secs);
 
839
              if(data->set.get_filetime)
 
840
                data->info.filetime = k->timeofdoc;
 
841
            }
 
842
            else if((checkprefix("WWW-Authenticate:", k->p) &&
 
843
                     (401 == k->httpcode)) ||
 
844
                    (checkprefix("Proxy-authenticate:", k->p) &&
 
845
                     (407 == k->httpcode))) {
 
846
              result = Curl_http_input_auth(conn, k->httpcode, k->p);
 
847
              if(result)
 
848
                return result;
 
849
            }
 
850
            else if ((k->httpcode >= 300 && k->httpcode < 400) &&
 
851
                     checkprefix("Location:", k->p)) {
 
852
              if(data->set.http_follow_location) {
 
853
                /* this is the URL that the server advices us to get instead */
 
854
                char *ptr;
 
855
                char *start=k->p;
 
856
                char backup;
 
857
 
 
858
                start += 9; /* pass "Location:" */
 
859
 
 
860
                /* Skip spaces and tabs. We do this to support multiple
 
861
                   white spaces after the "Location:" keyword. */
 
862
                while(*start && isspace((int)*start ))
 
863
                  start++;
 
864
 
 
865
                /* Scan through the string from the end to find the last
 
866
                   non-space. k->end_ptr points to the actual terminating zero
 
867
                   letter, move pointer one letter back and start from
 
868
                   there. This logic strips off trailing whitespace, but keeps
 
869
                   any embedded whitespace. */
 
870
                ptr = k->end_ptr-1;
 
871
                while((ptr>=start) && isspace((int)*ptr))
 
872
                  ptr--;
 
873
                ptr++;
 
874
 
 
875
                backup = *ptr; /* store the ending letter */
 
876
                if(ptr != start) {
 
877
                  *ptr = '\0';   /* zero terminate */
 
878
                  conn->newurl = strdup(start); /* clone string */
 
879
                  *ptr = backup; /* restore ending letter */
 
880
                  if(!conn->newurl)
 
881
                    return CURLE_OUT_OF_MEMORY;
 
882
                }
 
883
              }
 
884
            }
 
885
#endif   /* CURL_DISABLE_HTTP */
 
886
 
 
887
            /*
 
888
             * End of header-checks. Write them to the client.
 
889
             */
 
890
 
 
891
            writetype = CLIENTWRITE_HEADER;
 
892
            if (data->set.include_header)
 
893
              writetype |= CLIENTWRITE_BODY;
 
894
 
 
895
            if(data->set.verbose)
 
896
              Curl_debug(data, CURLINFO_HEADER_IN,
 
897
                         k->p, k->hbuflen, conn->host.dispname);
 
898
 
 
899
            result = Curl_client_write(data, writetype, k->p, k->hbuflen);
 
900
            if(result)
 
901
              return result;
 
902
 
 
903
            data->info.header_size += k->hbuflen;
 
904
            conn->headerbytecount += k->hbuflen;
 
905
 
 
906
            /* reset hbufp pointer && hbuflen */
 
907
            k->hbufp = data->state.headerbuff;
 
908
            k->hbuflen = 0;
 
909
          }
 
910
          while (!stop_reading && *k->str); /* header line within buffer */
 
911
 
 
912
          if(stop_reading)
 
913
            /* We've stopped dealing with input, get out of the do-while loop */
 
914
            break;
 
915
 
 
916
          /* We might have reached the end of the header part here, but
 
917
             there might be a non-header part left in the end of the read
 
918
             buffer. */
 
919
 
 
920
        }                       /* end if header mode */
 
921
 
 
922
        /* This is not an 'else if' since it may be a rest from the header
 
923
           parsing, where the beginning of the buffer is headers and the end
 
924
           is non-headers. */
 
925
        if (k->str && !k->header && (nread > 0)) {
 
926
 
 
927
          if(0 == k->bodywrites) {
 
928
            /* These checks are only made the first time we are about to
 
929
               write a piece of the body */
 
930
            if(conn->protocol&PROT_HTTP) {
 
931
              /* HTTP-only checks */
 
932
 
 
933
              if (conn->newurl) {
 
934
                if(conn->bits.close) {
 
935
                  /* Abort after the headers if "follow Location" is set
 
936
                     and we're set to close anyway. */
 
937
                  k->keepon &= ~KEEP_READ;
 
938
                  FD_ZERO(&k->rkeepfd);
 
939
                  *done = TRUE;
 
940
                  return CURLE_OK;
 
941
                }
 
942
                /* We have a new url to load, but since we want to be able
 
943
                   to re-use this connection properly, we read the full
 
944
                   response in "ignore more" */
 
945
                k->ignorebody = TRUE;
 
946
                infof(data, "Ignoring the response-body\n");
 
947
              }
 
948
              if(data->set.timecondition && !conn->range) {
 
949
                /* A time condition has been set AND no ranges have been
 
950
                   requested. This seems to be what chapter 13.3.4 of
 
951
                   RFC 2616 defines to be the correct action for a
 
952
                   HTTP/1.1 client */
 
953
                if((k->timeofdoc > 0) && (data->set.timevalue > 0)) {
 
954
                  switch(data->set.timecondition) {
 
955
                  case CURL_TIMECOND_IFMODSINCE:
 
956
                  default:
 
957
                    if(k->timeofdoc < data->set.timevalue) {
 
958
                      infof(data,
 
959
                            "The requested document is not new enough\n");
 
960
                      *done = TRUE;
 
961
                      return CURLE_OK;
 
962
                    }
 
963
                    break;
 
964
                  case CURL_TIMECOND_IFUNMODSINCE:
 
965
                    if(k->timeofdoc > data->set.timevalue) {
 
966
                      infof(data,
 
967
                            "The requested document is not old enough\n");
 
968
                      *done = TRUE;
 
969
                      return CURLE_OK;
 
970
                    }
 
971
                    break;
 
972
                  } /* switch */
 
973
                } /* two valid time strings */
 
974
              } /* we have a time condition */
 
975
 
 
976
            } /* this is HTTP */
 
977
          } /* this is the first time we write a body part */
 
978
          k->bodywrites++;
 
979
 
 
980
          /* pass data to the debug function before it gets "dechunked" */
 
981
          if(data->set.verbose) {
 
982
            if(k->badheader) {
 
983
              Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
 
984
                         k->hbuflen, conn->host.dispname);
 
985
              if(k->badheader == HEADER_PARTHEADER)
 
986
                Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
 
987
                           conn->host.dispname);
 
988
            }
 
989
            else
 
990
              Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
 
991
                         conn->host.dispname);
 
992
          }
 
993
 
 
994
#ifndef CURL_DISABLE_HTTP
 
995
          if(conn->bits.chunk) {
 
996
            /*
 
997
             * Bless me father for I have sinned. Here comes a chunked
 
998
             * transfer flying and we need to decode this properly.  While
 
999
             * the name says read, this function both reads and writes away
 
1000
             * the data. The returned 'nread' holds the number of actual
 
1001
             * data it wrote to the client.  */
 
1002
            CHUNKcode res =
 
1003
              Curl_httpchunk_read(conn, k->str, nread, &nread);
 
1004
 
 
1005
            if(CHUNKE_OK < res) {
 
1006
              if(CHUNKE_WRITE_ERROR == res) {
 
1007
                failf(data, "Failed writing data");
 
1008
                return CURLE_WRITE_ERROR;
 
1009
              }
 
1010
              failf(data, "Received problem %d in the chunky parser", res);
 
1011
              return CURLE_RECV_ERROR;
 
1012
            }
 
1013
            else if(CHUNKE_STOP == res) {
 
1014
              /* we're done reading chunks! */
 
1015
              k->keepon &= ~KEEP_READ; /* read no more */
 
1016
              FD_ZERO(&k->rkeepfd);
 
1017
 
 
1018
              /* There are now possibly N number of bytes at the end of the
 
1019
                 str buffer that weren't written to the client, but we don't
 
1020
                 care about them right now. */
 
1021
            }
 
1022
            /* If it returned OK, we just keep going */
 
1023
          }
 
1024
#endif   /* CURL_DISABLE_HTTP */
 
1025
 
 
1026
          if((-1 != conn->maxdownload) &&
 
1027
             (k->bytecount + nread >= conn->maxdownload)) {
 
1028
            nread = (ssize_t) (conn->maxdownload - k->bytecount);
 
1029
            if(nread < 0 ) /* this should be unusual */
 
1030
              nread = 0;
 
1031
 
 
1032
            k->keepon &= ~KEEP_READ; /* we're done reading */
 
1033
            FD_ZERO(&k->rkeepfd);
 
1034
          }
 
1035
 
 
1036
          k->bytecount += nread;
 
1037
 
 
1038
          Curl_pgrsSetDownloadCounter(data, k->bytecount);
 
1039
 
 
1040
          if(!conn->bits.chunk && (nread || k->badheader)) {
 
1041
            /* If this is chunky transfer, it was already written */
 
1042
 
 
1043
            if(k->badheader && !k->ignorebody) {
 
1044
              /* we parsed a piece of data wrongly assuming it was a header
 
1045
                 and now we output it as body instead */
 
1046
              result = Curl_client_write(data, CLIENTWRITE_BODY,
 
1047
                                         data->state.headerbuff,
 
1048
                                         k->hbuflen);
 
1049
            }
 
1050
            if(k->badheader < HEADER_ALLBAD) {
 
1051
              /* This switch handles various content encodings. If there's an
 
1052
                 error here, be sure to check over the almost identical code
 
1053
                 in http_chunks.c.
 
1054
                 Make sure that ALL_CONTENT_ENCODINGS contains all the
 
1055
                 encodings handled here. */
 
1056
#ifdef HAVE_LIBZ
 
1057
              switch (k->content_encoding) {
 
1058
              case IDENTITY:
 
1059
#endif
 
1060
                /* This is the default when the server sends no
 
1061
                   Content-Encoding header. See Curl_readwrite_init; the
 
1062
                   memset() call initializes k->content_encoding to zero. */
 
1063
                if(!k->ignorebody)
 
1064
                  result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
 
1065
                                             nread);
 
1066
#ifdef HAVE_LIBZ
 
1067
                break;
 
1068
 
 
1069
              case DEFLATE:
 
1070
                /* Assume CLIENTWRITE_BODY; headers are not encoded. */
 
1071
                result = Curl_unencode_deflate_write(data, k, nread);
 
1072
                break;
 
1073
 
 
1074
              case GZIP:
 
1075
                /* Assume CLIENTWRITE_BODY; headers are not encoded. */
 
1076
                result = Curl_unencode_gzip_write(data, k, nread);
 
1077
                break;
 
1078
 
 
1079
              case COMPRESS:
 
1080
              default:
 
1081
                failf (data, "Unrecognized content encoding type. "
 
1082
                       "libcurl understands `identity', `deflate' and `gzip' "
 
1083
                       "content encodings.");
 
1084
                result = CURLE_BAD_CONTENT_ENCODING;
 
1085
                break;
 
1086
              }
 
1087
#endif
 
1088
            }
 
1089
            k->badheader = HEADER_NORMAL; /* taken care of now */
 
1090
 
 
1091
            if(result)
 
1092
              return result;
 
1093
          }
 
1094
 
 
1095
        } /* if (! header and data to read ) */
 
1096
 
 
1097
      } while(!readdone);
 
1098
 
 
1099
    } /* if( read from socket ) */
 
1100
 
 
1101
    /* If we still have writing to do, we check if we have a writable
 
1102
       socket. Sometimes the writefdp is NULL, if no fd_set was done using
 
1103
       the multi interface and then we can do nothing but to attempt a
 
1104
       write to be sure. */
 
1105
    if((k->keepon & KEEP_WRITE) &&
 
1106
       (!writefdp || FD_ISSET(conn->writesockfd, writefdp)) ) {
 
1107
      /* write */
 
1108
 
 
1109
      int i, si;
 
1110
      ssize_t bytes_written;
 
1111
      bool writedone=TRUE;
 
1112
 
 
1113
      if ((k->bytecount == 0) && (k->writebytecount == 0))
 
1114
        Curl_pgrsTime(data, TIMER_STARTTRANSFER);
 
1115
 
 
1116
      didwhat |= KEEP_WRITE;
 
1117
 
 
1118
      /*
 
1119
       * We loop here to do the READ and SEND loop until we run out of
 
1120
       * data to send or until we get EWOULDBLOCK back
 
1121
       */
 
1122
      do {
 
1123
 
 
1124
        /* only read more data if there's no upload data already
 
1125
           present in the upload buffer */
 
1126
        if(0 == conn->upload_present) {
 
1127
          /* init the "upload from here" pointer */
 
1128
          conn->upload_fromhere = k->uploadbuf;
 
1129
 
 
1130
          if(!k->upload_done) {
 
1131
            /* HTTP pollution, this should be written nicer to become more
 
1132
               protocol agnostic. */
 
1133
            int fillcount;
 
1134
 
 
1135
            if(k->wait100_after_headers &&
 
1136
               (conn->proto.http->sending == HTTPSEND_BODY)) {
 
1137
              /* If this call is to send body data, we must take some action:
 
1138
                 We have sent off the full HTTP 1.1 request, and we shall now
 
1139
                 go into the Expect: 100 state and await such a header */
 
1140
              k->wait100_after_headers = FALSE; /* headers sent */
 
1141
              k->write_after_100_header = TRUE; /* wait for the header */
 
1142
              FD_ZERO (&k->writefd);            /* clear it */
 
1143
              k->wkeepfd = k->writefd;          /* set the keeper variable */
 
1144
              k->keepon &= ~KEEP_WRITE;         /* disable writing */
 
1145
              k->start100 = Curl_tvnow();       /* timeout count starts now */
 
1146
              didwhat &= ~KEEP_WRITE;  /* we didn't write anything actually */
 
1147
              break;
 
1148
            }
 
1149
 
 
1150
            result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
 
1151
            if(result)
 
1152
              return result;
 
1153
 
 
1154
            nread = (ssize_t)fillcount;
 
1155
          }
 
1156
          else
 
1157
            nread = 0; /* we're done uploading/reading */
 
1158
 
 
1159
          /* the signed int typecase of nread of for systems that has
 
1160
             unsigned size_t */
 
1161
          if (nread<=0) {
 
1162
            /* done */
 
1163
            k->keepon &= ~KEEP_WRITE; /* we're done writing */
 
1164
            FD_ZERO(&k->wkeepfd);
 
1165
            writedone = TRUE;
 
1166
            (void)writedone;
 
1167
            break;
 
1168
          }
 
1169
 
 
1170
          /* store number of bytes available for upload */
 
1171
          conn->upload_present = nread;
 
1172
 
 
1173
          /* convert LF to CRLF if so asked */
 
1174
          if (data->set.crlf) {
 
1175
              if(data->state.scratch == NULL)
 
1176
                data->state.scratch = malloc(2*BUFSIZE);
 
1177
              if(data->state.scratch == NULL) {
 
1178
                failf (data, "Failed to alloc scratch buffer!");
 
1179
                return CURLE_OUT_OF_MEMORY;
 
1180
              }
 
1181
            for(i = 0, si = 0; i < nread; i++, si++) {
 
1182
              if (conn->upload_fromhere[i] == 0x0a) {
 
1183
                data->state.scratch[si++] = 0x0d;
 
1184
                data->state.scratch[si] = 0x0a;
 
1185
              }
 
1186
              else
 
1187
                data->state.scratch[si] = conn->upload_fromhere[i];
 
1188
            }
 
1189
            if(si != nread) {
 
1190
              /* only perform the special operation if we really did replace
 
1191
                 anything */
 
1192
              nread = si;
 
1193
 
 
1194
              /* upload from the new (replaced) buffer instead */
 
1195
              conn->upload_fromhere = data->state.scratch;
 
1196
 
 
1197
              /* set the new amount too */
 
1198
              conn->upload_present = nread;
 
1199
            }
 
1200
          }
 
1201
        }
 
1202
        else {
 
1203
          /* We have a partial buffer left from a previous "round". Use
 
1204
             that instead of reading more data */
 
1205
        }
 
1206
 
 
1207
        /* write to socket (send away data) */
 
1208
        result = Curl_write(conn,
 
1209
                            conn->writesockfd,     /* socket to send to */
 
1210
                            conn->upload_fromhere, /* buffer pointer */
 
1211
                            conn->upload_present,  /* buffer size */
 
1212
                            &bytes_written);       /* actually send away */
 
1213
        if(result)
 
1214
          return result;
 
1215
 
 
1216
        if(data->set.verbose)
 
1217
          /* show the data before we change the pointer upload_fromhere */
 
1218
          Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere,
 
1219
                     bytes_written, conn->host.dispname);
 
1220
 
 
1221
        if(conn->upload_present != bytes_written) {
 
1222
          /* we only wrote a part of the buffer (if anything), deal with it! */
 
1223
 
 
1224
          /* store the amount of bytes left in the buffer to write */
 
1225
          conn->upload_present -= bytes_written;
 
1226
 
 
1227
          /* advance the pointer where to find the buffer when the next send
 
1228
             is to happen */
 
1229
          conn->upload_fromhere += bytes_written;
 
1230
 
 
1231
          writedone = TRUE; /* we are done, stop the loop */
 
1232
        }
 
1233
        else {
 
1234
          /* we've uploaded that buffer now */
 
1235
          conn->upload_fromhere = k->uploadbuf;
 
1236
          conn->upload_present = 0; /* no more bytes left */
 
1237
 
 
1238
          if(k->upload_done) {
 
1239
            /* switch off writing, we're done! */
 
1240
            k->keepon &= ~KEEP_WRITE; /* we're done writing */
 
1241
            FD_ZERO(&k->wkeepfd);
 
1242
            writedone = TRUE;
 
1243
          }
 
1244
        }
 
1245
 
 
1246
        k->writebytecount += bytes_written;
 
1247
        Curl_pgrsSetUploadCounter(data, k->writebytecount);
 
1248
 
 
1249
      } while(!writedone); /* loop until we're done writing! */
 
1250
 
 
1251
    }
 
1252
 
 
1253
  } while(0); /* just to break out from! */
 
1254
 
 
1255
  k->now = Curl_tvnow();
 
1256
  if(didwhat) {
 
1257
    /* Update read/write counters */
 
1258
    if(conn->bytecountp)
 
1259
      *conn->bytecountp = k->bytecount; /* read count */
 
1260
    if(conn->writebytecountp)
 
1261
      *conn->writebytecountp = k->writebytecount; /* write count */
 
1262
  }
 
1263
  else {
 
1264
    /* no read no write, this is a timeout? */
 
1265
    if (k->write_after_100_header) {
 
1266
      /* This should allow some time for the header to arrive, but only a
 
1267
         very short time as otherwise it'll be too much wasted times too
 
1268
         often. */
 
1269
 
 
1270
      /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
 
1271
 
 
1272
      Therefore, when a client sends this header field to an origin server
 
1273
      (possibly via a proxy) from which it has never seen a 100 (Continue)
 
1274
      status, the client SHOULD NOT wait for an indefinite period before
 
1275
      sending the request body.
 
1276
 
 
1277
      */
 
1278
 
 
1279
      long ms = Curl_tvdiff(k->now, k->start100);
 
1280
      if(ms > CURL_TIMEOUT_EXPECT_100) {
 
1281
        /* we've waited long enough, continue anyway */
 
1282
        k->write_after_100_header = FALSE;
 
1283
        FD_SET (conn->writesockfd, &k->writefd); /* write socket */
 
1284
        k->keepon |= KEEP_WRITE;
 
1285
        k->wkeepfd = k->writefd;
 
1286
      }
 
1287
    }
 
1288
  }
 
1289
 
 
1290
  if(Curl_pgrsUpdate(conn))
 
1291
    result = CURLE_ABORTED_BY_CALLBACK;
 
1292
  else
 
1293
    result = Curl_speedcheck(data, k->now);
 
1294
  if (result)
 
1295
    return result;
 
1296
 
 
1297
  if (data->set.timeout &&
 
1298
      ((Curl_tvdiff(k->now, k->start)/1000) >= data->set.timeout)) {
 
1299
    failf(data, "Operation timed out with %" FORMAT_OFF_T
 
1300
          " out of %" FORMAT_OFF_T " bytes received",
 
1301
          k->bytecount, conn->size);
 
1302
    return CURLE_OPERATION_TIMEOUTED;
 
1303
  }
 
1304
 
 
1305
  if(!k->keepon) {
 
1306
    /*
 
1307
     * The transfer has been performed. Just make some general checks before
 
1308
     * returning.
 
1309
     */
 
1310
 
 
1311
    if(!(conn->bits.no_body) && (conn->size != -1) &&
 
1312
       (k->bytecount != conn->size) &&
 
1313
       !conn->newurl) {
 
1314
      failf(data, "transfer closed with %" FORMAT_OFF_T
 
1315
            " bytes remaining to read",
 
1316
            conn->size - k->bytecount);
 
1317
      return CURLE_PARTIAL_FILE;
 
1318
    }
 
1319
    else if(conn->bits.chunk && conn->proto.http->chunk.datasize) {
 
1320
      failf(data, "transfer closed with at least %d bytes remaining",
 
1321
            conn->proto.http->chunk.datasize);
 
1322
      return CURLE_PARTIAL_FILE;
 
1323
    }
 
1324
    if(Curl_pgrsUpdate(conn))
 
1325
      return CURLE_ABORTED_BY_CALLBACK;
 
1326
  }
 
1327
 
 
1328
  /* Now update the "done" boolean we return */
 
1329
  *done = !k->keepon;
 
1330
 
 
1331
  return CURLE_OK;
 
1332
}
 
1333
 
 
1334
 
 
1335
/*
 
1336
 * Curl_readwrite_init() inits the readwrite session.
 
1337
 */
 
1338
 
 
1339
CURLcode Curl_readwrite_init(struct connectdata *conn)
 
1340
{
 
1341
  struct SessionHandle *data;
 
1342
  struct Curl_transfer_keeper *k = &conn->keep;
 
1343
 
 
1344
  /* NB: the content encoding software depends on this initialization of
 
1345
     Curl_transfer_keeper. */
 
1346
  memset(k, 0, sizeof(struct Curl_transfer_keeper));
 
1347
 
 
1348
  k->start = Curl_tvnow(); /* start time */
 
1349
  k->now = k->start;   /* current time is now */
 
1350
  k->header = TRUE; /* assume header */
 
1351
  k->httpversion = -1; /* unknown at this point */
 
1352
 
 
1353
  data = conn->data; /* there's the root struct */
 
1354
  k->buf = data->state.buffer;
 
1355
  k->uploadbuf = data->state.uploadbuffer;
 
1356
  k->maxfd = (conn->sockfd>conn->writesockfd?
 
1357
              conn->sockfd:conn->writesockfd)+1;
 
1358
  k->hbufp = data->state.headerbuff;
 
1359
  k->ignorebody=FALSE;
 
1360
 
 
1361
  Curl_pgrsTime(data, TIMER_PRETRANSFER);
 
1362
  Curl_speedinit(data);
 
1363
 
 
1364
  Curl_pgrsSetUploadCounter(data, 0);
 
1365
  Curl_pgrsSetDownloadCounter(data, 0);
 
1366
 
 
1367
  if (!conn->bits.getheader) {
 
1368
    k->header = FALSE;
 
1369
    if(conn->size > 0)
 
1370
      Curl_pgrsSetDownloadSize(data, conn->size);
 
1371
  }
 
1372
  /* we want header and/or body, if neither then don't do this! */
 
1373
  if(conn->bits.getheader || !conn->bits.no_body) {
 
1374
 
 
1375
    FD_ZERO (&k->readfd);               /* clear it */
 
1376
    if(conn->sockfd != CURL_SOCKET_BAD) {
 
1377
      FD_SET (conn->sockfd, &k->readfd); /* read socket */
 
1378
      k->keepon |= KEEP_READ;
 
1379
    }
 
1380
 
 
1381
    FD_ZERO (&k->writefd);              /* clear it */
 
1382
    if(conn->writesockfd != CURL_SOCKET_BAD) {
 
1383
      /* HTTP 1.1 magic:
 
1384
 
 
1385
         Even if we require a 100-return code before uploading data, we might
 
1386
         need to write data before that since the REQUEST may not have been
 
1387
         finished sent off just yet.
 
1388
 
 
1389
         Thus, we must check if the request has been sent before we set the
 
1390
         state info where we wait for the 100-return code
 
1391
      */
 
1392
      if (data->set.expect100header &&
 
1393
          (conn->proto.http->sending == HTTPSEND_BODY)) {
 
1394
        /* wait with write until we either got 100-continue or a timeout */
 
1395
        k->write_after_100_header = TRUE;
 
1396
        k->start100 = k->start;
 
1397
      }
 
1398
      else {
 
1399
        if(data->set.expect100header)
 
1400
          /* when we've sent off the rest of the headers, we must await a
 
1401
             100-continue */
 
1402
          k->wait100_after_headers = TRUE;
 
1403
        FD_SET (conn->writesockfd, &k->writefd); /* write socket */
 
1404
        k->keepon |= KEEP_WRITE;
 
1405
      }
 
1406
    }
 
1407
 
 
1408
    /* get these in backup variables to be able to restore them on each lap in
 
1409
       the select() loop */
 
1410
    k->rkeepfd = k->readfd;
 
1411
    k->wkeepfd = k->writefd;
 
1412
 
 
1413
  }
 
1414
 
 
1415
  return CURLE_OK;
 
1416
}
 
1417
 
 
1418
/*
 
1419
 * Curl_single_fdset() gets called by the multi interface code when the app
 
1420
 * has requested to get the fd_sets for the current connection. This function
 
1421
 * will then be called once for every connection that the multi interface
 
1422
 * keeps track of. This function will only be called for connections that are
 
1423
 * in the proper state to have this information available.
 
1424
 */
 
1425
void Curl_single_fdset(struct connectdata *conn,
 
1426
                       fd_set *read_fd_set,
 
1427
                       fd_set *write_fd_set,
 
1428
                       fd_set *exc_fd_set,
 
1429
                       int *max_fd)
 
1430
{
 
1431
  *max_fd = -1; /* init */
 
1432
  if(conn->keep.keepon & KEEP_READ) {
 
1433
    FD_SET(conn->sockfd, read_fd_set);
 
1434
    *max_fd = conn->sockfd;
 
1435
    conn->keep.readfdp = read_fd_set; /* store the address of the set */
 
1436
  }
 
1437
  if(conn->keep.keepon & KEEP_WRITE) {
 
1438
    FD_SET(conn->writesockfd, write_fd_set);
 
1439
 
 
1440
    /* since sockets are curl_socket_t nowadays, we typecast it to int here
 
1441
       to compare it nicely */
 
1442
    if((int)conn->writesockfd > *max_fd)
 
1443
      *max_fd = conn->writesockfd;
 
1444
    conn->keep.writefdp = write_fd_set; /* store the address of the set */
 
1445
  }
 
1446
  /* we don't use exceptions, only touch that one to prevent compiler
 
1447
     warnings! */
 
1448
  *exc_fd_set = *exc_fd_set;
 
1449
}
 
1450
 
 
1451
 
 
1452
/*
 
1453
 * Transfer()
 
1454
 *
 
1455
 * This function is what performs the actual transfer. It is capable of
 
1456
 * doing both ways simultaneously.
 
1457
 * The transfer must already have been setup by a call to Curl_Transfer().
 
1458
 *
 
1459
 * Note that headers are created in a preallocated buffer of a default size.
 
1460
 * That buffer can be enlarged on demand, but it is never shrunken again.
 
1461
 *
 
1462
 * Parts of this function was once written by the friendly Mark Butler
 
1463
 * <butlerm@xmission.com>.
 
1464
 */
 
1465
 
 
1466
static CURLcode
 
1467
Transfer(struct connectdata *conn)
 
1468
{
 
1469
  CURLcode result;
 
1470
  struct Curl_transfer_keeper *k = &conn->keep;
 
1471
  bool done=FALSE;
 
1472
 
 
1473
  if(!(conn->protocol & PROT_FILE))
 
1474
    /* Only do this if we are not transferring FILE:, since the file: treatment
 
1475
       is different*/
 
1476
    Curl_readwrite_init(conn);
 
1477
 
 
1478
  if((conn->sockfd == CURL_SOCKET_BAD) &&
 
1479
     (conn->writesockfd == CURL_SOCKET_BAD))
 
1480
    /* nothing to read, nothing to write, we're already OK! */
 
1481
    return CURLE_OK;
 
1482
 
 
1483
  /* we want header and/or body, if neither then don't do this! */
 
1484
  if(!conn->bits.getheader && conn->bits.no_body)
 
1485
    return CURLE_OK;
 
1486
 
 
1487
  k->writefdp = &k->writefd; /* store the address of the set */
 
1488
  k->readfdp = &k->readfd;   /* store the address of the set */
 
1489
 
 
1490
  while (!done) {
 
1491
    struct timeval interval;
 
1492
    k->readfd = k->rkeepfd;  /* set these every lap in the loop */
 
1493
    k->writefd = k->wkeepfd;
 
1494
    interval.tv_sec = 1;
 
1495
    interval.tv_usec = 0;
 
1496
 
 
1497
    switch (select (k->maxfd, k->readfdp, k->writefdp, NULL, &interval)) {
 
1498
    case -1: /* select() error, stop reading */
 
1499
#ifdef EINTR
 
1500
      /* The EINTR is not serious, and it seems you might get this more
 
1501
         ofen when using the lib in a multi-threaded environment! */
 
1502
      if(errno == EINTR)
 
1503
        ;
 
1504
      else
 
1505
#endif
 
1506
        done = TRUE; /* no more read or write */
 
1507
      continue;
 
1508
    case 0:  /* timeout */
 
1509
    default: /* readable descriptors */
 
1510
      result = Curl_readwrite(conn, &done);
 
1511
      break;
 
1512
    }
 
1513
    if(result)
 
1514
      return result;
 
1515
 
 
1516
    /* "done" signals to us if the transfer(s) are ready */
 
1517
  }
 
1518
 
 
1519
  return CURLE_OK;
 
1520
}
 
1521
 
 
1522
/*
 
1523
 * Curl_pretransfer() is called immediately before a transfer starts.
 
1524
 */
 
1525
CURLcode Curl_pretransfer(struct SessionHandle *data)
 
1526
{
 
1527
  if(!data->change.url)
 
1528
    /* we can't do anything wihout URL */
 
1529
    return CURLE_URL_MALFORMAT;
 
1530
 
 
1531
#ifdef USE_SSLEAY
 
1532
  {
 
1533
    /* Init the SSL session ID cache here. We do it here since we want to do
 
1534
       it after the *_setopt() calls (that could change the size of the cache)
 
1535
       but before any transfer takes place. */
 
1536
    CURLcode res = Curl_SSL_InitSessions(data, data->set.ssl.numsessions);
 
1537
    if(res)
 
1538
      return res;
 
1539
  }
 
1540
#endif
 
1541
 
 
1542
  data->set.followlocation=0; /* reset the location-follow counter */
 
1543
  data->state.this_is_a_follow = FALSE; /* reset this */
 
1544
  data->state.errorbuf = FALSE; /* no error has occurred */
 
1545
 
 
1546
  data->state.authproblem = FALSE;
 
1547
  data->state.authhost.want = data->set.httpauth;
 
1548
  data->state.authproxy.want = data->set.proxyauth;
 
1549
 
 
1550
#ifndef CURL_DISABLE_HTTP
 
1551
  /* If there was a list of cookie files to read and we haven't done it before,
 
1552
     do it now! */
 
1553
  if(data->change.cookielist) {
 
1554
    struct curl_slist *list = data->change.cookielist;
 
1555
    Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
 
1556
    while(list) {
 
1557
      data->cookies = Curl_cookie_init(data,
 
1558
                                       list->data,
 
1559
                                       data->cookies,
 
1560
                                       data->set.cookiesession);
 
1561
      list = list->next;
 
1562
    }
 
1563
    Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
 
1564
    curl_slist_free_all(data->change.cookielist); /* clean up list */
 
1565
    data->change.cookielist = NULL; /* don't do this again! */
 
1566
  }
 
1567
#endif   /* CURL_DISABLE_HTTP */
 
1568
 
 
1569
 
 
1570
 /* Allow data->set.use_port to set which port to use. This needs to be
 
1571
  * disabled for example when we follow Location: headers to URLs using
 
1572
  * different ports! */
 
1573
  data->state.allow_port = TRUE;
 
1574
 
 
1575
#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
 
1576
  /*************************************************************
 
1577
   * Tell signal handler to ignore SIGPIPE
 
1578
   *************************************************************/
 
1579
  if(!data->set.no_signal)
 
1580
    data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
 
1581
#endif
 
1582
 
 
1583
  Curl_initinfo(data); /* reset session-specific information "variables" */
 
1584
  Curl_pgrsStartNow(data);
 
1585
 
 
1586
  return CURLE_OK;
 
1587
}
 
1588
 
 
1589
/*
 
1590
 * Curl_posttransfer() is called immediately after a transfer ends
 
1591
 */
 
1592
CURLcode Curl_posttransfer(struct SessionHandle *data)
 
1593
{
 
1594
#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
 
1595
  /* restore the signal handler for SIGPIPE before we get back */
 
1596
  if(!data->set.no_signal)
 
1597
    signal(SIGPIPE, data->state.prev_signal);
 
1598
#else
 
1599
  (void)data; /* unused parameter */
 
1600
#endif
 
1601
 
 
1602
  return CURLE_OK;
 
1603
}
 
1604
 
 
1605
/*
 
1606
 * strlen_url() returns the length of the given URL if the spaces within the
 
1607
 * URL were properly URL encoded.
 
1608
 */
 
1609
static int strlen_url(char *url)
 
1610
{
 
1611
  char *ptr;
 
1612
  int newlen=0;
 
1613
  bool left=TRUE; /* left side of the ? */
 
1614
 
 
1615
  for(ptr=url; *ptr; ptr++) {
 
1616
    switch(*ptr) {
 
1617
    case '?':
 
1618
      left=FALSE;
 
1619
    default:
 
1620
      newlen++;
 
1621
      break;
 
1622
    case ' ':
 
1623
      if(left)
 
1624
        newlen+=3;
 
1625
      else
 
1626
        newlen++;
 
1627
      break;
 
1628
    }
 
1629
  }
 
1630
  return newlen;
 
1631
}
 
1632
 
 
1633
/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
 
1634
 * the source URL accordingly.
 
1635
 */
 
1636
static void strcpy_url(char *output, char *url)
 
1637
{
 
1638
  /* we must add this with whitespace-replacing */
 
1639
  bool left=TRUE;
 
1640
  char *iptr;
 
1641
  char *optr = output;
 
1642
  for(iptr = url;    /* read from here */
 
1643
      *iptr;         /* until zero byte */
 
1644
      iptr++) {
 
1645
    switch(*iptr) {
 
1646
    case '?':
 
1647
      left=FALSE;
 
1648
    default:
 
1649
      *optr++=*iptr;
 
1650
      break;
 
1651
    case ' ':
 
1652
      if(left) {
 
1653
        *optr++='%'; /* add a '%' */
 
1654
        *optr++='2'; /* add a '2' */
 
1655
        *optr++='0'; /* add a '0' */
 
1656
      }
 
1657
      else
 
1658
        *optr++='+'; /* add a '+' here */
 
1659
      break;
 
1660
    }
 
1661
  }
 
1662
  *optr=0; /* zero terminate output buffer */
 
1663
 
 
1664
}
 
1665
 
 
1666
/*
 
1667
 * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
 
1668
 * as given by the remote server and set up the new URL to request.
 
1669
 */
 
1670
CURLcode Curl_follow(struct SessionHandle *data,
 
1671
                     char *newurl) /* this 'newurl' is the Location: string,
 
1672
                                      and it must be malloc()ed before passed
 
1673
                                      here */
 
1674
{
 
1675
  /* Location: redirect */
 
1676
  char prot[16]; /* URL protocol string storage */
 
1677
  char letter;   /* used for a silly sscanf */
 
1678
  size_t newlen;
 
1679
  char *newest;
 
1680
 
 
1681
  if (data->set.maxredirs &&
 
1682
      (data->set.followlocation >= data->set.maxredirs)) {
 
1683
    failf(data,"Maximum (%d) redirects followed", data->set.maxredirs);
 
1684
    return CURLE_TOO_MANY_REDIRECTS;
 
1685
  }
 
1686
 
 
1687
  /* mark the next request as a followed location: */
 
1688
  data->state.this_is_a_follow = TRUE;
 
1689
 
 
1690
  data->set.followlocation++; /* count location-followers */
 
1691
 
 
1692
  if(data->set.http_auto_referer) {
 
1693
    /* We are asked to automatically set the previous URL as the
 
1694
       referer when we get the next URL. We pick the ->url field,
 
1695
       which may or may not be 100% correct */
 
1696
 
 
1697
    if(data->change.referer_alloc)
 
1698
      /* If we already have an allocated referer, free this first */
 
1699
      free(data->change.referer);
 
1700
 
 
1701
    data->change.referer = strdup(data->change.url);
 
1702
    data->change.referer_alloc = TRUE; /* yes, free this later */
 
1703
  }
 
1704
 
 
1705
  if(2 != sscanf(newurl, "%15[^?&/:]://%c", prot, &letter)) {
 
1706
    /***
 
1707
     *DANG* this is an RFC 2068 violation. The URL is supposed
 
1708
     to be absolute and this doesn't seem to be that!
 
1709
     ***
 
1710
     Instead, we have to TRY to append this new path to the old URL
 
1711
     to the right of the host part. Oh crap, this is doomed to cause
 
1712
     problems in the future...
 
1713
    */
 
1714
    char *protsep;
 
1715
    char *pathsep;
 
1716
 
 
1717
    char *useurl = newurl;
 
1718
    size_t urllen;
 
1719
 
 
1720
    /* we must make our own copy of the URL to play with, as it may
 
1721
       point to read-only data */
 
1722
    char *url_clone=strdup(data->change.url);
 
1723
 
 
1724
    if(!url_clone)
 
1725
      return CURLE_OUT_OF_MEMORY; /* skip out of this NOW */
 
1726
 
 
1727
    /* protsep points to the start of the host name */
 
1728
    protsep=strstr(url_clone, "//");
 
1729
    if(!protsep)
 
1730
      protsep=url_clone;
 
1731
    else
 
1732
      protsep+=2; /* pass the slashes */
 
1733
 
 
1734
    if('/' != newurl[0]) {
 
1735
      int level=0;
 
1736
 
 
1737
      /* First we need to find out if there's a ?-letter in the URL,
 
1738
         and cut it and the right-side of that off */
 
1739
      pathsep = strrchr(protsep, '?');
 
1740
      if(pathsep)
 
1741
        *pathsep=0;
 
1742
 
 
1743
      /* we have a relative path to append to the last slash if
 
1744
         there's one available */
 
1745
      pathsep = strrchr(protsep, '/');
 
1746
      if(pathsep)
 
1747
        *pathsep=0;
 
1748
 
 
1749
      /* Check if there's any slash after the host name, and if so,
 
1750
         remember that position instead */
 
1751
      pathsep = strchr(protsep, '/');
 
1752
      if(pathsep)
 
1753
        protsep = pathsep+1;
 
1754
      else
 
1755
        protsep = NULL;
 
1756
 
 
1757
      /* now deal with one "./" or any amount of "../" in the newurl
 
1758
         and act accordingly */
 
1759
 
 
1760
      if((useurl[0] == '.') && (useurl[1] == '/'))
 
1761
        useurl+=2; /* just skip the "./" */
 
1762
 
 
1763
      while((useurl[0] == '.') &&
 
1764
            (useurl[1] == '.') &&
 
1765
            (useurl[2] == '/')) {
 
1766
        level++;
 
1767
        useurl+=3; /* pass the "../" */
 
1768
      }
 
1769
 
 
1770
      if(protsep) {
 
1771
        while(level--) {
 
1772
          /* cut off one more level from the right of the original URL */
 
1773
          pathsep = strrchr(protsep, '/');
 
1774
          if(pathsep)
 
1775
            *pathsep=0;
 
1776
          else {
 
1777
            *protsep=0;
 
1778
            break;
 
1779
          }
 
1780
        }
 
1781
      }
 
1782
    }
 
1783
    else {
 
1784
      /* We got a new absolute path for this server, cut off from the
 
1785
         first slash */
 
1786
      pathsep = strchr(protsep, '/');
 
1787
      if(pathsep)
 
1788
        *pathsep=0;
 
1789
      else {
 
1790
        /* There was no slash. Now, since we might be operating on a badly
 
1791
           formatted URL, such as "http://www.url.com?id=2380" which doesn't
 
1792
           use a slash separator as it is supposed to, we need to check for a
 
1793
           ?-letter as well! */
 
1794
        pathsep = strchr(protsep, '?');
 
1795
        if(pathsep)
 
1796
          *pathsep=0;
 
1797
      }
 
1798
    }
 
1799
 
 
1800
    /* If the new part contains a space, this is a mighty stupid redirect
 
1801
       but we still make an effort to do "right". To the left of a '?'
 
1802
       letter we replace each space with %20 while it is replaced with '+'
 
1803
       on the right side of the '?' letter.
 
1804
    */
 
1805
    newlen = strlen_url(useurl);
 
1806
 
 
1807
    urllen = strlen(url_clone);
 
1808
 
 
1809
    newest=(char *)malloc( urllen + 1 + /* possible slash */
 
1810
                           newlen + 1 /* zero byte */);
 
1811
 
 
1812
    if(!newest) {
 
1813
      free(url_clone); /* don't leak this */
 
1814
      return CURLE_OUT_OF_MEMORY; /* go out from this */
 
1815
    }
 
1816
 
 
1817
    /* copy over the root url part */
 
1818
    memcpy(newest, url_clone, urllen);
 
1819
 
 
1820
    /* check if we need to append a slash */
 
1821
    if(('/' == useurl[0]) || (protsep && !*protsep))
 
1822
      ;
 
1823
    else
 
1824
      newest[urllen++]='/';
 
1825
 
 
1826
    /* then append the new piece on the right side */
 
1827
    strcpy_url(&newest[urllen], useurl);
 
1828
 
 
1829
    free(newurl); /* newurl is the allocated pointer */
 
1830
    free(url_clone);
 
1831
    newurl = newest;
 
1832
  }
 
1833
  else {
 
1834
    /* This is an absolute URL, don't allow the custom port number */
 
1835
    data->state.allow_port = FALSE;
 
1836
 
 
1837
    if(strchr(newurl, ' ')) {
 
1838
      /* This new URL contains at least one space, this is a mighty stupid
 
1839
         redirect but we still make an effort to do "right". */
 
1840
      newlen = strlen_url(newurl);
 
1841
 
 
1842
      newest = malloc(newlen+1); /* get memory for this */
 
1843
      if(newest) {
 
1844
        strcpy_url(newest, newurl); /* create a space-free URL */
 
1845
 
 
1846
        free(newurl); /* that was no good */
 
1847
        newurl = newest; /* use this instead now */
 
1848
      }
 
1849
    }
 
1850
 
 
1851
  }
 
1852
 
 
1853
  if(data->change.url_alloc)
 
1854
    free(data->change.url);
 
1855
  else
 
1856
    data->change.url_alloc = TRUE; /* the URL is allocated */
 
1857
 
 
1858
  data->change.url = newurl;
 
1859
  newurl = NULL; /* don't free! */
 
1860
  (void)newurl;
 
1861
 
 
1862
  infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
 
1863
 
 
1864
  /*
 
1865
   * We get here when the HTTP code is 300-399 (and 401). We need to perform
 
1866
   * differently based on exactly what return code there was.
 
1867
   *
 
1868
   * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
 
1869
   * a HTTP (proxy-) authentication scheme other than Basic.
 
1870
   */
 
1871
  switch(data->info.httpcode) {
 
1872
    /* 401 - Act on a www-authentication, we keep on moving and do the
 
1873
       Authorization: XXXX header in the HTTP request code snippet */
 
1874
    /* 407 - Act on a proxy-authentication, we keep on moving and do the
 
1875
       Proxy-Authorization: XXXX header in the HTTP request code snippet */
 
1876
    /* 300 - Multiple Choices */
 
1877
    /* 306 - Not used */
 
1878
    /* 307 - Temporary Redirect */
 
1879
  default:  /* for all above (and the unknown ones) */
 
1880
    /* Some codes are explicitly mentioned since I've checked RFC2616 and they
 
1881
     * seem to be OK to POST to.
 
1882
     */
 
1883
    break;
 
1884
  case 301: /* Moved Permanently */
 
1885
    /* (quote from RFC2616, section 10.3.2):
 
1886
     *
 
1887
     * Note: When automatically redirecting a POST request after receiving a
 
1888
     * 301 status code, some existing HTTP/1.0 user agents will erroneously
 
1889
     * change it into a GET request.
 
1890
     *
 
1891
     * ----
 
1892
     *
 
1893
     * Warning: Because most of importants user agents do this obvious RFC2616
 
1894
     * violation, many webservers expect this misbehavior. So these servers
 
1895
     * often answers to a POST request with an error page.  To be sure that
 
1896
     * libcurl gets the page that most user agents would get, libcurl has to
 
1897
     * force GET:
 
1898
     */
 
1899
    if( data->set.httpreq == HTTPREQ_POST
 
1900
        || data->set.httpreq == HTTPREQ_POST_FORM) {
 
1901
      infof(data,
 
1902
            "Violate RFC 2616/10.3.2 and switch from POST to GET\n");
 
1903
      data->set.httpreq = HTTPREQ_GET;
 
1904
    }
 
1905
    break;
 
1906
  case 302: /* Found */
 
1907
    /* (From 10.3.3)
 
1908
 
 
1909
    Note: RFC 1945 and RFC 2068 specify that the client is not allowed
 
1910
    to change the method on the redirected request.  However, most
 
1911
    existing user agent implementations treat 302 as if it were a 303
 
1912
    response, performing a GET on the Location field-value regardless
 
1913
    of the original request method. The status codes 303 and 307 have
 
1914
    been added for servers that wish to make unambiguously clear which
 
1915
    kind of reaction is expected of the client.
 
1916
 
 
1917
    (From 10.3.4)
 
1918
 
 
1919
    Note: Many pre-HTTP/1.1 user agents do not understand the 303
 
1920
    status. When interoperability with such clients is a concern, the
 
1921
    302 status code may be used instead, since most user agents react
 
1922
    to a 302 response as described here for 303.
 
1923
    */
 
1924
  case 303: /* See Other */
 
1925
    /* Disable both types of POSTs, since doing a second POST when
 
1926
     * following isn't what anyone would want! */
 
1927
    if(data->set.httpreq != HTTPREQ_GET) {
 
1928
      data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
 
1929
      infof(data, "Disables POST, goes with %s\n",
 
1930
            data->set.opt_no_body?"HEAD":"GET");
 
1931
    }
 
1932
    break;
 
1933
  case 304: /* Not Modified */
 
1934
    /* 304 means we did a conditional request and it was "Not modified".
 
1935
     * We shouldn't get any Location: header in this response!
 
1936
     */
 
1937
    break;
 
1938
  case 305: /* Use Proxy */
 
1939
    /* (quote from RFC2616, section 10.3.6):
 
1940
     * "The requested resource MUST be accessed through the proxy given
 
1941
     * by the Location field. The Location field gives the URI of the
 
1942
     * proxy.  The recipient is expected to repeat this single request
 
1943
     * via the proxy. 305 responses MUST only be generated by origin
 
1944
     * servers."
 
1945
     */
 
1946
    break;
 
1947
  }
 
1948
  Curl_pgrsTime(data, TIMER_REDIRECT);
 
1949
  Curl_pgrsResetTimes(data);
 
1950
 
 
1951
  return CURLE_OK;
 
1952
}
 
1953
 
 
1954
static CURLcode
 
1955
Curl_connect_host(struct SessionHandle *data,
 
1956
                  struct connectdata **conn)
 
1957
{
 
1958
  CURLcode res;
 
1959
  int urlchanged;
 
1960
 
 
1961
  do {
 
1962
    bool async;
 
1963
    Curl_pgrsTime(data, TIMER_STARTSINGLE);
 
1964
    data->change.url_changed = FALSE;
 
1965
    res = Curl_connect(data, conn, &async);
 
1966
 
 
1967
    if((CURLE_OK == res) && async) {
 
1968
      /* Now, if async is TRUE here, we need to wait for the name
 
1969
         to resolve */
 
1970
      res = Curl_wait_for_resolv(*conn, NULL);
 
1971
      if(CURLE_OK == res)
 
1972
        /* Resolved, continue with the connection */
 
1973
        res = Curl_async_resolved(*conn);
 
1974
    }
 
1975
    if(res)
 
1976
      break;
 
1977
 
 
1978
    /* If a callback (or something) has altered the URL we should use within
 
1979
       the Curl_connect(), we detect it here and act as if we are redirected
 
1980
       to the new URL */
 
1981
    urlchanged = data->change.url_changed;
 
1982
    if ((CURLE_OK == res) && urlchanged) {
 
1983
      res = Curl_done(conn, res);
 
1984
      if(CURLE_OK == res) {
 
1985
        char *gotourl = strdup(data->change.url);
 
1986
        res = Curl_follow(data, gotourl);
 
1987
        if(res)
 
1988
          free(gotourl);
 
1989
      }
 
1990
    }
 
1991
  } while (urlchanged && res == CURLE_OK);
 
1992
 
 
1993
  return res;
 
1994
}
 
1995
 
 
1996
 
 
1997
 
 
1998
/*
 
1999
 * Curl_perform() is the internal high-level function that gets called by the
 
2000
 * external curl_easy_perform() function. It inits, performs and cleans up a
 
2001
 * single file transfer.
 
2002
 */
 
2003
CURLcode Curl_perform(struct SessionHandle *data)
 
2004
{
 
2005
  CURLcode res;
 
2006
  CURLcode res2;
 
2007
  struct connectdata *conn=NULL;
 
2008
  char *newurl = NULL; /* possibly a new URL to follow to! */
 
2009
 
 
2010
  data->state.used_interface = Curl_if_easy;
 
2011
 
 
2012
  res = Curl_pretransfer(data);
 
2013
  if(res)
 
2014
    return res;
 
2015
 
 
2016
  /*
 
2017
   * It is important that there is NO 'return' from this function at any other
 
2018
   * place than falling down to the end of the function! This is because we
 
2019
   * have cleanup stuff that must be done before we get back, and that is only
 
2020
   * performed after this do-while loop.
 
2021
   */
 
2022
 
 
2023
  do {
 
2024
    res = Curl_connect_host(data, &conn);   /* primary connection */
 
2025
 
 
2026
    if(res == CURLE_OK) {
 
2027
      if (data->set.source_host) /* 3rd party transfer */
 
2028
        res = Curl_pretransfersec(conn);
 
2029
      else
 
2030
        conn->sec_conn = NULL;
 
2031
    }
 
2032
 
 
2033
    if(res == CURLE_OK) {
 
2034
 
 
2035
      res = Curl_do(&conn);
 
2036
 
 
2037
      /* for non 3rd party transfer only */
 
2038
      if(res == CURLE_OK && !data->set.source_host) {
 
2039
        res = Transfer(conn); /* now fetch that URL please */
 
2040
        if(res == CURLE_OK) {
 
2041
 
 
2042
          if((conn->keep.bytecount+conn->headerbytecount == 0) &&
 
2043
             conn->bits.reuse) {
 
2044
            /* We got no data and we attempted to re-use a connection. This
 
2045
               might happen if the connection was left alive when we were done
 
2046
               using it before, but that was closed when we wanted to read
 
2047
               from it again. Bad luck. Retry the same request on a fresh
 
2048
               connect! */
 
2049
            infof(data, "Connection died, retrying a fresh connect\n");
 
2050
            newurl = strdup(conn->data->change.url);
 
2051
 
 
2052
            conn->bits.close = TRUE; /* close this connection */
 
2053
            conn->bits.retry = TRUE; /* mark this as a connection we're about
 
2054
                                        to retry. Marking it this way should
 
2055
                                        prevent i.e HTTP transfers to return
 
2056
                                        error just because nothing has been
 
2057
                                        transfered! */
 
2058
          }
 
2059
          else
 
2060
            /*
 
2061
             * We must duplicate the new URL here as the connection data
 
2062
             * may be free()ed in the Curl_done() function.
 
2063
             */
 
2064
            newurl = conn->newurl?strdup(conn->newurl):NULL;
 
2065
        }
 
2066
        else {
 
2067
          /* The transfer phase returned error, we mark the connection to get
 
2068
           * closed to prevent being re-used. This is becasue we can't
 
2069
           * possibly know if the connection is in a good shape or not now. */
 
2070
          conn->bits.close = TRUE;
 
2071
 
 
2072
          if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
 
2073
            /* if we failed anywhere, we must clean up the secondary socket if
 
2074
               it was used */
 
2075
            sclose(conn->sock[SECONDARYSOCKET]);
 
2076
            conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
 
2077
          }
 
2078
        }
 
2079
 
 
2080
        /* Always run Curl_done(), even if some of the previous calls
 
2081
           failed, but return the previous (original) error code */
 
2082
        res2 = Curl_done(&conn, res);
 
2083
 
 
2084
        if(CURLE_OK == res)
 
2085
          res = res2;
 
2086
      }
 
2087
      else
 
2088
        /* Curl_do() failed, clean up left-overs in the done-call */
 
2089
        res2 = Curl_done(&conn, res);
 
2090
 
 
2091
      (void)res2;
 
2092
 
 
2093
      /*
 
2094
       * Important: 'conn' cannot be used here, since it may have been closed
 
2095
       * in 'Curl_done' or other functions.
 
2096
       */
 
2097
 
 
2098
      if((res == CURLE_OK) && newurl) {
 
2099
        res = Curl_follow(data, newurl);
 
2100
        if(CURLE_OK == res) {
 
2101
          newurl = NULL;
 
2102
          continue;
 
2103
        }
 
2104
      }
 
2105
    }
 
2106
    break; /* it only reaches here when this shouldn't loop */
 
2107
 
 
2108
  } while(1); /* loop if Location: */
 
2109
 
 
2110
  if(newurl)
 
2111
    free(newurl);
 
2112
 
 
2113
  /* run post-transfer uncondionally, but don't clobber the return code if
 
2114
     we already have an error code recorder */
 
2115
  res2 = Curl_posttransfer(data);
 
2116
  if(!res && res2)
 
2117
    res = res2;
 
2118
 
 
2119
  return res;
 
2120
}
 
2121
 
 
2122
/*
 
2123
 * Curl_Transfer() is called to setup some basic properties for the upcoming
 
2124
 * transfer.
 
2125
 */
 
2126
CURLcode
 
2127
Curl_Transfer(struct connectdata *c_conn, /* connection data */
 
2128
              int sockindex,       /* socket index to read from or -1 */
 
2129
              curl_off_t size,     /* -1 if unknown at this point */
 
2130
              bool getheader,      /* TRUE if header parsing is wanted */
 
2131
              curl_off_t *bytecountp, /* return number of bytes read or NULL */
 
2132
              int writesockindex,  /* socket index to write to, it may very
 
2133
                                      well be the same we read from. -1
 
2134
                                      disables */
 
2135
              curl_off_t *writecountp /* return number of bytes written or
 
2136
                                       NULL */
 
2137
              )
 
2138
{
 
2139
  struct connectdata *conn = (struct connectdata *)c_conn;
 
2140
  if(!conn)
 
2141
    return CURLE_BAD_FUNCTION_ARGUMENT;
 
2142
 
 
2143
  curlassert((sockindex <= 1) && (sockindex >= -1));
 
2144
 
 
2145
  /* now copy all input parameters */
 
2146
  conn->sockfd = sockindex==-1?
 
2147
    CURL_SOCKET_BAD:conn->sock[sockindex];
 
2148
  conn->size = size;
 
2149
  conn->bits.getheader = getheader;
 
2150
  conn->bytecountp = bytecountp;
 
2151
  conn->writesockfd = writesockindex==-1?
 
2152
    CURL_SOCKET_BAD:conn->sock[writesockindex];
 
2153
  conn->writebytecountp = writecountp;
 
2154
 
 
2155
  return CURLE_OK;
 
2156
 
 
2157
}
 
2158
 
 
2159
/*
 
2160
 * Curl_pretransfersec() prepares the secondary connection (used for 3rd party
 
2161
 * FTP transfers).
 
2162
 */
 
2163
CURLcode Curl_pretransfersec(struct connectdata *conn)
 
2164
{
 
2165
  CURLcode status;
 
2166
  struct SessionHandle *data = conn->data;
 
2167
  struct connectdata *sec_conn = NULL;   /* secondary connection */
 
2168
 
 
2169
  /* update data with source host options */
 
2170
  char *url = aprintf( "%s://%s/", conn->protostr, data->set.source_host);
 
2171
 
 
2172
  if(!url)
 
2173
    return CURLE_OUT_OF_MEMORY;
 
2174
 
 
2175
  if(data->change.url_alloc)
 
2176
    free(data->change.url);
 
2177
 
 
2178
  data->change.url_alloc = TRUE;
 
2179
  data->change.url = url;
 
2180
  data->set.ftpport = data->set.source_port;
 
2181
  data->set.userpwd = data->set.source_userpwd;
 
2182
 
 
2183
  /* secondary connection */
 
2184
  status = Curl_connect_host(data, &sec_conn);
 
2185
  if(CURLE_OK == status) {
 
2186
    sec_conn->data = data;
 
2187
    conn->sec_conn = sec_conn;
 
2188
  }
 
2189
 
 
2190
  return status;
 
2191
}