~ubuntu-branches/ubuntu/warty/curl/warty

« back to all changes in this revision

Viewing changes to lib/url.c

  • Committer: Bazaar Package Importer
  • Author(s): Domenico Andreoli
  • Date: 2002-03-12 19:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20020312190621-iqx7k9cipo5d0ifr
Tags: upstream-7.9.5
ImportĀ upstreamĀ versionĀ 7.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 *                                  _   _ ____  _     
 
3
 *  Project                     ___| | | |  _ \| |    
 
4
 *                             / __| | | | |_) | |    
 
5
 *                            | (__| |_| |  _ <| |___ 
 
6
 *                             \___|\___/|_| \_\_____|
 
7
 *
 
8
 * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
 
9
 *
 
10
 * In order to be useful for every potential user, curl and libcurl are
 
11
 * dual-licensed under the MPL and the MIT/X-derivate licenses.
 
12
 *
 
13
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 
14
 * copies of the Software, and permit persons to whom the Software is
 
15
 * furnished to do so, under the terms of the MPL or the MIT/X-derivate
 
16
 * licenses. You may pick one of these licenses.
 
17
 *
 
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 
19
 * KIND, either express or implied.
 
20
 *
 
21
 * $Id: url.c,v 1.191 2002/02/28 23:31:23 bagder Exp $
 
22
 *****************************************************************************/
 
23
 
 
24
/* -- WIN32 approved -- */
 
25
 
 
26
#include "setup.h"
 
27
 
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
#include <stdarg.h>
 
31
#include <stdlib.h>
 
32
#include <ctype.h>
 
33
#include <sys/types.h>
 
34
#include <sys/stat.h>
 
35
 
 
36
#include <errno.h>
 
37
 
 
38
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
 
39
#include <winsock.h>
 
40
#include <time.h>
 
41
#include <io.h>
 
42
#else
 
43
#ifdef HAVE_SYS_SOCKET_H
 
44
#include <sys/socket.h>
 
45
#endif
 
46
#include <netinet/in.h>
 
47
#include <sys/time.h>
 
48
#include <sys/resource.h>
 
49
#ifdef HAVE_UNISTD_H
 
50
#include <unistd.h>
 
51
#endif
 
52
#include <netdb.h>
 
53
#ifdef HAVE_ARPA_INET_H
 
54
#include <arpa/inet.h>
 
55
#endif
 
56
#ifdef HAVE_NET_IF_H
 
57
#include <net/if.h>
 
58
#endif
 
59
#include <sys/ioctl.h>
 
60
#include <signal.h>
 
61
 
 
62
#ifdef HAVE_SYS_PARAM_H
 
63
#include <sys/param.h>
 
64
#endif
 
65
 
 
66
#ifdef HAVE_SYS_SELECT_H
 
67
#include <sys/select.h>
 
68
#endif
 
69
 
 
70
#ifdef  VMS
 
71
#include <in.h>
 
72
#include <inet.h>
 
73
#endif
 
74
 
 
75
#ifndef HAVE_SELECT
 
76
#error "We can't compile without select() support!"
 
77
#endif
 
78
#ifndef HAVE_SOCKET
 
79
#error "We can't compile without socket() support!"
 
80
#endif
 
81
 
 
82
#endif
 
83
 
 
84
#include "urldata.h"
 
85
#include "netrc.h"
 
86
 
 
87
#include "formdata.h"
 
88
#include "base64.h"
 
89
#include "ssluse.h"
 
90
#include "hostip.h"
 
91
#include "if2ip.h"
 
92
#include "transfer.h"
 
93
#include "sendf.h"
 
94
#include "getpass.h"
 
95
#include "progress.h"
 
96
#include "cookie.h"
 
97
#include "strequal.h"
 
98
#include "escape.h"
 
99
#include "strtok.h"
 
100
 
 
101
/* And now for the protocols */
 
102
#include "ftp.h"
 
103
#include "dict.h"
 
104
#include "telnet.h"
 
105
#include "http.h"
 
106
#include "file.h"
 
107
#include "ldap.h"
 
108
#include "url.h"
 
109
#include "connect.h"
 
110
 
 
111
#include <curl/types.h>
 
112
 
 
113
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
 
114
#include "inet_ntoa_r.h"
 
115
#endif
 
116
 
 
117
#define _MPRINTF_REPLACE /* use our functions only */
 
118
#include <curl/mprintf.h>
 
119
 
 
120
#ifdef KRB4
 
121
#include "security.h"
 
122
#endif
 
123
/* The last #include file should be: */
 
124
#ifdef MALLOCDEBUG
 
125
#include "memdebug.h"
 
126
#endif
 
127
 
 
128
/* Local static prototypes */
 
129
static int ConnectionKillOne(struct SessionHandle *data);
 
130
static bool ConnectionExists(struct SessionHandle *data,
 
131
                             struct connectdata *needle,
 
132
                             struct connectdata **usethis);
 
133
static unsigned int ConnectionStore(struct SessionHandle *data,
 
134
                                    struct connectdata *conn);
 
135
 
 
136
 
 
137
#if !defined(WIN32)||defined(__CYGWIN32__)
 
138
#ifndef RETSIGTYPE
 
139
#define RETSIGTYPE void
 
140
#endif
 
141
static
 
142
RETSIGTYPE alarmfunc(int signal)
 
143
{
 
144
  /* this is for "-ansi -Wall -pedantic" to stop complaining!   (rabe) */
 
145
  (void)signal;
 
146
  return;
 
147
}
 
148
#endif
 
149
 
 
150
 
 
151
/*
 
152
 * This is the internal function curl_easy_cleanup() calls. This should
 
153
 * cleanup and free all resources associated with this sessionhandle.
 
154
 *
 
155
 * NOTE: if we ever add something that attempts to write to a socket or
 
156
 * similar here, we must ignore SIGPIPE first. It is currently only done
 
157
 * when curl_easy_perform() is invoked.
 
158
 */
 
159
 
 
160
CURLcode Curl_close(struct SessionHandle *data)
 
161
{
 
162
  /* Loop through all open connections and kill them one by one */
 
163
  while(-1 != ConnectionKillOne(data));
 
164
 
 
165
#ifdef USE_SSLEAY
 
166
  /* Close down all open SSL info and sessions */
 
167
  Curl_SSL_Close_All(data);
 
168
#endif
 
169
 
 
170
  if(data->state.auth_host)
 
171
    free(data->state.auth_host);
 
172
 
 
173
  if(data->change.proxy_alloc)
 
174
    free(data->change.proxy);
 
175
 
 
176
  if(data->change.referer_alloc)
 
177
    free(data->change.referer);
 
178
 
 
179
  if(data->change.url_alloc)
 
180
    free(data->change.url);
 
181
 
 
182
  if(data->state.headerbuff)
 
183
    free(data->state.headerbuff);
 
184
 
 
185
  if(data->set.cookiejar)
 
186
    /* we have a "destination" for all the cookies to get dumped to */
 
187
    Curl_cookie_output(data->cookies, data->set.cookiejar);
 
188
    
 
189
  Curl_cookie_cleanup(data->cookies);
 
190
 
 
191
  /* free the connection cache */
 
192
  free(data->state.connects);
 
193
 
 
194
  if(data->info.contenttype)
 
195
    free(data->info.contenttype);
 
196
 
 
197
  free(data);
 
198
  return CURLE_OK;
 
199
}
 
200
 
 
201
static
 
202
int my_getpass(void *clientp, const char *prompt, char* buffer, int buflen )
 
203
{
 
204
  char *retbuf;
 
205
  clientp=NULL; /* prevent compiler warning */
 
206
 
 
207
  retbuf = getpass_r(prompt, buffer, buflen);
 
208
  if(NULL == retbuf)
 
209
    return 1;
 
210
  else
 
211
    return 0; /* success */
 
212
}
 
213
 
 
214
 
 
215
CURLcode Curl_open(struct SessionHandle **curl)
 
216
{
 
217
  /* We don't yet support specifying the URL at this point */
 
218
  struct SessionHandle *data;
 
219
  /* Very simple start-up: alloc the struct, init it with zeroes and return */
 
220
  data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle));
 
221
  if(!data)
 
222
    /* this is a very serious error */
 
223
    return CURLE_OUT_OF_MEMORY;
 
224
  
 
225
  memset(data, 0, sizeof(struct SessionHandle));
 
226
 
 
227
  /* We do some initial setup here, all those fields that can't be just 0 */
 
228
 
 
229
  data->state.headerbuff=(char*)malloc(HEADERSIZE);
 
230
  if(!data->state.headerbuff) {
 
231
    free(data); /* free the memory again */
 
232
    return CURLE_OUT_OF_MEMORY;
 
233
  }
 
234
 
 
235
  data->state.headersize=HEADERSIZE;
 
236
 
 
237
  data->set.out = stdout; /* default output to stdout */
 
238
  data->set.in  = stdin;  /* default input from stdin */
 
239
  data->set.err  = stderr;  /* default stderr to stderr */
 
240
  
 
241
  /* use fwrite as default function to store output */
 
242
  data->set.fwrite = (curl_write_callback)fwrite;
 
243
 
 
244
  /* use fread as default function to read input */
 
245
  data->set.fread = (curl_read_callback)fread;
 
246
  
 
247
  /* set the default passwd function */
 
248
  data->set.fpasswd = my_getpass;
 
249
 
 
250
  data->set.infilesize = -1; /* we don't know any size */
 
251
 
 
252
  data->state.current_speed = -1; /* init to negative == impossible */
 
253
 
 
254
  data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
 
255
  data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
 
256
 
 
257
  data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
 
258
  
 
259
  /* make libcurl quiet by default: */
 
260
  data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
 
261
  data->progress.flags |= PGRS_HIDE;
 
262
 
 
263
  /* Set the default size of the SSL session ID cache */
 
264
  data->set.ssl.numsessions = 5;
 
265
  
 
266
  /* create an array with connection data struct pointers */
 
267
  data->state.numconnects = 5; /* hard-coded right now */
 
268
  data->state.connects = (struct connectdata **)
 
269
    malloc(sizeof(struct connectdata *) * data->state.numconnects);
 
270
  
 
271
  if(!data->state.connects) {
 
272
    free(data);
 
273
    return CURLE_OUT_OF_MEMORY;
 
274
  }
 
275
  
 
276
  memset(data->state.connects, 0,
 
277
         sizeof(struct connectdata *)*data->state.numconnects);
 
278
 
 
279
  *curl = data;
 
280
 
 
281
  return CURLE_OK;
 
282
}
 
283
 
 
284
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
 
285
{
 
286
  va_list param;
 
287
  char *cookiefile;
 
288
 
 
289
  va_start(param, option);
 
290
 
 
291
  switch(option) {
 
292
  case CURLOPT_DNS_CACHE_TIMEOUT:
 
293
    data->set.dns_cache_timeout = va_arg(param, int);
 
294
    break;
 
295
  case CURLOPT_DNS_USE_GLOBAL_CACHE: 
 
296
    {
 
297
      int use_cache = va_arg(param, int);
 
298
      if (use_cache) {
 
299
        Curl_global_host_cache_init();
 
300
      }
 
301
 
 
302
      data->set.global_dns_cache = use_cache;
 
303
    }
 
304
    break;
 
305
  case CURLOPT_SSL_CIPHER_LIST:
 
306
    /* set a list of cipher we want to use in the SSL connection */
 
307
    data->set.ssl.cipher_list = va_arg(param, char *);
 
308
    break;
 
309
 
 
310
  case CURLOPT_RANDOM_FILE:
 
311
    /*
 
312
     * This is the path name to a file that contains random data to seed
 
313
     * the random SSL stuff with. The file is only used for reading.
 
314
     */
 
315
    data->set.ssl.random_file = va_arg(param, char *);
 
316
    break;
 
317
  case CURLOPT_EGDSOCKET:
 
318
    /*
 
319
     * The Entropy Gathering Daemon socket pathname
 
320
     */
 
321
    data->set.ssl.egdsocket = va_arg(param, char *);
 
322
    break;
 
323
  case CURLOPT_MAXCONNECTS:
 
324
    /*
 
325
     * Set the absolute number of maximum simultaneous alive connection that
 
326
     * libcurl is allowed to have.
 
327
     */
 
328
    {
 
329
      long newconnects= va_arg(param, long);
 
330
      struct connectdata **newptr;
 
331
 
 
332
      if(newconnects < data->state.numconnects) {
 
333
        /* Since this number is *decreased* from the existing number, we must
 
334
           close the possibly open connections that live on the indexes that
 
335
           are being removed! */
 
336
        int i;
 
337
        for(i=newconnects; i< data->state.numconnects; i++)
 
338
          Curl_disconnect(data->state.connects[i]);
 
339
      }
 
340
      if(newconnects) {
 
341
        newptr= (struct connectdata **)
 
342
          realloc(data->state.connects,
 
343
                  sizeof(struct connectdata *) * newconnects);
 
344
        if(!newptr)
 
345
          /* we closed a few connections in vain, but so what? */
 
346
          return CURLE_OUT_OF_MEMORY;
 
347
        data->state.connects = newptr;
 
348
        data->state.numconnects = newconnects;
 
349
      }
 
350
      else {
 
351
        /* zero makes NO cache at all */
 
352
        if(data->state.connects)
 
353
          free(data->state.connects);
 
354
        data->state.connects=NULL;
 
355
        data->state.numconnects=0;
 
356
      }
 
357
    }
 
358
    break;
 
359
  case CURLOPT_FORBID_REUSE:
 
360
    /*
 
361
     * When this transfer is done, it must not be left to be reused by a
 
362
     * subsequent transfer but shall be closed immediately.
 
363
     */
 
364
    data->set.reuse_forbid = va_arg(param, long)?TRUE:FALSE;
 
365
    break;
 
366
  case CURLOPT_FRESH_CONNECT:
 
367
    /*
 
368
     * This transfer shall not use a previously cached connection but
 
369
     * should be made with a fresh new connect!
 
370
     */
 
371
    data->set.reuse_fresh = va_arg(param, long)?TRUE:FALSE;
 
372
    break;
 
373
  case CURLOPT_VERBOSE:
 
374
    /*
 
375
     * Verbose means infof() calls that give a lot of information about
 
376
     * the connection and transfer procedures as well as internal choices.
 
377
     */
 
378
    data->set.verbose = va_arg(param, long)?TRUE:FALSE;
 
379
    break;
 
380
  case CURLOPT_HEADER:
 
381
    /*
 
382
     * Set to include the header in the general data output stream.
 
383
     */
 
384
    data->set.http_include_header = va_arg(param, long)?TRUE:FALSE;
 
385
    break;
 
386
  case CURLOPT_NOPROGRESS:
 
387
    /*
 
388
     * Shut off the internal supported progress meter
 
389
     */
 
390
    data->set.hide_progress = va_arg(param, long)?TRUE:FALSE;
 
391
    if(data->set.hide_progress)
 
392
      data->progress.flags |= PGRS_HIDE;
 
393
    else
 
394
      data->progress.flags &= ~PGRS_HIDE;
 
395
    break;
 
396
  case CURLOPT_NOBODY:
 
397
    /*
 
398
     * Do not include the body part in the output data stream.
 
399
     */
 
400
    data->set.no_body = va_arg(param, long)?TRUE:FALSE;
 
401
    break;
 
402
  case CURLOPT_FAILONERROR:
 
403
    /*
 
404
     * Don't output the >=300 error code HTML-page, but instead only
 
405
     * return error.
 
406
     */
 
407
    data->set.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
 
408
    break;
 
409
  case CURLOPT_UPLOAD:
 
410
    /*
 
411
     * We want to sent data to the remote host
 
412
     */
 
413
    data->set.upload = va_arg(param, long)?TRUE:FALSE;
 
414
    if(data->set.upload)
 
415
      /* If this is HTTP, PUT is what's needed to "upload" */
 
416
      data->set.httpreq = HTTPREQ_PUT;
 
417
    break;
 
418
  case CURLOPT_FILETIME:
 
419
    /*
 
420
     * Try to get the file time of the remote document. The time will
 
421
     * later (possibly) become available using curl_easy_getinfo().
 
422
     */
 
423
    data->set.get_filetime = va_arg(param, long)?TRUE:FALSE;
 
424
    break;
 
425
  case CURLOPT_FTPLISTONLY:
 
426
    /*
 
427
     * An FTP option that changes the command to one that asks for a list
 
428
     * only, no file info details.
 
429
     */
 
430
    data->set.ftp_list_only = va_arg(param, long)?TRUE:FALSE;
 
431
    break;
 
432
  case CURLOPT_FTPAPPEND:
 
433
    /*
 
434
     * We want to upload and append to an existing (FTP) file.
 
435
     */
 
436
    data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
 
437
    break;
 
438
  case CURLOPT_NETRC:
 
439
    /*
 
440
     * Parse the $HOME/.netrc file
 
441
     */
 
442
    data->set.use_netrc = va_arg(param, long)?TRUE:FALSE;
 
443
    break;
 
444
  case CURLOPT_FOLLOWLOCATION:
 
445
    /*
 
446
     * Follow Location: header hints on a HTTP-server.
 
447
     */
 
448
    data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
 
449
    break;
 
450
  case CURLOPT_HTTP_VERSION:
 
451
    /*
 
452
     * This sets a requested HTTP version to be used. The value is one of
 
453
     * the listed enums in curl/curl.h.
 
454
     */
 
455
    data->set.httpversion = va_arg(param, long);
 
456
    break;
 
457
  case CURLOPT_TRANSFERTEXT:
 
458
    /*
 
459
     * This option was previously named 'FTPASCII'. Renamed to work with
 
460
     * more protocols than merely FTP.
 
461
     *
 
462
     * Transfer using ASCII (instead of BINARY).
 
463
     */
 
464
    data->set.ftp_ascii = va_arg(param, long)?TRUE:FALSE;
 
465
    break;
 
466
  case CURLOPT_PUT:
 
467
    /*
 
468
     * Use the HTTP PUT request to transfer data if this is TRUE.  If this is
 
469
     * FALSE, don't set the httpreq. We can't know what to revert it to!
 
470
     */
 
471
    if(va_arg(param, long))
 
472
      data->set.httpreq = HTTPREQ_PUT;
 
473
    break;
 
474
  case CURLOPT_TIMECONDITION:
 
475
    /*
 
476
     * Set HTTP time condition. This must be one of the defines in the
 
477
     * curl/curl.h header file.
 
478
     */
 
479
    data->set.timecondition = va_arg(param, long);
 
480
    break;
 
481
  case CURLOPT_TIMEVALUE:
 
482
    /*
 
483
     * This is the value to compare with the remote document with the
 
484
     * method set with CURLOPT_TIMECONDITION
 
485
     */
 
486
    data->set.timevalue = va_arg(param, long);
 
487
    break;
 
488
  case CURLOPT_SSLVERSION:
 
489
    /*
 
490
     * Set explicit SSL version to try to connect with, as some SSL
 
491
     * implementations are lame.
 
492
     */
 
493
    data->set.ssl.version = va_arg(param, long);
 
494
    break;
 
495
 
 
496
  case CURLOPT_COOKIEFILE:
 
497
    /*
 
498
     * Set cookie file to read and parse. Can be used multiple times.
 
499
     */
 
500
    cookiefile = (char *)va_arg(param, void *);
 
501
    if(cookiefile)
 
502
      data->cookies = Curl_cookie_init(cookiefile, data->cookies);
 
503
    break;
 
504
 
 
505
  case CURLOPT_COOKIEJAR:
 
506
    /*
 
507
     * Set cookie file name to dump all cookies to when we're done.
 
508
     */
 
509
    data->set.cookiejar = (char *)va_arg(param, void *);
 
510
 
 
511
    /*
 
512
     * Activate the cookie parser. This may or may not already
 
513
     * have been made.
 
514
     */
 
515
    data->cookies = Curl_cookie_init(NULL, data->cookies);
 
516
    break;
 
517
  case CURLOPT_WRITEHEADER:
 
518
    /*
 
519
     * Custom pointer to pass the header write callback function
 
520
     */
 
521
    data->set.writeheader = (void *)va_arg(param, void *);
 
522
    break;
 
523
  case CURLOPT_COOKIE:
 
524
    /*
 
525
     * Cookie string to send to the remote server in the request.
 
526
     */
 
527
    data->set.cookie = va_arg(param, char *);
 
528
    break;
 
529
  case CURLOPT_ERRORBUFFER:
 
530
    /*
 
531
     * Error buffer provided by the caller to get the human readable
 
532
     * error string in.
 
533
     */
 
534
    data->set.errorbuffer = va_arg(param, char *);
 
535
    break;
 
536
  case CURLOPT_FILE:
 
537
    /*
 
538
     * FILE pointer to write to or include in the data write callback
 
539
     */
 
540
    data->set.out = va_arg(param, FILE *);
 
541
    break;
 
542
  case CURLOPT_FTPPORT:
 
543
    /*
 
544
     * Use FTP PORT, this also specifies which IP address to use
 
545
     */
 
546
    data->set.ftpport = va_arg(param, char *);
 
547
    data->set.ftp_use_port = data->set.ftpport?1:0;
 
548
    break;
 
549
 
 
550
  case CURLOPT_FTP_USE_EPSV:
 
551
    data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
 
552
    break;
 
553
 
 
554
  case CURLOPT_HTTPHEADER:
 
555
    /*
 
556
     * Set a list with HTTP headers to use (or replace internals with)
 
557
     */
 
558
    data->set.headers = va_arg(param, struct curl_slist *);
 
559
    break;
 
560
  case CURLOPT_CUSTOMREQUEST:
 
561
    /*
 
562
     * Set a custom string to use as request
 
563
     */
 
564
    data->set.customrequest = va_arg(param, char *);
 
565
 
 
566
    /* we don't set
 
567
       data->set.httpreq = HTTPREQ_CUSTOM;
 
568
       here, we continue as if we were using the already set type
 
569
       and this just changes the actual request keyword */
 
570
    break;
 
571
  case CURLOPT_HTTPPOST:
 
572
    /*
 
573
     * Set to make us do HTTP POST
 
574
     */
 
575
    data->set.httppost = va_arg(param, struct HttpPost *);
 
576
    if(data->set.httppost)
 
577
      data->set.httpreq = HTTPREQ_POST_FORM;
 
578
    break;
 
579
 
 
580
  case CURLOPT_HTTPGET:
 
581
    /*
 
582
     * Set to force us do HTTP GET
 
583
     */
 
584
    if(va_arg(param, long)) {
 
585
      data->set.httpreq = HTTPREQ_GET;
 
586
      data->set.upload = FALSE; /* switch off upload */
 
587
    }
 
588
    break;
 
589
 
 
590
  case CURLOPT_INFILE:
 
591
    /*
 
592
     * FILE pointer to read the file to be uploaded from. Or possibly
 
593
     * used as argument to the read callback.
 
594
     */
 
595
    data->set.in = va_arg(param, FILE *);
 
596
    break;
 
597
  case CURLOPT_INFILESIZE:
 
598
    /*
 
599
     * If known, this should inform curl about the file size of the
 
600
     * to-be-uploaded file.
 
601
     */
 
602
    data->set.infilesize = va_arg(param, long);
 
603
    break;
 
604
  case CURLOPT_LOW_SPEED_LIMIT:
 
605
    /*
 
606
     * The low speed limit that if transfers are below this for
 
607
     * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
 
608
     */
 
609
    data->set.low_speed_limit=va_arg(param, long);
 
610
    break;
 
611
  case CURLOPT_LOW_SPEED_TIME:
 
612
    /*
 
613
     * The low speed time that if transfers are below the set
 
614
     * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
 
615
     */
 
616
    data->set.low_speed_time=va_arg(param, long);
 
617
    break;
 
618
  case CURLOPT_URL:
 
619
    /*
 
620
     * The URL to fetch.
 
621
     */
 
622
    if(data->change.url_alloc) {
 
623
      /* the already set URL is allocated, free it first! */
 
624
      free(data->change.url);
 
625
      data->change.url_alloc=FALSE;
 
626
    }
 
627
    data->set.set_url = va_arg(param, char *);
 
628
    data->change.url = data->set.set_url;
 
629
    break;
 
630
  case CURLOPT_PORT:
 
631
    /*
 
632
     * The port number to use when getting the URL
 
633
     */
 
634
    data->set.use_port = va_arg(param, long);
 
635
    break;
 
636
  case CURLOPT_POST:
 
637
    /* Does this option serve a purpose anymore? */
 
638
 
 
639
    if(va_arg(param, long))
 
640
      data->set.httpreq = HTTPREQ_POST;
 
641
    break;
 
642
  case CURLOPT_POSTFIELDS:
 
643
    /*
 
644
     * A string with POST data. Makes curl HTTP POST.
 
645
     */
 
646
    data->set.postfields = va_arg(param, char *);
 
647
    if(data->set.postfields)
 
648
      data->set.httpreq = HTTPREQ_POST;
 
649
    break;
 
650
  case CURLOPT_POSTFIELDSIZE:
 
651
    /*
 
652
     * The size of the POSTFIELD data, if curl should now do a strlen
 
653
     * to find out. Enables binary posts.
 
654
     */
 
655
    data->set.postfieldsize = va_arg(param, long);
 
656
    break;
 
657
  case CURLOPT_REFERER:
 
658
    /*
 
659
     * String to set in the HTTP Referer: field.
 
660
     */
 
661
    if(data->change.referer_alloc) {
 
662
      free(data->change.referer);
 
663
      data->change.referer_alloc = FALSE;
 
664
    }
 
665
    data->set.set_referer = va_arg(param, char *);
 
666
    data->change.referer = data->set.set_referer;
 
667
    break;
 
668
  case CURLOPT_AUTOREFERER:
 
669
    /*
 
670
     * Switch on automatic referer that gets set if curl follows locations.
 
671
     */
 
672
    data->set.http_auto_referer = va_arg(param, long)?1:0;
 
673
    break;
 
674
  case CURLOPT_PROXY:
 
675
    /*
 
676
     * Set proxy server:port to use as HTTP proxy
 
677
     */
 
678
    if(data->change.proxy_alloc) {
 
679
      /*
 
680
       * The already set string is allocated, free that first
 
681
       */
 
682
      data->change.proxy_alloc=FALSE;;
 
683
      free(data->change.proxy);
 
684
    }
 
685
    data->set.set_proxy = va_arg(param, char *);
 
686
    data->change.proxy = data->set.set_proxy;
 
687
    break;
 
688
  case CURLOPT_HTTPPROXYTUNNEL:
 
689
    /*
 
690
     * Tunnel operations through the proxy instead of normal proxy use
 
691
     */
 
692
    data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
 
693
    break;
 
694
  case CURLOPT_PROXYPORT:
 
695
    /*
 
696
     * Explicitly set HTTP proxy port number.
 
697
     */
 
698
    data->set.proxyport = va_arg(param, long);
 
699
    break;
 
700
  case CURLOPT_TIMEOUT:
 
701
    /*
 
702
     * The maximum time you allow curl to use for a single transfer
 
703
     * operation.
 
704
     */
 
705
    data->set.timeout = va_arg(param, long);
 
706
    break;
 
707
  case CURLOPT_CONNECTTIMEOUT:
 
708
    /*
 
709
     * The maximum time you allow curl to use to connect.
 
710
     */
 
711
    data->set.connecttimeout = va_arg(param, long);
 
712
    break;
 
713
  case CURLOPT_MAXREDIRS:
 
714
    /*
 
715
     * The maximum amount of hops you allow curl to follow Location:
 
716
     * headers. This should mostly be used to detect never-ending loops.
 
717
     */
 
718
    data->set.maxredirs = va_arg(param, long);
 
719
    break;
 
720
  case CURLOPT_USERAGENT:
 
721
    /*
 
722
     * String to use in the HTTP User-Agent field
 
723
     */
 
724
    data->set.useragent = va_arg(param, char *);
 
725
    break;
 
726
  case CURLOPT_USERPWD:
 
727
    /*
 
728
     * user:password to use in the operation
 
729
     */
 
730
    data->set.userpwd = va_arg(param, char *);
 
731
    break;
 
732
  case CURLOPT_POSTQUOTE:
 
733
    /*
 
734
     * List of RAW FTP commands to use after a transfer 
 
735
     */
 
736
    data->set.postquote = va_arg(param, struct curl_slist *);
 
737
    break;
 
738
  case CURLOPT_PREQUOTE:
 
739
    /*
 
740
     * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
 
741
     */
 
742
    data->set.prequote = va_arg(param, struct curl_slist *);
 
743
    break;
 
744
  case CURLOPT_QUOTE:
 
745
    /*
 
746
     * List of RAW FTP commands to use before a transfer 
 
747
     */
 
748
    data->set.quote = va_arg(param, struct curl_slist *);
 
749
    break;
 
750
  case CURLOPT_PROGRESSFUNCTION:
 
751
    /*
 
752
     * Progress callback function
 
753
     */
 
754
    data->set.fprogress = va_arg(param, curl_progress_callback);
 
755
    data->progress.callback = TRUE; /* no longer internal */
 
756
    break;
 
757
  case CURLOPT_PROGRESSDATA:
 
758
    /*
 
759
     * Custom client data to pass to the progress callback
 
760
     */
 
761
    data->set.progress_client = va_arg(param, void *);
 
762
    break;
 
763
  case CURLOPT_PASSWDFUNCTION:
 
764
    /*
 
765
     * Password prompt callback
 
766
     */
 
767
    data->set.fpasswd = va_arg(param, curl_passwd_callback);
 
768
    break;
 
769
  case CURLOPT_PASSWDDATA:
 
770
    /*
 
771
     * Custom client data to pass to the password callback
 
772
     */
 
773
    data->set.passwd_client = va_arg(param, void *);
 
774
    break;
 
775
  case CURLOPT_PROXYUSERPWD:
 
776
    /*
 
777
     * user:password needed to use the proxy
 
778
     */
 
779
    data->set.proxyuserpwd = va_arg(param, char *);
 
780
    break;
 
781
  case CURLOPT_RANGE:
 
782
    /*
 
783
     * What range of the file you want to transfer
 
784
     */
 
785
    data->set.set_range = va_arg(param, char *);
 
786
    break;
 
787
  case CURLOPT_RESUME_FROM:
 
788
    /*
 
789
     * Resume transfer at the give file position
 
790
     */
 
791
    data->set.set_resume_from = va_arg(param, long);
 
792
    break;
 
793
  case CURLOPT_STDERR:
 
794
    /*
 
795
     * Set to a FILE * that should receive all error writes. This
 
796
     * defaults to stderr for normal operations.
 
797
     */
 
798
    data->set.err = va_arg(param, FILE *);
 
799
    break;
 
800
  case CURLOPT_HEADERFUNCTION:
 
801
    /*
 
802
     * Set header write callback
 
803
     */
 
804
    data->set.fwrite_header = va_arg(param, curl_write_callback);
 
805
    break;
 
806
  case CURLOPT_WRITEFUNCTION:
 
807
    /*
 
808
     * Set data write callback
 
809
     */
 
810
    data->set.fwrite = va_arg(param, curl_write_callback);
 
811
    break;
 
812
  case CURLOPT_READFUNCTION:
 
813
    /*
 
814
     * Read data callback
 
815
     */
 
816
    data->set.fread = va_arg(param, curl_read_callback);
 
817
    break;
 
818
  case CURLOPT_SSLCERT:
 
819
    /*
 
820
     * String that holds file name of the SSL certificate to use
 
821
     */
 
822
    data->set.cert = va_arg(param, char *);
 
823
    break;
 
824
  case CURLOPT_SSLCERTTYPE:
 
825
    /*
 
826
     * String that holds file type of the SSL certificate to use
 
827
     */
 
828
    data->set.cert_type = va_arg(param, char *);
 
829
    break;
 
830
  case CURLOPT_SSLKEY:
 
831
    /*
 
832
     * String that holds file name of the SSL certificate to use
 
833
     */
 
834
    data->set.key = va_arg(param, char *);
 
835
    break;
 
836
  case CURLOPT_SSLKEYTYPE:
 
837
    /*
 
838
     * String that holds file type of the SSL certificate to use
 
839
     */
 
840
    data->set.key_type = va_arg(param, char *);
 
841
    break;
 
842
  case CURLOPT_SSLKEYPASSWD:
 
843
    /*
 
844
     * String that holds the SSL private key password.
 
845
     */
 
846
    data->set.key_passwd = va_arg(param, char *);
 
847
    break;
 
848
  case CURLOPT_SSLENGINE:
 
849
    /*
 
850
     * String that holds the SSL crypto engine.
 
851
     */
 
852
#ifdef HAVE_OPENSSL_ENGINE_H
 
853
    {
 
854
      const char *cpTemp = va_arg(param, char *);
 
855
      ENGINE     *e;
 
856
      if (cpTemp && cpTemp[0]) {
 
857
        e = ENGINE_by_id(cpTemp);
 
858
        if (e) {
 
859
          if (data->engine) {
 
860
            ENGINE_free(data->engine);
 
861
          }
 
862
          data->engine = e;
 
863
        }
 
864
        else {
 
865
          failf(data, "SSL Engine '%s' not found", cpTemp);
 
866
          return CURLE_SSL_ENGINE_NOTFOUND;
 
867
        }
 
868
      }
 
869
    }
 
870
#else
 
871
    return CURLE_SSL_ENGINE_NOTFOUND;
 
872
#endif
 
873
    break;
 
874
  case CURLOPT_SSLENGINE_DEFAULT:
 
875
    /*
 
876
     * flag to set engine as default.
 
877
     */
 
878
#ifdef HAVE_OPENSSL_ENGINE_H
 
879
    if (data->engine) {
 
880
      if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) {
 
881
#ifdef DEBUG
 
882
        fprintf(stderr,"set default crypto engine\n");
 
883
#endif
 
884
      }
 
885
      else {
 
886
#ifdef DEBUG
 
887
        failf(data, "set default crypto engine failed");
 
888
#endif
 
889
        return CURLE_SSL_ENGINE_SETFAILED;
 
890
      }
 
891
    }
 
892
#endif
 
893
    break;
 
894
  case CURLOPT_CRLF:
 
895
    /*
 
896
     * Kludgy option to enable CRLF convertions. Subject for removal.
 
897
     */
 
898
    data->set.crlf = va_arg(param, long)?TRUE:FALSE;
 
899
    break;
 
900
  case CURLOPT_INTERFACE:
 
901
    /*
 
902
     * Set what interface to bind to when performing an operation and thus
 
903
     * what from-IP your connection will use.
 
904
     */
 
905
    data->set.device = va_arg(param, char *);
 
906
    break;
 
907
  case CURLOPT_KRB4LEVEL:
 
908
    /*
 
909
     * A string that defines the krb4 security level.
 
910
     */
 
911
    data->set.krb4_level = va_arg(param, char *);
 
912
    data->set.krb4=data->set.krb4_level?TRUE:FALSE;
 
913
    break;
 
914
  case CURLOPT_SSL_VERIFYPEER:
 
915
    /*
 
916
     * Enable peer SSL verifying.
 
917
     */
 
918
    data->set.ssl.verifypeer = va_arg(param, long);
 
919
    break;
 
920
  case CURLOPT_SSL_VERIFYHOST:
 
921
    /*
 
922
     * Enable verification of the CN contained in the peer certificate
 
923
     */
 
924
    data->set.ssl.verifyhost = va_arg(param, long);
 
925
    break;
 
926
  case CURLOPT_CAINFO:
 
927
    /*
 
928
     * Set CA info for SSL connection. Specify file name of the CA certificate
 
929
     */
 
930
    data->set.ssl.CAfile = va_arg(param, char *);
 
931
    data->set.ssl.CApath = NULL; /*This does not work on windows.*/
 
932
    break;
 
933
  case CURLOPT_TELNETOPTIONS:
 
934
    /*
 
935
     * Set a linked list of telnet options
 
936
     */
 
937
    data->set.telnet_options = va_arg(param, struct curl_slist *);
 
938
    break;
 
939
  default:
 
940
    /* unknown tag and its companion, just ignore: */
 
941
    return CURLE_READ_ERROR; /* correct this */
 
942
  }
 
943
  return CURLE_OK;
 
944
}
 
945
 
 
946
CURLcode Curl_disconnect(struct connectdata *conn)
 
947
{
 
948
  if(!conn)
 
949
    return CURLE_OK; /* this is closed and fine already */
 
950
 
 
951
  /*
 
952
   * The range string is usually freed in curl_done(), but we might
 
953
   * get here *instead* if we fail prematurely. Thus we need to be able
 
954
   * to free this resource here as well.
 
955
   */
 
956
  if(conn->bits.rangestringalloc) {
 
957
    free(conn->range);
 
958
    conn->bits.rangestringalloc = FALSE;
 
959
  }
 
960
 
 
961
  if(-1 != conn->connectindex) {
 
962
    /* unlink ourselves! */
 
963
    infof(conn->data, "Closing connection #%d\n", conn->connectindex);
 
964
    conn->data->state.connects[conn->connectindex] = NULL;
 
965
  }
 
966
 
 
967
  if(conn->curl_disconnect)
 
968
    /* This is set if protocol-specific cleanups should be made */
 
969
    conn->curl_disconnect(conn);
 
970
 
 
971
  if(conn->proto.generic)
 
972
    free(conn->proto.generic);
 
973
 
 
974
  if(conn->newurl)
 
975
    free(conn->newurl);
 
976
 
 
977
  if(conn->path) /* the URL path part */
 
978
    free(conn->path);
 
979
 
 
980
#ifdef USE_SSLEAY
 
981
  Curl_SSL_Close(conn);
 
982
#endif /* USE_SSLEAY */
 
983
 
 
984
  /* close possibly still open sockets */
 
985
  if(-1 != conn->secondarysocket)
 
986
    sclose(conn->secondarysocket);
 
987
  if(-1 != conn->firstsocket)
 
988
    sclose(conn->firstsocket);
 
989
 
 
990
  if(conn->allocptr.proxyuserpwd)
 
991
    free(conn->allocptr.proxyuserpwd);
 
992
  if(conn->allocptr.uagent)
 
993
    free(conn->allocptr.uagent);
 
994
  if(conn->allocptr.userpwd)
 
995
    free(conn->allocptr.userpwd);
 
996
  if(conn->allocptr.rangeline)
 
997
    free(conn->allocptr.rangeline);
 
998
  if(conn->allocptr.ref)
 
999
    free(conn->allocptr.ref);
 
1000
  if(conn->allocptr.cookie)
 
1001
    free(conn->allocptr.cookie);
 
1002
  if(conn->allocptr.host)
 
1003
    free(conn->allocptr.host);
 
1004
 
 
1005
  if(conn->proxyhost)
 
1006
    free(conn->proxyhost);
 
1007
 
 
1008
  free(conn); /* free all the connection oriented data */
 
1009
 
 
1010
  return CURLE_OK;
 
1011
}
 
1012
 
 
1013
/*
 
1014
 * This function should return TRUE if the socket is to be assumed to
 
1015
 * be dead. Most commonly this happens when the server has closed the
 
1016
 * connection due to inactivity.
 
1017
 */
 
1018
static bool SocketIsDead(int sock) 
 
1019
 
1020
  int sval; 
 
1021
  bool ret_val = TRUE; 
 
1022
  fd_set check_set; 
 
1023
  struct timeval to; 
 
1024
 
 
1025
  FD_ZERO(&check_set); 
 
1026
  FD_SET(sock,&check_set); 
 
1027
 
 
1028
  to.tv_sec = 0; 
 
1029
  to.tv_usec = 1; 
 
1030
 
 
1031
  sval = select(sock + 1, &check_set, 0, 0, &to);
 
1032
  if(sval == 0)
 
1033
    /* timeout */
 
1034
    ret_val = FALSE;
 
1035
  
 
1036
  return ret_val;
 
1037
}
 
1038
 
 
1039
/*
 
1040
 * Given one filled in connection struct (named needle), this function should
 
1041
 * detect if there already is one that have all the significant details
 
1042
 * exactly the same and thus should be used instead.
 
1043
 */
 
1044
static bool
 
1045
ConnectionExists(struct SessionHandle *data,
 
1046
                 struct connectdata *needle,
 
1047
                 struct connectdata **usethis)
 
1048
{
 
1049
  long i;
 
1050
  struct connectdata *check;
 
1051
 
 
1052
  for(i=0; i< data->state.numconnects; i++) {
 
1053
    /*
 
1054
     * Note that if we use a HTTP proxy, we check connections to that
 
1055
     * proxy and not to the actual remote server.
 
1056
     */
 
1057
    check = data->state.connects[i];
 
1058
    if(!check)
 
1059
      /* NULL pointer means not filled-in entry */
 
1060
      continue;
 
1061
    if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) {
 
1062
      /* The requested connection does not use a HTTP proxy or it
 
1063
         uses SSL. */
 
1064
 
 
1065
      if(!(needle->protocol&PROT_SSL) && check->bits.httpproxy)
 
1066
        /* we don't do SSL but the cached connection has a proxy,
 
1067
           then don't match this */
 
1068
        continue;
 
1069
 
 
1070
      if(strequal(needle->protostr, check->protostr) &&
 
1071
         strequal(needle->name, check->name) &&
 
1072
         (needle->remote_port == check->remote_port) ) {
 
1073
        bool dead;
 
1074
        if(strequal(needle->protostr, "FTP")) {
 
1075
          /* This is FTP, verify that we're using the same name and
 
1076
             password as well */
 
1077
          if(!strequal(needle->data->state.user, check->proto.ftp->user) ||
 
1078
             !strequal(needle->data->state.passwd, check->proto.ftp->passwd)) {
 
1079
            /* one of them was different */
 
1080
            continue;
 
1081
          }
 
1082
        }
 
1083
        dead = SocketIsDead(check->firstsocket);
 
1084
        if(dead) {
 
1085
          /*
 
1086
           * Even though the connection seems to have passed away, we could
 
1087
           * still make an effort to get the name information, as we intend to
 
1088
           * connect to the same host again.
 
1089
           *
 
1090
           * This is now subject to discussion. What do you think?
 
1091
           */
 
1092
          infof(data, "Connection %d seems to be dead!\n", i);
 
1093
          Curl_disconnect(check); /* disconnect resources */
 
1094
          data->state.connects[i]=NULL; /* nothing here */
 
1095
 
 
1096
          /* There's no need to continue search, because we only store
 
1097
             one connection for each unique set of identifiers */
 
1098
          return FALSE;
 
1099
        }
 
1100
 
 
1101
        *usethis = check;
 
1102
        return TRUE; /* yes, we found one to use! */
 
1103
        
 
1104
      }
 
1105
    }
 
1106
    else { /* The requested needle connection is using a proxy,
 
1107
              is the checked one using the same? */
 
1108
      if(check->bits.httpproxy &&
 
1109
         strequal(needle->proxyhost, check->proxyhost) &&
 
1110
         needle->port == check->port) {
 
1111
        /* This is the same proxy connection, use it! */
 
1112
        *usethis = check;
 
1113
        return TRUE;
 
1114
      }
 
1115
    }
 
1116
  }
 
1117
  return FALSE; /* no matching connecting exists */
 
1118
}
 
1119
 
 
1120
/*
 
1121
 * This function frees/closes a connection in the connection cache. This
 
1122
 * should take the previously set policy into account when deciding which
 
1123
 * of the connections to kill.
 
1124
 */
 
1125
static int
 
1126
ConnectionKillOne(struct SessionHandle *data)
 
1127
{
 
1128
  long i;
 
1129
  struct connectdata *conn;
 
1130
  int highscore=-1;
 
1131
  int connindex=-1;
 
1132
  int score;
 
1133
  CURLcode result;
 
1134
  struct timeval now;
 
1135
 
 
1136
  now = Curl_tvnow();
 
1137
 
 
1138
  for(i=0; i< data->state.numconnects; i++) {
 
1139
    conn = data->state.connects[i];
 
1140
    
 
1141
    if(!conn)
 
1142
      continue;
 
1143
 
 
1144
    /*
 
1145
     * By using the set policy, we score each connection.
 
1146
     */
 
1147
    switch(data->set.closepolicy) {
 
1148
    case CURLCLOSEPOLICY_LEAST_RECENTLY_USED:
 
1149
    default:
 
1150
      /*
 
1151
       * Set higher score for the age passed since the connection
 
1152
       * was used.
 
1153
       */
 
1154
      score = Curl_tvdiff(now, conn->now);
 
1155
      break;
 
1156
    case CURLCLOSEPOLICY_OLDEST:
 
1157
      /*
 
1158
       * Set higher score for the age passed since the connection
 
1159
       * was created.
 
1160
       */
 
1161
      score = Curl_tvdiff(now, conn->created);
 
1162
      break;
 
1163
    }
 
1164
 
 
1165
    if(score > highscore) {
 
1166
      highscore = score;
 
1167
      connindex = i;
 
1168
    }
 
1169
  }
 
1170
  if(connindex >= 0) {
 
1171
 
 
1172
    /* the winner gets the honour of being disconnected */
 
1173
    result = Curl_disconnect(data->state.connects[connindex]);
 
1174
 
 
1175
    /* clean the array entry */
 
1176
    data->state.connects[connindex] = NULL;
 
1177
  }
 
1178
 
 
1179
  return connindex; /* return the available index or -1 */
 
1180
}
 
1181
 
 
1182
/*
 
1183
 * The given input connection struct pointer is to be stored. If the "cache"
 
1184
 * is already full, we must clean out the most suitable using the previously
 
1185
 * set policy.
 
1186
 *
 
1187
 * The given connection should be unique. That must've been checked prior to
 
1188
 * this call.
 
1189
 */
 
1190
static unsigned int
 
1191
ConnectionStore(struct SessionHandle *data,
 
1192
                struct connectdata *conn)
 
1193
{
 
1194
  long i;
 
1195
  for(i=0; i< data->state.numconnects; i++) {
 
1196
    if(!data->state.connects[i])
 
1197
      break;
 
1198
  }
 
1199
  if(i == data->state.numconnects) {
 
1200
    /* there was no room available, kill one */
 
1201
    i = ConnectionKillOne(data);
 
1202
    infof(data, "Connection (#%d) was killed to make room\n", i);
 
1203
  }
 
1204
 
 
1205
  if(-1 != i) {
 
1206
    /* only do this if a true index was returned, if -1 was returned there
 
1207
       is no room in the cache for an unknown reason and we cannot store
 
1208
       this there. */
 
1209
    data->state.connects[i] = conn; /* fill in this */
 
1210
    conn->connectindex = i; /* make the child know where the pointer to this
 
1211
                               particular data is stored */
 
1212
  }
 
1213
  return i;
 
1214
}
 
1215
 
 
1216
static CURLcode ConnectPlease(struct connectdata *conn)
 
1217
{
 
1218
  CURLcode result;
 
1219
  Curl_ipconnect *addr;
 
1220
 
 
1221
  /*************************************************************
 
1222
   * Connect to server/proxy
 
1223
   *************************************************************/
 
1224
  result= Curl_connecthost(conn,
 
1225
                           conn->hostaddr,
 
1226
                           conn->port,
 
1227
                           &conn->firstsocket,
 
1228
                           &addr);
 
1229
  if(CURLE_OK == result) {
 
1230
    /* All is cool, then we store the current information from the hostaddr
 
1231
       struct to the serv_addr, as it might be needed later. The address
 
1232
       returned from the function above is crucial here. */
 
1233
#ifdef ENABLE_IPV6
 
1234
    conn->serv_addr = addr;
 
1235
#else
 
1236
    memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
 
1237
    memcpy((char *)&(conn->serv_addr.sin_addr),
 
1238
           (struct in_addr *)addr, sizeof(struct in_addr));
 
1239
    conn->serv_addr.sin_family = conn->hostaddr->h_addrtype;
 
1240
    conn->serv_addr.sin_port = htons(conn->port);
 
1241
#endif
 
1242
  }
 
1243
 
 
1244
  return result;
 
1245
}
 
1246
 
 
1247
static CURLcode CreateConnection(struct SessionHandle *data,
 
1248
                                 struct connectdata **in_connect)
 
1249
{
 
1250
  char *tmp;
 
1251
  char *buf;
 
1252
  CURLcode result=CURLE_OK;
 
1253
  char resumerange[40]="";
 
1254
  struct connectdata *conn;
 
1255
  struct connectdata *conn_temp;
 
1256
  char endbracket;
 
1257
  int urllen;
 
1258
#ifdef HAVE_INET_NTOA_R
 
1259
  char ntoa_buf[64];
 
1260
#endif
 
1261
#ifdef HAVE_ALARM
 
1262
  unsigned int prev_alarm;
 
1263
#endif
 
1264
 
 
1265
#ifdef HAVE_SIGACTION
 
1266
  struct sigaction keep_sigact;   /* store the old struct here */
 
1267
  bool keep_copysig;              /* did copy it? */
 
1268
#else
 
1269
#ifdef HAVE_SIGNAL
 
1270
  void *keep_sigact;              /* store the old handler here */
 
1271
#endif
 
1272
#endif
 
1273
 
 
1274
  /*************************************************************
 
1275
   * Check input data
 
1276
   *************************************************************/
 
1277
 
 
1278
  if(!data->change.url)
 
1279
    return CURLE_URL_MALFORMAT;
 
1280
 
 
1281
  /* First, split up the current URL in parts so that we can use the
 
1282
     parts for checking against the already present connections. In order
 
1283
     to not have to modify everything at once, we allocate a temporary
 
1284
     connection data struct and fill in for comparison purposes. */
 
1285
 
 
1286
  conn = (struct connectdata *)malloc(sizeof(struct connectdata));
 
1287
  if(!conn) {
 
1288
    *in_connect = NULL; /* clear the pointer */
 
1289
    return CURLE_OUT_OF_MEMORY;
 
1290
  }
 
1291
  /* We must set the return variable as soon as possible, so that our
 
1292
     parent can cleanup any possible allocs we may have done before
 
1293
     any failure */
 
1294
  *in_connect = conn;
 
1295
 
 
1296
  /* we have to init the struct */
 
1297
  memset(conn, 0, sizeof(struct connectdata));
 
1298
 
 
1299
  /* and we setup a few fields in case we end up actually using this struct */
 
1300
  conn->data = data;           /* remember our daddy */
 
1301
  conn->firstsocket = -1;     /* no file descriptor */
 
1302
  conn->secondarysocket = -1; /* no file descriptor */
 
1303
  conn->connectindex = -1;    /* no index */
 
1304
  conn->bits.httpproxy = data->change.proxy?TRUE:FALSE; /* proxy-or-not */
 
1305
  conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */
 
1306
  conn->range = data->set.set_range;               /* clone the range setting */
 
1307
  conn->resume_from = data->set.set_resume_from;   /* inherite resume_from */
 
1308
 
 
1309
  /* Default protocol-independent behavior doesn't support persistant
 
1310
     connections, so we set this to force-close. Protocols that support
 
1311
     this need to set this to FALSE in their "curl_do" functions. */
 
1312
  conn->bits.close = TRUE;
 
1313
  
 
1314
  /* inherite initial knowledge from the data struct */
 
1315
  conn->bits.user_passwd = data->set.userpwd?1:0;
 
1316
  conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
 
1317
 
 
1318
  /* maxdownload must be -1 on init, as 0 is a valid value! */
 
1319
  conn->maxdownload = -1;  /* might have been used previously! */
 
1320
 
 
1321
  /* Store creation time to help future close decision making */
 
1322
  conn->created = Curl_tvnow();
 
1323
 
 
1324
 
 
1325
  /***********************************************************
 
1326
   * We need to allocate memory to store the path in. We get the size of the
 
1327
   * full URL to be sure, and we need to make it at least 256 bytes since
 
1328
   * other parts of the code will rely on this fact
 
1329
   ***********************************************************/
 
1330
#define LEAST_PATH_ALLOC 256
 
1331
  urllen=strlen(data->change.url);
 
1332
  if(urllen < LEAST_PATH_ALLOC)
 
1333
    urllen=LEAST_PATH_ALLOC;
 
1334
  
 
1335
  conn->path=(char *)malloc(urllen);
 
1336
  if(NULL == conn->path)
 
1337
    return CURLE_OUT_OF_MEMORY; /* really bad error */
 
1338
 
 
1339
  /*************************************************************
 
1340
   * Parse the URL.
 
1341
   *
 
1342
   * We need to parse the url even when using the proxy, because we will need
 
1343
   * the hostname and port in case we are trying to SSL connect through the
 
1344
   * proxy -- and we don't know if we will need to use SSL until we parse the
 
1345
   * url ...
 
1346
   ************************************************************/
 
1347
  if((2 == sscanf(data->change.url, "%64[^:]://%[^\n]",
 
1348
                  conn->protostr,
 
1349
                  conn->path)) && strequal(conn->protostr, "file")) {
 
1350
    /*
 
1351
     * we deal with file://<host>/<path> differently since it supports no
 
1352
     * hostname other than "localhost" and "127.0.0.1", which is unique among
 
1353
     * the URL protocols specified in RFC 1738
 
1354
     */
 
1355
    if(conn->path[0] != '/') {
 
1356
      /* the URL included a host name, we ignore host names in file:// URLs
 
1357
         as the standards don't define what to do with them */
 
1358
      char *ptr=strchr(conn->path, '/');
 
1359
      if(ptr) {
 
1360
        /* there was a slash present
 
1361
           
 
1362
           RFC1738 (section 3.1, page 5) says:
 
1363
 
 
1364
           The rest of the locator consists of data specific to the scheme,
 
1365
           and is known as the "url-path". It supplies the details of how the
 
1366
           specified resource can be accessed. Note that the "/" between the
 
1367
           host (or port) and the url-path is NOT part of the url-path.
 
1368
 
 
1369
           As most agents use file://localhost/foo to get '/foo' although the
 
1370
           slash preceeding foo is a separator and not a slash for the path,
 
1371
           a URL as file://localhost//foo must be valid as well, to refer to
 
1372
           the same file with an absolute path.
 
1373
        */
 
1374
 
 
1375
        if(ptr[1] && ('/' == ptr[1]))
 
1376
          /* if there was two slashes, we skip the first one as that is then
 
1377
             used truly as a separator */
 
1378
          ptr++; 
 
1379
        
 
1380
        strcpy(conn->path, ptr);
 
1381
      }
 
1382
    }
 
1383
 
 
1384
    strcpy(conn->protostr, "file"); /* store protocol string lowercase */
 
1385
  }
 
1386
  else {
 
1387
    /* Set default host and default path */
 
1388
    strcpy(conn->gname, "curl.haxx.se");
 
1389
    strcpy(conn->path, "/");
 
1390
 
 
1391
    if (2 > sscanf(data->change.url,
 
1392
                   "%64[^\n:]://%512[^\n/]%[^\n]",
 
1393
                   conn->protostr, conn->gname, conn->path)) {
 
1394
      
 
1395
      /*
 
1396
       * The URL was badly formatted, let's try the browser-style _without_
 
1397
       * protocol specified like 'http://'.
 
1398
       */
 
1399
      if((1 > sscanf(data->change.url, "%512[^\n/]%[^\n]",
 
1400
                     conn->gname, conn->path)) ) {
 
1401
        /*
 
1402
         * We couldn't even get this format.
 
1403
         */
 
1404
        failf(data, "<url> malformed");
 
1405
        return CURLE_URL_MALFORMAT;
 
1406
      }
 
1407
 
 
1408
      /*
 
1409
       * Since there was no protocol part specified, we guess what protocol it
 
1410
       * is based on the first letters of the server name.
 
1411
       */
 
1412
 
 
1413
      if(strnequal(conn->gname, "FTP", 3)) {
 
1414
        strcpy(conn->protostr, "ftp");
 
1415
      }
 
1416
      else if(strnequal(conn->gname, "GOPHER", 6))
 
1417
        strcpy(conn->protostr, "gopher");
 
1418
#ifdef USE_SSLEAY
 
1419
      else if(strnequal(conn->gname, "HTTPS", 5))
 
1420
        strcpy(conn->protostr, "https");
 
1421
      else if(strnequal(conn->gname, "FTPS", 4))
 
1422
        strcpy(conn->protostr, "ftps");
 
1423
#endif /* USE_SSLEAY */
 
1424
      else if(strnequal(conn->gname, "TELNET", 6))
 
1425
        strcpy(conn->protostr, "telnet");
 
1426
      else if (strnequal(conn->gname, "DICT", sizeof("DICT")-1))
 
1427
        strcpy(conn->protostr, "DICT");
 
1428
      else if (strnequal(conn->gname, "LDAP", sizeof("LDAP")-1))
 
1429
        strcpy(conn->protostr, "LDAP");
 
1430
      else {
 
1431
        strcpy(conn->protostr, "http");
 
1432
      }
 
1433
 
 
1434
      conn->protocol |= PROT_MISSING; /* not given in URL */
 
1435
    }
 
1436
  }
 
1437
 
 
1438
  buf = data->state.buffer; /* this is our buffer */
 
1439
 
 
1440
  /*************************************************************
 
1441
   * Take care of user and password authentication stuff
 
1442
   *************************************************************/
 
1443
 
 
1444
  if(conn->bits.user_passwd && !data->set.use_netrc) {
 
1445
    data->state.user[0] =0;
 
1446
    data->state.passwd[0]=0;
 
1447
 
 
1448
    if(*data->set.userpwd != ':') {
 
1449
      /* the name is given, get user+password */
 
1450
      sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
 
1451
             data->state.user, data->state.passwd);
 
1452
    }
 
1453
    else
 
1454
      /* no name given, get the password only */
 
1455
      sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
 
1456
 
 
1457
    /* check for password, if no ask for one */
 
1458
    if( !data->state.passwd[0] ) {
 
1459
      if(!data->set.fpasswd ||
 
1460
         data->set.fpasswd(data->set.passwd_client,
 
1461
                       "password:", data->state.passwd,
 
1462
                           sizeof(data->state.passwd)))
 
1463
        return CURLE_BAD_PASSWORD_ENTERED;
 
1464
    }
 
1465
  }
 
1466
 
 
1467
  /*************************************************************
 
1468
   * Take care of proxy authentication stuff
 
1469
   *************************************************************/
 
1470
  if(conn->bits.proxy_user_passwd) {
 
1471
    data->state.proxyuser[0] =0;
 
1472
    data->state.proxypasswd[0]=0;
 
1473
 
 
1474
    if(*data->set.proxyuserpwd != ':') {
 
1475
      /* the name is given, get user+password */
 
1476
      sscanf(data->set.proxyuserpwd, "%127[^:]:%127[^\n]",
 
1477
             data->state.proxyuser, data->state.proxypasswd);
 
1478
      }
 
1479
    else
 
1480
      /* no name given, get the password only */
 
1481
      sscanf(data->set.proxyuserpwd+1, "%127[^\n]", data->state.proxypasswd);
 
1482
 
 
1483
    /* check for password, if no ask for one */
 
1484
    if( !data->state.proxypasswd[0] ) {
 
1485
      if(!data->set.fpasswd ||
 
1486
         data->set.fpasswd( data->set.passwd_client,
 
1487
                        "proxy password:",
 
1488
                        data->state.proxypasswd,
 
1489
                        sizeof(data->state.proxypasswd)))
 
1490
        return CURLE_BAD_PASSWORD_ENTERED;
 
1491
    }
 
1492
 
 
1493
  }
 
1494
 
 
1495
  /*************************************************************
 
1496
   * Set a few convenience pointers 
 
1497
   *************************************************************/
 
1498
  conn->name = conn->gname;
 
1499
  conn->ppath = conn->path;
 
1500
  conn->hostname = conn->name;
 
1501
 
 
1502
 
 
1503
  /*************************************************************
 
1504
   * Detect what (if any) proxy to use
 
1505
   *************************************************************/
 
1506
  if(!data->change.proxy) {
 
1507
    /* If proxy was not specified, we check for default proxy environment
 
1508
     * variables, to enable i.e Lynx compliance:
 
1509
     *
 
1510
     * http_proxy=http://some.server.dom:port/
 
1511
     * https_proxy=http://some.server.dom:port/
 
1512
     * ftp_proxy=http://some.server.dom:port/
 
1513
     * gopher_proxy=http://some.server.dom:port/
 
1514
     * no_proxy=domain1.dom,host.domain2.dom
 
1515
     *   (a comma-separated list of hosts which should
 
1516
     *   not be proxied, or an asterisk to override
 
1517
     *   all proxy variables)
 
1518
     * all_proxy=http://some.server.dom:port/
 
1519
     *   (seems to exist for the CERN www lib. Probably
 
1520
     *   the first to check for.)
 
1521
     *
 
1522
     * For compatibility, the all-uppercase versions of these variables are
 
1523
     * checked if the lowercase versions don't exist.
 
1524
     */
 
1525
    char *no_proxy=NULL;
 
1526
    char *no_proxy_tok_buf;
 
1527
    char *proxy=NULL;
 
1528
    char proxy_env[128];
 
1529
 
 
1530
    no_proxy=curl_getenv("no_proxy");
 
1531
    if(!no_proxy)
 
1532
      no_proxy=curl_getenv("NO_PROXY");
 
1533
 
 
1534
    if(!no_proxy || !strequal("*", no_proxy)) {
 
1535
      /* NO_PROXY wasn't specified or it wasn't just an asterisk */
 
1536
      char *nope;
 
1537
 
 
1538
      nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
 
1539
      while(nope) {
 
1540
        if(strlen(nope) <= strlen(conn->name)) {
 
1541
          char *checkn=
 
1542
            conn->name + strlen(conn->name) - strlen(nope);
 
1543
          if(strnequal(nope, checkn, strlen(nope))) {
 
1544
            /* no proxy for this host! */
 
1545
            break;
 
1546
          }
 
1547
        }
 
1548
        nope=strtok_r(NULL, ", ", &no_proxy_tok_buf);
 
1549
      }
 
1550
      if(!nope) {
 
1551
        /* It was not listed as without proxy */
 
1552
        char *protop = conn->protostr;
 
1553
        char *envp = proxy_env;
 
1554
        char *prox;
 
1555
 
 
1556
        /* Now, build <protocol>_proxy and check for such a one to use */
 
1557
        while(*protop)
 
1558
          *envp++ = tolower(*protop++);
 
1559
 
 
1560
        /* append _proxy */
 
1561
        strcpy(envp, "_proxy");
 
1562
 
 
1563
        /* read the protocol proxy: */
 
1564
        prox=curl_getenv(proxy_env);
 
1565
 
 
1566
        /*
 
1567
         * We don't try the uppercase version of HTTP_PROXY because of
 
1568
         * security reasons:
 
1569
         *
 
1570
         * When curl is used in a webserver application
 
1571
         * environment (cgi or php), this environment variable can
 
1572
         * be controlled by the web server user by setting the
 
1573
         * http header 'Proxy:' to some value.
 
1574
         * 
 
1575
         * This can cause 'internal' http/ftp requests to be
 
1576
         * arbitrarily redirected by any external attacker.
 
1577
         */
 
1578
        if(!prox && !strequal("http_proxy", proxy_env)) {
 
1579
          /* There was no lowercase variable, try the uppercase version: */
 
1580
          for(envp = proxy_env; *envp; envp++)
 
1581
            *envp = toupper(*envp);
 
1582
          prox=curl_getenv(proxy_env);
 
1583
        }
 
1584
 
 
1585
        if(prox && *prox) { /* don't count "" strings */
 
1586
          proxy = prox; /* use this */
 
1587
        }
 
1588
        else {
 
1589
          proxy = curl_getenv("all_proxy"); /* default proxy to use */
 
1590
          if(!proxy)
 
1591
            proxy=curl_getenv("ALL_PROXY");
 
1592
        }
 
1593
 
 
1594
        if(proxy && *proxy) {
 
1595
          /* we have a proxy here to set */
 
1596
          data->change.proxy = proxy;
 
1597
          data->change.proxy_alloc=TRUE; /* this needs to be freed later */
 
1598
          conn->bits.httpproxy = TRUE;
 
1599
        }
 
1600
      } /* if (!nope) - it wasn't specified non-proxy */
 
1601
    } /* NO_PROXY wasn't specified or '*' */
 
1602
    if(no_proxy)
 
1603
      free(no_proxy);
 
1604
  } /* if not using proxy */
 
1605
 
 
1606
  /*************************************************************
 
1607
   * No protocol part in URL was used, add it!
 
1608
   *************************************************************/
 
1609
  if(conn->protocol&PROT_MISSING) {
 
1610
    /* We're guessing prefixes here and if we're told to use a proxy or if
 
1611
       we're gonna follow a Location: later or... then we need the protocol
 
1612
       part added so that we have a valid URL. */
 
1613
    char *reurl;
 
1614
 
 
1615
    reurl = aprintf("%s://%s", conn->protostr, data->change.url);
 
1616
 
 
1617
    if(!reurl)
 
1618
      return CURLE_OUT_OF_MEMORY;
 
1619
 
 
1620
    data->change.url = reurl;
 
1621
    data->change.url_alloc = TRUE; /* free this later */
 
1622
    conn->protocol &= ~PROT_MISSING; /* switch that one off again */
 
1623
  }
 
1624
 
 
1625
  /************************************************************
 
1626
   * RESUME on a HTTP page is a tricky business. First, let's just check that
 
1627
   * 'range' isn't used, then set the range parameter and leave the resume as
 
1628
   * it is to inform about this situation for later use. We will then
 
1629
   * "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
 
1630
   * server, we will get the document resumed. If we talk to a HTTP/1.0
 
1631
   * server, we just fail since we can't rewind the file writing from within
 
1632
   * this function.
 
1633
   ***********************************************************/
 
1634
  if(conn->resume_from) {
 
1635
    if(!conn->bits.use_range) {
 
1636
      /* if it already was in use, we just skip this */
 
1637
      snprintf(resumerange, sizeof(resumerange), "%d-", conn->resume_from);
 
1638
      conn->range=strdup(resumerange); /* tell ourselves to fetch this range */
 
1639
      conn->bits.rangestringalloc = TRUE; /* mark as allocated */
 
1640
      conn->bits.use_range = 1; /* switch on range usage */
 
1641
    }
 
1642
  }
 
1643
 
 
1644
  /*************************************************************
 
1645
   * Setup internals depending on protocol
 
1646
   *************************************************************/
 
1647
 
 
1648
  if (strequal(conn->protostr, "HTTP")) {
 
1649
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1650
      data->set.use_port:PORT_HTTP;
 
1651
    conn->remote_port = PORT_HTTP;
 
1652
    conn->protocol |= PROT_HTTP;
 
1653
    conn->curl_do = Curl_http;
 
1654
    conn->curl_done = Curl_http_done;
 
1655
    conn->curl_connect = Curl_http_connect;
 
1656
  }
 
1657
  else if (strequal(conn->protostr, "HTTPS")) {
 
1658
#ifdef USE_SSLEAY
 
1659
 
 
1660
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1661
      data->set.use_port:PORT_HTTPS;
 
1662
    conn->remote_port = PORT_HTTPS;
 
1663
    conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
 
1664
 
 
1665
    conn->curl_do = Curl_http;
 
1666
    conn->curl_done = Curl_http_done;
 
1667
    conn->curl_connect = Curl_http_connect;
 
1668
 
 
1669
#else /* USE_SSLEAY */
 
1670
    failf(data, LIBCURL_NAME
 
1671
          " was built with SSL disabled, https: not supported!");
 
1672
    return CURLE_UNSUPPORTED_PROTOCOL;
 
1673
#endif /* !USE_SSLEAY */
 
1674
  }
 
1675
  else if (strequal(conn->protostr, "GOPHER")) {
 
1676
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1677
      data->set.use_port:PORT_GOPHER;
 
1678
    conn->remote_port = PORT_GOPHER;
 
1679
    /* Skip /<item-type>/ in path if present */
 
1680
    if (isdigit((int)conn->path[1])) {
 
1681
      conn->ppath = strchr(&conn->path[1], '/');
 
1682
      if (conn->ppath == NULL)
 
1683
        conn->ppath = conn->path;
 
1684
      }
 
1685
    conn->protocol |= PROT_GOPHER;
 
1686
    conn->curl_do = Curl_http;
 
1687
    conn->curl_done = Curl_http_done;
 
1688
  }
 
1689
  else if(strequal(conn->protostr, "FTP") ||
 
1690
          strequal(conn->protostr, "FTPS")) {
 
1691
    char *type;
 
1692
 
 
1693
    if(strequal(conn->protostr, "FTPS")) {
 
1694
#ifdef USE_SSLEAY
 
1695
      conn->protocol |= PROT_FTPS|PROT_SSL;
 
1696
#else
 
1697
      failf(data, LIBCURL_NAME
 
1698
            " was built with SSL disabled, ftps: not supported!");
 
1699
      return CURLE_UNSUPPORTED_PROTOCOL;
 
1700
#endif /* !USE_SSLEAY */
 
1701
    }
 
1702
 
 
1703
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1704
      data->set.use_port:PORT_FTP;
 
1705
    conn->remote_port = PORT_FTP;
 
1706
    conn->protocol |= PROT_FTP;
 
1707
 
 
1708
    if(data->change.proxy &&
 
1709
       !data->set.tunnel_thru_httpproxy) {
 
1710
      /* Unless we have asked to tunnel ftp operations through the proxy, we
 
1711
         switch and use HTTP operations only */
 
1712
      if(conn->protocol & PROT_FTPS) {
 
1713
        /* FTPS is a hacked protocol and does not work through your
 
1714
           ordinary http proxy! */
 
1715
        failf(data, "ftps does not work through http proxy!");
 
1716
        return CURLE_UNSUPPORTED_PROTOCOL;
 
1717
      }
 
1718
      conn->curl_do = Curl_http;
 
1719
      conn->curl_done = Curl_http_done;
 
1720
    }
 
1721
    else {
 
1722
      conn->curl_do = Curl_ftp;
 
1723
      conn->curl_done = Curl_ftp_done;
 
1724
      conn->curl_connect = Curl_ftp_connect;
 
1725
      conn->curl_disconnect = Curl_ftp_disconnect;
 
1726
    }
 
1727
 
 
1728
    conn->ppath++; /* don't include the initial slash */
 
1729
 
 
1730
    /* FTP URLs support an extension like ";type=<typecode>" that
 
1731
     * we'll try to get now! */
 
1732
    type=strstr(conn->ppath, ";type=");
 
1733
    if(!type) {
 
1734
      type=strstr(conn->gname, ";type=");
 
1735
    }
 
1736
    if(type) {
 
1737
      char command;
 
1738
      *type=0;
 
1739
      command = toupper(type[6]);
 
1740
      switch(command) {
 
1741
      case 'A': /* ASCII mode */
 
1742
        data->set.ftp_ascii = 1;
 
1743
        break;
 
1744
      case 'D': /* directory mode */
 
1745
        data->set.ftp_list_only = 1;
 
1746
        break;
 
1747
      case 'I': /* binary mode */
 
1748
      default:
 
1749
        /* switch off ASCII */
 
1750
        data->set.ftp_ascii = 0;
 
1751
        break;
 
1752
      }
 
1753
    }
 
1754
  }
 
1755
  else if(strequal(conn->protostr, "TELNET")) {
 
1756
    /* telnet testing factory */
 
1757
    conn->protocol |= PROT_TELNET;
 
1758
 
 
1759
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1760
      data->set.use_port: PORT_TELNET;
 
1761
    conn->remote_port = PORT_TELNET;
 
1762
    conn->curl_do = Curl_telnet;
 
1763
    conn->curl_done = Curl_telnet_done;
 
1764
  }
 
1765
  else if (strequal(conn->protostr, "DICT")) {
 
1766
    conn->protocol |= PROT_DICT;
 
1767
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1768
      data->set.use_port:PORT_DICT;
 
1769
    conn->remote_port = PORT_DICT;
 
1770
    conn->curl_do = Curl_dict;
 
1771
    conn->curl_done = NULL; /* no DICT-specific done */
 
1772
  }
 
1773
  else if (strequal(conn->protostr, "LDAP")) {
 
1774
    conn->protocol |= PROT_LDAP;
 
1775
    conn->port = (data->set.use_port && data->state.allow_port)?
 
1776
      data->set.use_port:PORT_LDAP;
 
1777
    conn->remote_port = PORT_LDAP;
 
1778
    conn->curl_do = Curl_ldap;
 
1779
    conn->curl_done = NULL; /* no LDAP-specific done */
 
1780
  }
 
1781
  else if (strequal(conn->protostr, "FILE")) {
 
1782
    conn->protocol |= PROT_FILE;
 
1783
 
 
1784
    conn->curl_do = Curl_file;
 
1785
    /* no done() function */
 
1786
 
 
1787
    /* anyway, this is supposed to be the connect function so we better
 
1788
       at least check that the file is present here! */
 
1789
    result = Curl_file_connect(conn);
 
1790
 
 
1791
    /* Setup a "faked" transfer that'll do nothing */
 
1792
    if(CURLE_OK == result) {
 
1793
      result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
 
1794
                             -1, NULL); /* no upload */
 
1795
    }
 
1796
 
 
1797
    return result;
 
1798
  }
 
1799
  else {
 
1800
    /* We fell through all checks and thus we don't support the specified
 
1801
       protocol */
 
1802
    failf(data, "Unsupported protocol: %s", conn->protostr);
 
1803
    return CURLE_UNSUPPORTED_PROTOCOL;
 
1804
  }
 
1805
 
 
1806
  /*************************************************************
 
1807
   * .netrc scanning coming up
 
1808
   *************************************************************/
 
1809
  if(data->set.use_netrc) {
 
1810
    if(Curl_parsenetrc(conn->hostname,
 
1811
                       data->state.user,
 
1812
                       data->state.passwd)) {
 
1813
      infof(data, "Couldn't find host %s in the .netrc file, using defaults",
 
1814
            conn->hostname);
 
1815
    }
 
1816
    else
 
1817
      conn->bits.user_passwd = 1; /* enable user+password */
 
1818
 
 
1819
    /* weather we failed or not, we don't know which fields that were filled
 
1820
       in anyway */
 
1821
    if(!data->state.user[0])
 
1822
      strcpy(data->state.user, CURL_DEFAULT_USER);
 
1823
    if(!data->state.passwd[0])
 
1824
      strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
 
1825
  }
 
1826
  else if(!(conn->bits.user_passwd) &&
 
1827
          (conn->protocol & (PROT_FTP|PROT_HTTP)) ) {
 
1828
    /* This is a FTP or HTTP URL, and we haven't got the user+password in
 
1829
     * the extra parameter, we will now try to extract the possible
 
1830
     * user+password pair in a string like:
 
1831
     * ftp://user:password@ftp.my.site:8021/README */
 
1832
    char *ptr=NULL; /* assign to remove possible warnings */
 
1833
    if((ptr=strchr(conn->name, '@'))) {
 
1834
      /* there's a user+password given here, to the left of the @ */
 
1835
 
 
1836
      data->state.user[0] =0;
 
1837
      data->state.passwd[0]=0;
 
1838
 
 
1839
      if(*conn->name != ':') {
 
1840
        /* the name is given, get user+password */
 
1841
        sscanf(conn->name, "%127[^:@]:%127[^@]",
 
1842
               data->state.user, data->state.passwd);
 
1843
      }
 
1844
      else
 
1845
        /* no name given, get the password only */
 
1846
        sscanf(conn->name+1, "%127[^@]", data->state.passwd);
 
1847
 
 
1848
      if(data->state.user[0]) {
 
1849
        char *newname=curl_unescape(data->state.user, 0);
 
1850
        if(strlen(newname) < sizeof(data->state.user)) {
 
1851
          strcpy(data->state.user, newname);
 
1852
        }
 
1853
        /* if the new name is longer than accepted, then just use
 
1854
           the unconverted name, it'll be wrong but what the heck */
 
1855
        free(newname);
 
1856
      }
 
1857
 
 
1858
      /* check for password, if no ask for one */
 
1859
      if( !data->state.passwd[0] ) {
 
1860
        if(!data->set.fpasswd ||
 
1861
           data->set.fpasswd(data->set.passwd_client,
 
1862
                             "password:", data->state.passwd,
 
1863
                             sizeof(data->state.passwd)))
 
1864
          return CURLE_BAD_PASSWORD_ENTERED;
 
1865
      }
 
1866
      else {
 
1867
        /* we have a password found in the URL, decode it! */
 
1868
        char *newpasswd=curl_unescape(data->state.passwd, 0);
 
1869
        if(strlen(newpasswd) < sizeof(data->state.passwd)) {
 
1870
          strcpy(data->state.passwd, newpasswd);
 
1871
        }
 
1872
        free(newpasswd);
 
1873
      }
 
1874
 
 
1875
      conn->name = ++ptr;
 
1876
      conn->bits.user_passwd=TRUE; /* enable user+password */
 
1877
    }
 
1878
    else {
 
1879
      strcpy(data->state.user, CURL_DEFAULT_USER);
 
1880
      strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
 
1881
    }
 
1882
  }
 
1883
 
 
1884
  /*************************************************************
 
1885
   * Figure out the remote port number
 
1886
   *
 
1887
   * No matter if we use a proxy or not, we have to figure out the remote
 
1888
   * port number of various reasons.
 
1889
   *
 
1890
   * To be able to detect port number flawlessly, we must not confuse them
 
1891
   * IPv6-specified addresses in the [0::1] style. (RFC2732)
 
1892
   *************************************************************/
 
1893
 
 
1894
  if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
 
1895
     (']' == endbracket)) {
 
1896
    /* This is a (IPv6-style) specified IP-address. We support _any_
 
1897
       IP within brackets to be really generic. */
 
1898
    conn->name++; /* pass the starting bracket */
 
1899
 
 
1900
    tmp = strchr(conn->name, ']');
 
1901
    *tmp = 0; /* zero terminate */
 
1902
 
 
1903
    tmp++; /* pass the ending bracket */
 
1904
    if(':' != *tmp)
 
1905
      tmp = NULL; /* no port number available */
 
1906
  }
 
1907
  else {
 
1908
    /* traditional IPv4-style port-extracting */
 
1909
    tmp = strchr(conn->name, ':');
 
1910
  }
 
1911
 
 
1912
  if (tmp) {
 
1913
    *tmp++ = '\0'; /* cut off the name there */
 
1914
    conn->remote_port = atoi(tmp);
 
1915
  }
 
1916
 
 
1917
  if(data->change.proxy) {
 
1918
    /* If this is supposed to use a proxy, we need to figure out the proxy
 
1919
       host name name, so that we can re-use an existing connection
 
1920
       that may exist registered to the same proxy host. */
 
1921
 
 
1922
    char *prox_portno;
 
1923
    char *endofprot;
 
1924
 
 
1925
    /* We need to make a duplicate of the proxy so that we can modify the
 
1926
       string safely. */
 
1927
    char *proxydup=strdup(data->change.proxy);
 
1928
 
 
1929
    /* We use 'proxyptr' to point to the proxy name from now on... */
 
1930
    char *proxyptr=proxydup;
 
1931
 
 
1932
    if(NULL == proxydup) {
 
1933
      failf(data, "memory shortage");
 
1934
      return CURLE_OUT_OF_MEMORY;
 
1935
    }
 
1936
 
 
1937
    /* Daniel Dec 10, 1998:
 
1938
       We do the proxy host string parsing here. We want the host name and the
 
1939
       port name. Accept a protocol:// prefix, even though it should just be
 
1940
       ignored. */
 
1941
 
 
1942
    /* 1. skip the protocol part if present */
 
1943
    endofprot=strstr(proxyptr, "://");
 
1944
    if(endofprot) {
 
1945
      proxyptr = endofprot+3;
 
1946
    }
 
1947
 
 
1948
    /* allow user to specify proxy.server.com:1080 if desired */
 
1949
    prox_portno = strchr (proxyptr, ':');
 
1950
    if (prox_portno) {
 
1951
      *prox_portno = 0x0; /* cut off number from host name */
 
1952
      prox_portno ++;
 
1953
      /* now set the local port number */
 
1954
      conn->port = atoi(prox_portno);
 
1955
    }
 
1956
    else if(data->set.proxyport) {
 
1957
      /* None given in the proxy string, then get the default one if it is
 
1958
         given */
 
1959
      conn->port = data->set.proxyport;
 
1960
    }
 
1961
 
 
1962
    /* now, clone the cleaned proxy host name */
 
1963
    conn->proxyhost = strdup(proxyptr);
 
1964
 
 
1965
    free(proxydup); /* free the duplicate pointer and not the modified */
 
1966
  }
 
1967
 
 
1968
  /*************************************************************
 
1969
   * Check the current list of connections to see if we can
 
1970
   * re-use an already existing one or if we have to create a
 
1971
   * new one.
 
1972
   *************************************************************/
 
1973
 
 
1974
  /* reuse_fresh is set TRUE if we are told to use a fresh connection
 
1975
     by force */
 
1976
  if(!data->set.reuse_fresh &&
 
1977
     ConnectionExists(data, conn, &conn_temp)) {
 
1978
    /*
 
1979
     * We already have a connection for this, we got the former connection
 
1980
     * in the conn_temp variable and thus we need to cleanup the one we
 
1981
     * just allocated before we can move along and use the previously
 
1982
     * existing one.
 
1983
     */
 
1984
    struct connectdata *old_conn = conn;
 
1985
    char *path = old_conn->path; /* setup the current path pointer properly */
 
1986
    char *ppath = old_conn->ppath; /* this is the modified path pointer */
 
1987
    if(old_conn->proxyhost)
 
1988
      free(old_conn->proxyhost);
 
1989
    conn = conn_temp;        /* use this connection from now on */
 
1990
 
 
1991
    /* we need these pointers if we speak over a proxy */
 
1992
    conn->hostname = conn->gname;
 
1993
    conn->name = &conn->gname[old_conn->name - old_conn->gname];
 
1994
 
 
1995
    free(conn->path);    /* free the previously allocated path pointer */
 
1996
 
 
1997
    /* 'path' points to the allocated data, 'ppath' may have been advanced
 
1998
       to point somewhere within the 'path' area. */
 
1999
    conn->path = path; 
 
2000
    conn->ppath = ppath;
 
2001
 
 
2002
    /* re-use init */
 
2003
    conn->bits.reuse = TRUE; /* yes, we're re-using here */
 
2004
    conn->bits.chunk = FALSE; /* always assume not chunked unless told
 
2005
                                 otherwise */
 
2006
    conn->maxdownload = -1;  /* might have been used previously! */
 
2007
 
 
2008
    free(old_conn);          /* we don't need this anymore */
 
2009
 
 
2010
    /*
 
2011
     * If we're doing a resumed transfer, we need to setup our stuff
 
2012
     * properly.
 
2013
     */
 
2014
    conn->resume_from = data->set.set_resume_from;
 
2015
    if (conn->resume_from) {
 
2016
        snprintf(resumerange, sizeof(resumerange), "%d-", conn->resume_from);
 
2017
        if (conn->bits.rangestringalloc == TRUE) 
 
2018
            free(conn->range);
 
2019
        
 
2020
        /* tell ourselves to fetch this range */
 
2021
        conn->range = strdup(resumerange);
 
2022
        conn->bits.use_range = TRUE;        /* enable range download */
 
2023
        conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
 
2024
    }
 
2025
    else if (data->set.set_range) {
 
2026
      /* There is a range, but is not a resume, useful for random ftp access */
 
2027
      conn->range = strdup(data->set.set_range);
 
2028
      conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
 
2029
      conn->bits.use_range = TRUE;        /* enable range download */
 
2030
    }
 
2031
    
 
2032
    *in_connect = conn;      /* return this instead! */
 
2033
 
 
2034
    infof(data, "Re-using existing connection! (#%d)\n", conn->connectindex);
 
2035
  }
 
2036
  else {
 
2037
    /*
 
2038
     * This is a brand new connection, so let's store it in the connection
 
2039
     * cache of ours!
 
2040
     */
 
2041
    ConnectionStore(data, conn);
 
2042
  }
 
2043
 
 
2044
  /*************************************************************
 
2045
   * Set timeout if that is being used
 
2046
   *************************************************************/
 
2047
  if(data->set.timeout || data->set.connecttimeout) {
 
2048
    /*************************************************************
 
2049
     * Set signal handler to catch SIGALRM
 
2050
     * Store the old value to be able to set it back later!
 
2051
     *************************************************************/
 
2052
 
 
2053
#ifdef HAVE_SIGACTION
 
2054
    struct sigaction sigact;
 
2055
    sigaction(SIGALRM, NULL, &sigact);
 
2056
    keep_sigact = sigact;
 
2057
    keep_copysig = TRUE; /* yes, we have a copy */
 
2058
    sigact.sa_handler = alarmfunc;
 
2059
#ifdef SA_RESTART
 
2060
    /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
 
2061
    sigact.sa_flags &= ~SA_RESTART;
 
2062
#endif
 
2063
    /* now set the new struct */
 
2064
    sigaction(SIGALRM, &sigact, NULL);
 
2065
#else
 
2066
    /* no sigaction(), revert to the much lamer signal() */
 
2067
#ifdef HAVE_SIGNAL
 
2068
    keep_sigact = signal(SIGALRM, alarmfunc);
 
2069
#endif
 
2070
#endif
 
2071
 
 
2072
    /* We set the timeout on the name resolving phase first, separately from
 
2073
     * the download/upload part to allow a maximum time on everything. This is
 
2074
     * a signal-based timeout, why it won't work and shouldn't be used in
 
2075
     * multi-threaded environments. */
 
2076
 
 
2077
#ifdef HAVE_ALARM
 
2078
    /* alarm() makes a signal get sent when the timeout fires off, and that
 
2079
       will abort system calls */
 
2080
    prev_alarm = alarm(data->set.connecttimeout?
 
2081
                       data->set.connecttimeout:
 
2082
                       data->set.timeout);
 
2083
    /* We can expect the conn->created time to be "now", as that was just
 
2084
       recently set in the beginning of this function and nothing slow
 
2085
       has been done since then until now. */
 
2086
#endif
 
2087
  }
 
2088
 
 
2089
  /*************************************************************
 
2090
   * Resolve the name of the server or proxy
 
2091
   *************************************************************/
 
2092
  if(!data->change.proxy) {
 
2093
    /* If not connecting via a proxy, extract the port from the URL, if it is
 
2094
     * there, thus overriding any defaults that might have been set above. */
 
2095
    conn->port =  conn->remote_port; /* it is the same port */
 
2096
 
 
2097
    /* Resolve target host right on */
 
2098
    if(!conn->hostaddr) {
 
2099
      /* it might already be set if reusing a connection */
 
2100
      conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
 
2101
                                   &conn->hostent_buf);
 
2102
    }
 
2103
    if(!conn->hostaddr) {
 
2104
      failf(data, "Couldn't resolve host '%s'", conn->name);
 
2105
      result =  CURLE_COULDNT_RESOLVE_HOST;
 
2106
      /* don't return yet, we need to clean up the timeout first */
 
2107
    }
 
2108
  }
 
2109
  else if(!conn->hostaddr) {
 
2110
    /* This is a proxy that hasn't been resolved yet. It may be resolved
 
2111
       if we're reusing an existing connection. */
 
2112
 
 
2113
    /* resolve proxy */
 
2114
    /* it might already be set if reusing a connection */
 
2115
    conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
 
2116
                                 &conn->hostent_buf);
 
2117
 
 
2118
    if(!conn->hostaddr) {
 
2119
      failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
 
2120
      result = CURLE_COULDNT_RESOLVE_PROXY;
 
2121
      /* don't return yet, we need to clean up the timeout first */
 
2122
    }
 
2123
  }
 
2124
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
 
2125
#ifdef HAVE_ALARM
 
2126
  if(data->set.timeout || data->set.connecttimeout) {
 
2127
#ifdef HAVE_SIGACTION
 
2128
    if(keep_copysig) {
 
2129
      /* we got a struct as it looked before, now put that one back nice
 
2130
         and clean */
 
2131
      sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
 
2132
    }
 
2133
#else
 
2134
#ifdef HAVE_SIGNAL
 
2135
    /* restore the previous SIGALRM handler */
 
2136
    signal(SIGALRM, keep_sigact);
 
2137
#endif
 
2138
#endif
 
2139
    /* switch back the alarm() to either zero or to what it was before minus
 
2140
       the time we spent until now! */
 
2141
    if(prev_alarm) {
 
2142
      /* there was an alarm() set before us, now put it back */
 
2143
      long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
 
2144
      long alarm_set;
 
2145
 
 
2146
      /* the alarm period is counted in even number of seconds */
 
2147
      alarm_set = prev_alarm - elapsed_ms/1000;
 
2148
 
 
2149
      if(alarm_set<=0) {
 
2150
        /* if it turned negative, we should fire off a SIGALRM here, but we
 
2151
           won't, and zero would be to switch it off so we never set it to
 
2152
           less than 1! */
 
2153
        alarm(1);
 
2154
        result = CURLE_OPERATION_TIMEOUTED;
 
2155
        failf(data, "Previous alarm fired off!");
 
2156
      }
 
2157
      else
 
2158
        alarm(alarm_set);
 
2159
    }
 
2160
    else
 
2161
      alarm(0); /* just shut it off */
 
2162
  }
 
2163
#endif
 
2164
  if(result)
 
2165
    return result;
 
2166
 
 
2167
  /*************************************************************
 
2168
   * Proxy authentication
 
2169
   *************************************************************/
 
2170
  if(conn->bits.proxy_user_passwd) {
 
2171
    char *authorization;
 
2172
    snprintf(data->state.buffer, BUFSIZE, "%s:%s",
 
2173
             data->state.proxyuser, data->state.proxypasswd);
 
2174
    if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
 
2175
                          &authorization) >= 0) {
 
2176
      if(conn->allocptr.proxyuserpwd)
 
2177
        free(conn->allocptr.proxyuserpwd);
 
2178
      conn->allocptr.proxyuserpwd =
 
2179
        aprintf("Proxy-authorization: Basic %s\015\012", authorization);
 
2180
      free(authorization);
 
2181
    }
 
2182
  }
 
2183
 
 
2184
  /*************************************************************
 
2185
   * Send user-agent to HTTP proxies even if the target protocol
 
2186
   * isn't HTTP.
 
2187
   *************************************************************/
 
2188
  if((conn->protocol&PROT_HTTP) || data->change.proxy) {
 
2189
    if(data->set.useragent) {
 
2190
      if(conn->allocptr.uagent)
 
2191
        free(conn->allocptr.uagent);
 
2192
      conn->allocptr.uagent =
 
2193
        aprintf("User-Agent: %s\015\012", data->set.useragent);
 
2194
    }
 
2195
  }
 
2196
 
 
2197
  if(-1 == conn->firstsocket) {
 
2198
    /* Connect only if not already connected! */
 
2199
    result = ConnectPlease(conn);
 
2200
    if(CURLE_OK != result)
 
2201
      return result;
 
2202
 
 
2203
    if(conn->curl_connect) {
 
2204
      /* is there a connect() procedure? */
 
2205
 
 
2206
      /* set start time here for timeout purposes in the
 
2207
       * connect procedure, it is later set again for the
 
2208
       * progress meter purpose */
 
2209
      conn->now = Curl_tvnow();
 
2210
 
 
2211
      /* Call the protocol-specific connect function */
 
2212
      result = conn->curl_connect(conn);
 
2213
      if(result != CURLE_OK)
 
2214
        return result; /* pass back errors */
 
2215
    }
 
2216
  }
 
2217
 
 
2218
  Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected */
 
2219
 
 
2220
  conn->now = Curl_tvnow(); /* time this *after* the connect is done */
 
2221
  conn->bytecount = 0;
 
2222
  conn->headerbytecount = 0;
 
2223
  
 
2224
  /* Figure out the ip-number and display the first host name it shows: */
 
2225
#ifdef ENABLE_IPV6
 
2226
  {
 
2227
    char hbuf[NI_MAXHOST];
 
2228
#ifdef NI_WITHSCOPEID
 
2229
    const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
 
2230
#else
 
2231
    const int niflags = NI_NUMERICHOST;
 
2232
#endif
 
2233
    struct addrinfo *ai = conn->serv_addr;
 
2234
 
 
2235
    if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
 
2236
        niflags)) {
 
2237
      snprintf(hbuf, sizeof(hbuf), "?");
 
2238
    }
 
2239
    if (ai->ai_canonname) {
 
2240
      infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
 
2241
            conn->port);
 
2242
    } else {
 
2243
      infof(data, "Connected to %s port %d\n", hbuf, conn->port);
 
2244
    }
 
2245
  }
 
2246
#else
 
2247
  {
 
2248
    struct in_addr in;
 
2249
    (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
 
2250
    infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
 
2251
#if defined(HAVE_INET_NTOA_R)
 
2252
          inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf))
 
2253
#else
 
2254
          inet_ntoa(in)
 
2255
#endif
 
2256
          );
 
2257
  }
 
2258
#endif
 
2259
 
 
2260
#ifdef __EMX__
 
2261
  /* 20000330 mgs
 
2262
   * the check is quite a hack...
 
2263
   * we're calling _fsetmode to fix the problem with fwrite converting newline
 
2264
   * characters (you get mangled text files, and corrupted binary files when
 
2265
   * you download to stdout and redirect it to a file). */
 
2266
 
 
2267
  if ((data->set.out)->_handle == NULL) {
 
2268
    _fsetmode(stdout, "b");
 
2269
  }
 
2270
#endif
 
2271
 
 
2272
  return CURLE_OK;
 
2273
}
 
2274
 
 
2275
CURLcode Curl_connect(struct SessionHandle *data,
 
2276
                      struct connectdata **in_connect)
 
2277
{
 
2278
  CURLcode code;
 
2279
  struct connectdata *conn;
 
2280
 
 
2281
  /* call the stuff that needs to be called */
 
2282
  code = CreateConnection(data, in_connect);
 
2283
 
 
2284
  if(CURLE_OK != code) {
 
2285
    /* We're not allowed to return failure with memory left allocated
 
2286
       in the connectdata struct, free those here */
 
2287
    conn = (struct connectdata *)*in_connect;
 
2288
    if(conn) {
 
2289
      Curl_disconnect(conn);      /* close the connection */
 
2290
      *in_connect = NULL;         /* return a NULL */
 
2291
    }
 
2292
  }
 
2293
  return code;
 
2294
}
 
2295
 
 
2296
 
 
2297
CURLcode Curl_done(struct connectdata *conn)
 
2298
{
 
2299
  struct SessionHandle *data=conn->data;
 
2300
  CURLcode result;
 
2301
 
 
2302
  /* cleanups done even if the connection is re-used */
 
2303
 
 
2304
  if(conn->bits.rangestringalloc) {
 
2305
    free(conn->range);
 
2306
    conn->bits.rangestringalloc = FALSE;
 
2307
  }
 
2308
 
 
2309
  /* Cleanup possible redirect junk */
 
2310
  if(conn->newurl) {
 
2311
    free(conn->newurl);
 
2312
    conn->newurl = NULL;
 
2313
  }
 
2314
 
 
2315
  /* this calls the protocol-specific function pointer previously set */
 
2316
  if(conn->curl_done)
 
2317
    result = conn->curl_done(conn);
 
2318
  else
 
2319
    result = CURLE_OK;
 
2320
 
 
2321
  Curl_pgrsDone(conn); /* done with the operation */
 
2322
 
 
2323
  /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
 
2324
     forced us to close this no matter what we think.
 
2325
    
 
2326
     if conn->bits.close is TRUE, it means that the connection should be
 
2327
     closed in spite of all our efforts to be nice, due to protocol
 
2328
     restrictions in our or the server's end */
 
2329
  if(data->set.reuse_forbid ||
 
2330
     ((CURLE_OK == result) && conn->bits.close))
 
2331
    result = Curl_disconnect(conn); /* close the connection */
 
2332
  else
 
2333
    infof(data, "Connection #%d left intact\n", conn->connectindex);
 
2334
 
 
2335
  return result;
 
2336
}
 
2337
 
 
2338
CURLcode Curl_do(struct connectdata **connp)
 
2339
{
 
2340
  CURLcode result=CURLE_OK;
 
2341
  struct connectdata *conn = *connp;
 
2342
  struct SessionHandle *data=conn->data;
 
2343
 
 
2344
  if(conn->curl_do) {
 
2345
    /* generic protocol-specific function pointer set in curl_connect() */
 
2346
    result = conn->curl_do(conn);
 
2347
 
 
2348
    /* This was formerly done in transfer.c, but we better do it here */
 
2349
    
 
2350
    if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) {
 
2351
      /* This was a re-use of a connection and we got a write error in the
 
2352
       * DO-phase. Then we DISCONNECT this connection and have another attempt
 
2353
       * to CONNECT and then DO again! The retry cannot possibly find another
 
2354
       * connection to re-use, since we only keep one possible connection for
 
2355
       * each.  */
 
2356
 
 
2357
      infof(data, "Re-used connection seems dead, get a new one\n");
 
2358
 
 
2359
      conn->bits.close = TRUE; /* enforce close of this connetion */
 
2360
      result = Curl_done(conn);   /* we are so done with this */
 
2361
      if(CURLE_OK == result) {
 
2362
        /* Now, redo the connect and get a new connection */
 
2363
        result = Curl_connect(data, connp);
 
2364
        if(CURLE_OK == result)
 
2365
          /* ... finally back to actually retry the DO phase */
 
2366
          result = conn->curl_do(*connp);
 
2367
      }
 
2368
    }
 
2369
  }
 
2370
  return result;
 
2371
}
 
2372
 
 
2373
/*
 
2374
 * local variables:
 
2375
 * eval: (load-file "../curl-mode.el")
 
2376
 * end:
 
2377
 * vim600: fdm=marker
 
2378
 * vim: et sw=2 ts=2 sts=2 tw=78
 
2379
 */