]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/curl/lib/url.c
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / curl / lib / url.c
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: url.c,v 1.350 2004/03/12 08:55:51 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 <time.h>
40 #include <io.h>
41 #else
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
44 #endif
45 #include <netinet/in.h>
46 #include <sys/time.h>
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50 #include <netdb.h>
51 #ifdef HAVE_ARPA_INET_H
52 #include <arpa/inet.h>
53 #endif
54 #ifdef HAVE_NET_IF_H
55 #include <net/if.h>
56 #endif
57 #include <sys/ioctl.h>
58 #include <signal.h>
59
60 #ifdef HAVE_SYS_PARAM_H
61 #include <sys/param.h>
62 #endif
63
64 #ifdef HAVE_SYS_SELECT_H
65 #include <sys/select.h>
66 #endif
67
68 #ifdef VMS
69 #include <in.h>
70 #include <inet.h>
71 #endif
72
73 #ifdef HAVE_SETJMP_H
74 #include <setjmp.h>
75 #endif
76
77 #ifndef HAVE_SELECT
78 #error "We can't compile without select() support!"
79 #endif
80 #ifndef HAVE_SOCKET
81 #error "We can't compile without socket() support!"
82 #endif
83
84
85 #endif
86
87 #ifdef HAVE_OPENSSL_ENGINE_H
88 #include <openssl/engine.h>
89 #endif
90 #include "urldata.h"
91 #include "netrc.h"
92
93 #include "formdata.h"
94 #include "base64.h"
95 #include "ssluse.h"
96 #include "hostip.h"
97 #include "if2ip.h"
98 #include "transfer.h"
99 #include "sendf.h"
100 #include "progress.h"
101 #include "cookie.h"
102 #include "strequal.h"
103 #include "escape.h"
104 #include "strtok.h"
105 #include "share.h"
106 #include "content_encoding.h"
107 #include "http_digest.h"
108 #include "http_negotiate.h"
109
110 /* And now for the protocols */
111 #include "ftp.h"
112 #include "dict.h"
113 #include "telnet.h"
114 #include "http.h"
115 #include "file.h"
116 #include "ldap.h"
117 #include "url.h"
118 #include "connect.h"
119 //#include <ca-bundle.h>
120
121 #include <curl/types.h>
122
123 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
124 #include "inet_ntoa_r.h"
125 #endif
126
127 #define _MPRINTF_REPLACE /* use our functions only */
128 #include <curl/mprintf.h>
129
130 #ifdef HAVE_KRB4
131 #include "security.h"
132 #endif
133
134 /* The last #include file should be: */
135 #ifdef CURLDEBUG
136 #include "memdebug.h"
137 #endif
138
139 /* Local static prototypes */
140 static int ConnectionKillOne(struct SessionHandle *data);
141 static bool ConnectionExists(struct SessionHandle *data,
142                              struct connectdata *needle,
143                              struct connectdata **usethis);
144 static unsigned int ConnectionStore(struct SessionHandle *data,
145                                     struct connectdata *conn);
146 static bool safe_strequal(char* str1, char* str2);
147
148 #ifndef USE_ARES
149 /* not for Win32, unless it is cygwin
150    not for ares builds */
151 #if !defined(WIN32) || defined(__CYGWIN32__)
152
153 #ifndef RETSIGTYPE
154 #define RETSIGTYPE void
155 #endif
156 #ifdef HAVE_SIGSETJMP
157 extern sigjmp_buf curl_jmpenv;
158 #endif
159 static
160 RETSIGTYPE alarmfunc(int sig)
161 {
162   /* this is for "-ansi -Wall -pedantic" to stop complaining!   (rabe) */
163   (void)sig;
164 #ifdef HAVE_SIGSETJMP
165   siglongjmp(curl_jmpenv, 1);
166 #endif
167   return;
168 }
169 #endif
170 #endif /* USE_ARES */
171
172 void Curl_safefree(void *ptr)
173 {
174   if(ptr)
175     free(ptr);
176 }
177
178 /*
179  * This is the internal function curl_easy_cleanup() calls. This should
180  * cleanup and free all resources associated with this sessionhandle.
181  *
182  * NOTE: if we ever add something that attempts to write to a socket or
183  * similar here, we must ignore SIGPIPE first. It is currently only done
184  * when curl_easy_perform() is invoked.
185  */
186
187 CURLcode Curl_close(struct SessionHandle *data)
188 {
189   /* Loop through all open connections and kill them one by one */
190   while(-1 != ConnectionKillOne(data));
191
192 #ifdef USE_SSLEAY
193   /* Close down all open SSL info and sessions */
194   Curl_SSL_Close_All(data);
195 #endif
196
197   if(data->change.cookielist) /* clean up list if any */
198     curl_slist_free_all(data->change.cookielist);
199
200   Curl_safefree(data->state.auth_host);
201   Curl_safefree(data->state.scratch);
202
203   if(data->change.proxy_alloc)
204     free(data->change.proxy);
205
206   if(data->change.referer_alloc)
207     free(data->change.referer);
208
209   if(data->change.url_alloc)
210     free(data->change.url);
211
212   Curl_safefree(data->state.headerbuff);
213
214 #ifndef CURL_DISABLE_HTTP
215   Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
216   if(data->set.cookiejar) {
217     /* we have a "destination" for all the cookies to get dumped to */
218     if(Curl_cookie_output(data->cookies, data->set.cookiejar))
219       infof(data, "WARNING: failed to save cookies in %s\n",
220             data->set.cookiejar);
221   }
222
223   if( !data->share || (data->cookies != data->share->cookies) ) {
224     Curl_cookie_cleanup(data->cookies);
225   }
226   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
227 #endif
228
229   /* free the connection cache */
230   free(data->state.connects);
231
232   Curl_safefree(data->info.contenttype);
233
234   Curl_digest_cleanup(data);
235
236 #ifdef USE_ARES
237   /* this destroys the channel and we cannot use it anymore after this */
238   ares_destroy(data->state.areschannel);
239 #endif
240
241   /* No longer a dirty share, if it exists */
242   if (data->share)
243     data->share->dirty--;
244
245   free(data);
246   return CURLE_OK;
247 }
248
249 CURLcode Curl_open(struct SessionHandle **curl)
250 {
251   /* We don't yet support specifying the URL at this point */
252   struct SessionHandle *data;
253   /* Very simple start-up: alloc the struct, init it with zeroes and return */
254   data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle));
255   if(!data)
256     /* this is a very serious error */
257     return CURLE_OUT_OF_MEMORY;
258
259   memset(data, 0, sizeof(struct SessionHandle));
260
261 #ifdef USE_ARES
262   if(ARES_SUCCESS != ares_init(&data->state.areschannel)) {
263     free(data);
264     return CURLE_FAILED_INIT;
265   }
266   /* make sure that all other returns from this function should destroy the
267      ares channel before returning error! */
268 #endif
269
270   /* We do some initial setup here, all those fields that can't be just 0 */
271
272   data->state.headerbuff=(char*)malloc(HEADERSIZE);
273   if(!data->state.headerbuff) {
274     free(data); /* free the memory again */
275     return CURLE_OUT_OF_MEMORY;
276   }
277
278   data->state.headersize=HEADERSIZE;
279
280   data->set.out = stdout; /* default output to stdout */
281   data->set.in  = stdin;  /* default input from stdin */
282   data->set.err  = stderr;  /* default stderr to stderr */
283
284   /* use fwrite as default function to store output */
285   data->set.fwrite = (curl_write_callback)fwrite;
286
287   /* use fread as default function to read input */
288   data->set.fread = (curl_read_callback)fread;
289
290   data->set.infilesize = -1; /* we don't know any size */
291
292   data->state.current_speed = -1; /* init to negative == impossible */
293
294   data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
295   data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
296   data->set.ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
297
298   data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
299
300   /* make libcurl quiet by default: */
301   data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
302   data->progress.flags |= PGRS_HIDE;
303
304   /* Set the default size of the SSL session ID cache */
305   data->set.ssl.numsessions = 5;
306
307   data->set.proxyport = 1080;
308
309   data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
310
311   data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic authentication */
312   data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic authentication */
313
314   /* create an array with connection data struct pointers */
315   data->state.numconnects = 5; /* hard-coded right now */
316   data->state.connects = (struct connectdata **)
317     malloc(sizeof(struct connectdata *) * data->state.numconnects);
318
319   if(!data->state.connects) {
320     free(data->state.headerbuff);
321     free(data);
322     return CURLE_OUT_OF_MEMORY;
323   }
324
325   /*
326    * libcurl 7.10 introduces SSL verification *by default*! This needs to be
327    * switched off unless wanted.
328    */
329   data->set.ssl.verifypeer = TRUE;
330   data->set.ssl.verifyhost = 2;
331 #ifdef CURL_CA_BUNDLE
332   /* This is our prefered CA cert bundle since install time */
333   data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
334 #endif
335
336   memset(data->state.connects, 0,
337          sizeof(struct connectdata *)*data->state.numconnects);
338
339   *curl = data;
340   return CURLE_OK;
341 }
342
343 CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
344 {
345   va_list param;
346   char *cookiefile;
347
348   va_start(param, option);
349
350   switch(option) {
351   case CURLOPT_DNS_CACHE_TIMEOUT:
352     data->set.dns_cache_timeout = va_arg(param, int);
353     break;
354   case CURLOPT_DNS_USE_GLOBAL_CACHE:
355     {
356       int use_cache = va_arg(param, int);
357       if (use_cache) {
358         Curl_global_host_cache_init();
359       }
360
361       data->set.global_dns_cache = use_cache;
362     }
363     break;
364   case CURLOPT_SSL_CIPHER_LIST:
365     /* set a list of cipher we want to use in the SSL connection */
366     data->set.ssl.cipher_list = va_arg(param, char *);
367     break;
368
369   case CURLOPT_RANDOM_FILE:
370     /*
371      * This is the path name to a file that contains random data to seed
372      * the random SSL stuff with. The file is only used for reading.
373      */
374     data->set.ssl.random_file = va_arg(param, char *);
375     break;
376   case CURLOPT_EGDSOCKET:
377     /*
378      * The Entropy Gathering Daemon socket pathname
379      */
380     data->set.ssl.egdsocket = va_arg(param, char *);
381     break;
382   case CURLOPT_MAXCONNECTS:
383     /*
384      * Set the absolute number of maximum simultaneous alive connection that
385      * libcurl is allowed to have.
386      */
387     {
388       long newconnects= va_arg(param, long);
389       struct connectdata **newptr;
390
391       if(newconnects < data->state.numconnects) {
392         /* Since this number is *decreased* from the existing number, we must
393            close the possibly open connections that live on the indexes that
394            are being removed! */
395         int i;
396         for(i=newconnects; i< data->state.numconnects; i++)
397           Curl_disconnect(data->state.connects[i]);
398       }
399       if(newconnects) {
400         int i;
401         newptr= (struct connectdata **)
402           realloc(data->state.connects,
403                   sizeof(struct connectdata *) * newconnects);
404         if(!newptr)
405           /* we closed a few connections in vain, but so what? */
406           return CURLE_OUT_OF_MEMORY;
407
408         /* nullify the newly added pointers */
409         for(i=data->state.numconnects; i<newconnects; i++) {
410           newptr[i] = NULL;
411         }
412
413         data->state.connects = newptr;
414         data->state.numconnects = newconnects;
415       }
416       else {
417         /* zero makes NO cache at all */
418         if(data->state.connects)
419           free(data->state.connects);
420         data->state.connects=NULL;
421         data->state.numconnects=0;
422       }
423     }
424     break;
425   case CURLOPT_FORBID_REUSE:
426     /*
427      * When this transfer is done, it must not be left to be reused by a
428      * subsequent transfer but shall be closed immediately.
429      */
430     data->set.reuse_forbid = va_arg(param, long)?TRUE:FALSE;
431     break;
432   case CURLOPT_FRESH_CONNECT:
433     /*
434      * This transfer shall not use a previously cached connection but
435      * should be made with a fresh new connect!
436      */
437     data->set.reuse_fresh = va_arg(param, long)?TRUE:FALSE;
438     break;
439   case CURLOPT_VERBOSE:
440     /*
441      * Verbose means infof() calls that give a lot of information about
442      * the connection and transfer procedures as well as internal choices.
443      */
444     data->set.verbose = va_arg(param, long)?TRUE:FALSE;
445     break;
446   case CURLOPT_HEADER:
447     /*
448      * Set to include the header in the general data output stream.
449      */
450     data->set.http_include_header = va_arg(param, long)?TRUE:FALSE;
451     break;
452   case CURLOPT_NOPROGRESS:
453     /*
454      * Shut off the internal supported progress meter
455      */
456     data->set.hide_progress = va_arg(param, long)?TRUE:FALSE;
457     if(data->set.hide_progress)
458       data->progress.flags |= PGRS_HIDE;
459     else
460       data->progress.flags &= ~PGRS_HIDE;
461     break;
462   case CURLOPT_NOBODY:
463     /*
464      * Do not include the body part in the output data stream.
465      */
466     data->set.no_body = va_arg(param, long)?TRUE:FALSE;
467     break;
468   case CURLOPT_FAILONERROR:
469     /*
470      * Don't output the >=300 error code HTML-page, but instead only
471      * return error.
472      */
473     data->set.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
474     break;
475   case CURLOPT_UPLOAD:
476     /*
477      * We want to sent data to the remote host
478      */
479     data->set.upload = va_arg(param, long)?TRUE:FALSE;
480     if(data->set.upload)
481       /* If this is HTTP, PUT is what's needed to "upload" */
482       data->set.httpreq = HTTPREQ_PUT;
483     break;
484   case CURLOPT_FILETIME:
485     /*
486      * Try to get the file time of the remote document. The time will
487      * later (possibly) become available using curl_easy_getinfo().
488      */
489     data->set.get_filetime = va_arg(param, long)?TRUE:FALSE;
490     break;
491   case CURLOPT_FTP_CREATE_MISSING_DIRS:
492     /*
493      * An FTP option that modifies an upload to create missing directories on
494      * the server.
495      */ 
496     data->set.ftp_create_missing_dirs = va_arg( param , long )?TRUE:FALSE;
497     break;
498   case CURLOPT_FTP_RESPONSE_TIMEOUT:
499     /*
500      * An FTP option that specifies how quickly an FTP response must be 
501      * obtained before it is considered failure.
502      */
503     data->set.ftp_response_timeout = va_arg( param , long );
504     break;
505   case CURLOPT_FTPLISTONLY:
506     /*
507      * An FTP option that changes the command to one that asks for a list
508      * only, no file info details.
509      */
510     data->set.ftp_list_only = va_arg(param, long)?TRUE:FALSE;
511     break;
512   case CURLOPT_FTPAPPEND:
513     /*
514      * We want to upload and append to an existing (FTP) file.
515      */
516     data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
517     break;
518   case CURLOPT_NETRC:
519     /*
520      * Parse the $HOME/.netrc file
521      */
522     data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
523     break;
524   case CURLOPT_NETRC_FILE:
525     /*
526      * Use this file instead of the $HOME/.netrc file
527      */
528     data->set.netrc_file = va_arg(param, char *);
529     break;
530   case CURLOPT_FOLLOWLOCATION:
531     /*
532      * Follow Location: header hints on a HTTP-server.
533      */
534     data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
535     break;
536   case CURLOPT_UNRESTRICTED_AUTH:
537     /*
538      * Send authentication (user+password) when following locations, even when
539      * hostname changed.
540      */
541     data->set.http_disable_hostname_check_before_authentication =
542       va_arg(param, long)?TRUE:FALSE;
543     break;
544   case CURLOPT_HTTP_VERSION:
545     /*
546      * This sets a requested HTTP version to be used. The value is one of
547      * the listed enums in curl/curl.h.
548      */
549     data->set.httpversion = va_arg(param, long);
550     break;
551   case CURLOPT_TRANSFERTEXT:
552     /*
553      * This option was previously named 'FTPASCII'. Renamed to work with
554      * more protocols than merely FTP.
555      *
556      * Transfer using ASCII (instead of BINARY).
557      */
558     data->set.ftp_ascii = va_arg(param, long)?TRUE:FALSE;
559     break;
560   case CURLOPT_PUT:
561     /*
562      * Use the HTTP PUT request to transfer data if this is TRUE.  If this is
563      * FALSE, don't set the httpreq. We can't know what to revert it to!
564      */
565     if(va_arg(param, long))
566       data->set.httpreq = HTTPREQ_PUT;
567     break;
568   case CURLOPT_TIMECONDITION:
569     /*
570      * Set HTTP time condition. This must be one of the defines in the
571      * curl/curl.h header file.
572      */
573     data->set.timecondition = (curl_TimeCond)va_arg(param, long);
574     break;
575   case CURLOPT_TIMEVALUE:
576     /*
577      * This is the value to compare with the remote document with the
578      * method set with CURLOPT_TIMECONDITION
579      */
580     data->set.timevalue = va_arg(param, long);
581     break;
582   case CURLOPT_SSLVERSION:
583     /*
584      * Set explicit SSL version to try to connect with, as some SSL
585      * implementations are lame.
586      */
587     data->set.ssl.version = va_arg(param, long);
588     break;
589
590   case CURLOPT_COOKIESESSION:
591     /*
592      * Set this option to TRUE to start a new "cookie session". It will
593      * prevent the forthcoming read-cookies-from-file actions to accept
594      * cookies that are marked as being session cookies, as they belong to a
595      * previous session.
596      *
597      * In the original Netscape cookie spec, "session cookies" are cookies
598      * with no expire date set. RFC2109 describes the same action if no
599      * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
600      * a 'Discard' action that can enforce the discard even for cookies that
601      * have a Max-Age.
602      *
603      * We run mostly with the original cookie spec, as hardly anyone implements
604      * anything else.
605      */
606     data->set.cookiesession = (bool)va_arg(param, long);
607     break;
608
609 #ifndef CURL_DISABLE_HTTP
610   case CURLOPT_COOKIEFILE:
611     /*
612      * Set cookie file to read and parse. Can be used multiple times.
613      */
614     cookiefile = (char *)va_arg(param, void *);
615     if(cookiefile)
616       /* append the cookie file name to the list of file names, and deal with
617          them later */
618       data->change.cookielist =
619         curl_slist_append(data->change.cookielist, cookiefile);
620     break;
621
622   case CURLOPT_COOKIEJAR:
623     /*
624      * Set cookie file name to dump all cookies to when we're done.
625      */
626     data->set.cookiejar = (char *)va_arg(param, void *);
627
628     /*
629      * Activate the cookie parser. This may or may not already
630      * have been made.
631      */
632     data->cookies = Curl_cookie_init(data, NULL, data->cookies,
633                                      data->set.cookiesession);
634     break;
635 #endif
636
637   case CURLOPT_WRITEHEADER:
638     /*
639      * Custom pointer to pass the header write callback function
640      */
641     data->set.writeheader = (void *)va_arg(param, void *);
642     break;
643   case CURLOPT_COOKIE:
644     /*
645      * Cookie string to send to the remote server in the request.
646      */
647     data->set.cookie = va_arg(param, char *);
648     break;
649   case CURLOPT_ERRORBUFFER:
650     /*
651      * Error buffer provided by the caller to get the human readable
652      * error string in.
653      */
654     data->set.errorbuffer = va_arg(param, char *);
655     break;
656   case CURLOPT_FILE:
657     /*
658      * FILE pointer to write to or include in the data write callback
659      */
660     data->set.out = va_arg(param, FILE *);
661     break;
662   case CURLOPT_FTPPORT:
663     /*
664      * Use FTP PORT, this also specifies which IP address to use
665      */
666     data->set.ftpport = va_arg(param, char *);
667     data->set.ftp_use_port = data->set.ftpport?1:0;
668     break;
669
670   case CURLOPT_FTP_USE_EPRT:
671     data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
672     break;
673
674   case CURLOPT_FTP_USE_EPSV:
675     data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
676     break;
677     
678   case CURLOPT_HTTPHEADER:
679     /*
680      * Set a list with HTTP headers to use (or replace internals with)
681      */
682     data->set.headers = va_arg(param, struct curl_slist *);
683     break;
684   case CURLOPT_CUSTOMREQUEST:
685     /*
686      * Set a custom string to use as request
687      */
688     data->set.customrequest = va_arg(param, char *);
689
690     /* we don't set
691        data->set.httpreq = HTTPREQ_CUSTOM;
692        here, we continue as if we were using the already set type
693        and this just changes the actual request keyword */
694     break;
695   case CURLOPT_HTTPPOST:
696     /*
697      * Set to make us do HTTP POST
698      */
699     data->set.httppost = va_arg(param, struct curl_httppost *);
700     if(data->set.httppost)
701       data->set.httpreq = HTTPREQ_POST_FORM;
702     break;
703
704   case CURLOPT_HTTPGET:
705     /*
706      * Set to force us do HTTP GET
707      */
708     if(va_arg(param, long)) {
709       data->set.httpreq = HTTPREQ_GET;
710       data->set.upload = FALSE; /* switch off upload */
711     }
712     break;
713
714   case CURLOPT_INFILE:
715     /*
716      * FILE pointer to read the file to be uploaded from. Or possibly
717      * used as argument to the read callback.
718      */
719     data->set.in = va_arg(param, FILE *);
720     break;
721   case CURLOPT_INFILESIZE:
722     /*
723      * If known, this should inform curl about the file size of the
724      * to-be-uploaded file.
725      */
726     data->set.infilesize = va_arg(param, long);
727     break;
728   case CURLOPT_INFILESIZE_LARGE:
729     /*
730      * If known, this should inform curl about the file size of the
731      * to-be-uploaded file.
732      */
733     data->set.infilesize = va_arg(param, curl_off_t);
734     break;
735   case CURLOPT_LOW_SPEED_LIMIT:
736     /*
737      * The low speed limit that if transfers are below this for
738      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
739      */
740     data->set.low_speed_limit=va_arg(param, long);
741     break;
742   case CURLOPT_LOW_SPEED_TIME:
743     /*
744      * The low speed time that if transfers are below the set
745      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
746      */
747     data->set.low_speed_time=va_arg(param, long);
748     break;
749   case CURLOPT_URL:
750     /*
751      * The URL to fetch.
752      */
753     if(data->change.url_alloc) {
754       /* the already set URL is allocated, free it first! */
755       free(data->change.url);
756       data->change.url_alloc=FALSE;
757     }
758     data->set.set_url = va_arg(param, char *);
759     data->change.url = data->set.set_url;
760     data->change.url_changed = TRUE;
761     break;
762   case CURLOPT_PORT:
763     /*
764      * The port number to use when getting the URL
765      */
766     data->set.use_port = va_arg(param, long);
767     break;
768   case CURLOPT_POST:
769     /* Does this option serve a purpose anymore? Yes it does, when
770        CURLOPT_POSTFIELDS isn't used and the POST data is read off the
771        callback! */
772     if(va_arg(param, long))
773       data->set.httpreq = HTTPREQ_POST;
774     break;
775   case CURLOPT_POSTFIELDS:
776     /*
777      * A string with POST data. Makes curl HTTP POST.
778      */
779     data->set.postfields = va_arg(param, char *);
780     if(data->set.postfields)
781       data->set.httpreq = HTTPREQ_POST;
782     break;
783   case CURLOPT_POSTFIELDSIZE:
784     /*
785      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
786      * figure it out. Enables binary posts.
787      */
788     data->set.postfieldsize = va_arg(param, long);
789     break;
790   case CURLOPT_POSTFIELDSIZE_LARGE:
791     /*
792      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
793      * figure it out. Enables binary posts.
794      */
795     data->set.postfieldsize = va_arg(param, curl_off_t);
796     break;
797   case CURLOPT_REFERER:
798     /*
799      * String to set in the HTTP Referer: field.
800      */
801     if(data->change.referer_alloc) {
802       free(data->change.referer);
803       data->change.referer_alloc = FALSE;
804     }
805     data->set.set_referer = va_arg(param, char *);
806     data->change.referer = data->set.set_referer;
807     break;
808   case CURLOPT_AUTOREFERER:
809     /*
810      * Switch on automatic referer that gets set if curl follows locations.
811      */
812     data->set.http_auto_referer = va_arg(param, long)?1:0;
813     break;
814   case CURLOPT_PROXY:
815     /*
816      * Set proxy server:port to use as HTTP proxy.
817      *
818      * If the proxy is set to "" we explicitly say that we don't want to use a
819      * proxy (even though there might be environment variables saying so).
820      *
821      * Setting it to NULL, means no proxy but allows the environment variables
822      * to decide for us.
823      */
824     if(data->change.proxy_alloc) {
825       /*
826        * The already set string is allocated, free that first
827        */
828       data->change.proxy_alloc=FALSE;;
829       free(data->change.proxy);
830     }
831     data->set.set_proxy = va_arg(param, char *);
832     data->change.proxy = data->set.set_proxy;
833     break;
834   case CURLOPT_HTTPPROXYTUNNEL:
835     /*
836      * Tunnel operations through the proxy instead of normal proxy use
837      */
838     data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
839     break;
840   case CURLOPT_PROXYPORT:
841     /*
842      * Explicitly set HTTP proxy port number.
843      */
844     data->set.proxyport = va_arg(param, long);
845     break;
846   case CURLOPT_TIMEOUT:
847     /*
848      * The maximum time you allow curl to use for a single transfer
849      * operation.
850      */
851     data->set.timeout = va_arg(param, long);
852     break;
853   case CURLOPT_CONNECTTIMEOUT:
854     /*
855      * The maximum time you allow curl to use to connect.
856      */
857     data->set.connecttimeout = va_arg(param, long);
858     break;
859   case CURLOPT_MAXREDIRS:
860     /*
861      * The maximum amount of hops you allow curl to follow Location:
862      * headers. This should mostly be used to detect never-ending loops.
863      */
864     data->set.maxredirs = va_arg(param, long);
865     break;
866   case CURLOPT_USERAGENT:
867     /*
868      * String to use in the HTTP User-Agent field
869      */
870     data->set.useragent = va_arg(param, char *);
871     break;
872   case CURLOPT_ENCODING:
873     /*
874      * String to use at the value of Accept-Encoding header. 08/28/02 jhrg
875      *
876      * If the encoding is set to "" we use an Accept-Encoding header that
877      * encompasses all the encodings we support.
878      * If the encoding is set to NULL we don't send an Accept-Encoding header
879      * and ignore an received Content-Encoding header.
880      *
881      */
882     data->set.encoding = va_arg(param, char *);
883     if(data->set.encoding && !*data->set.encoding)
884       data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
885     break;
886
887   case CURLOPT_HTTPAUTH:
888     /*
889      * Set HTTP Authentication type BITMASK.
890      */
891   {
892     long auth = va_arg(param, long);
893     /* switch off bits we can't support */
894 #ifndef USE_SSLEAY
895     auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
896 #endif
897 #ifndef HAVE_GSSAPI
898     auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
899 #endif
900     if(!auth)
901       return CURLE_FAILED_INIT; /* no supported types left! */
902
903     data->set.httpauth = auth;
904   }
905   break;
906   
907   case CURLOPT_PROXYAUTH:
908     /*
909      * Set HTTP Authentication type BITMASK.
910      */
911   {
912     long auth = va_arg(param, long);
913     /* switch off bits we can't support */
914 #ifndef USE_SSLEAY
915     auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
916 #endif
917 #ifndef HAVE_GSSAPI
918     auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
919 #endif
920     if(!auth)
921       return CURLE_FAILED_INIT; /* no supported types left! */
922
923     data->set.proxyauth = auth;
924   }
925   break;
926
927   case CURLOPT_USERPWD:
928     /*
929      * user:password to use in the operation
930      */
931     data->set.userpwd = va_arg(param, char *);
932     break;
933   case CURLOPT_POSTQUOTE:
934     /*
935      * List of RAW FTP commands to use after a transfer
936      */
937     data->set.postquote = va_arg(param, struct curl_slist *);
938     break;
939   case CURLOPT_PREQUOTE:
940     /*
941      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
942      */
943     data->set.prequote = va_arg(param, struct curl_slist *);
944     break;
945   case CURLOPT_QUOTE:
946     /*
947      * List of RAW FTP commands to use before a transfer
948      */
949     data->set.quote = va_arg(param, struct curl_slist *);
950     break;
951   case CURLOPT_PROGRESSFUNCTION:
952     /*
953      * Progress callback function
954      */
955     data->set.fprogress = va_arg(param, curl_progress_callback);
956     if(data->set.fprogress)
957       data->progress.callback = TRUE; /* no longer internal */
958     else
959       data->progress.callback = FALSE; /* NULL enforces internal */
960
961     break;
962   case CURLOPT_PROGRESSDATA:
963     /*
964      * Custom client data to pass to the progress callback
965      */
966     data->set.progress_client = va_arg(param, void *);
967     break;
968   case CURLOPT_PROXYUSERPWD:
969     /*
970      * user:password needed to use the proxy
971      */
972     data->set.proxyuserpwd = va_arg(param, char *);
973     break;
974   case CURLOPT_RANGE:
975     /*
976      * What range of the file you want to transfer
977      */
978     data->set.set_range = va_arg(param, char *);
979     break;
980   case CURLOPT_RESUME_FROM:
981     /*
982      * Resume transfer at the give file position
983      */
984     data->set.set_resume_from = va_arg(param, long);
985     break;
986   case CURLOPT_RESUME_FROM_LARGE:
987     /*
988      * Resume transfer at the give file position
989      */
990     data->set.set_resume_from = va_arg(param, curl_off_t);
991     break;
992   case CURLOPT_DEBUGFUNCTION:
993     /*
994      * stderr write callback.
995      */
996     data->set.fdebug = va_arg(param, curl_debug_callback);
997     /*
998      * if the callback provided is NULL, it'll use the default callback
999      */
1000     break;
1001   case CURLOPT_DEBUGDATA:
1002     /*
1003      * Set to a void * that should receive all error writes. This
1004      * defaults to CURLOPT_STDERR for normal operations.
1005      */
1006     data->set.debugdata = va_arg(param, void *);
1007     break;
1008   case CURLOPT_STDERR:
1009     /*
1010      * Set to a FILE * that should receive all error writes. This
1011      * defaults to stderr for normal operations.
1012      */
1013     data->set.err = va_arg(param, FILE *);
1014     if(!data->set.err)
1015       data->set.err = stderr;
1016     break;
1017   case CURLOPT_HEADERFUNCTION:
1018     /*
1019      * Set header write callback
1020      */
1021     data->set.fwrite_header = va_arg(param, curl_write_callback);
1022     break;
1023   case CURLOPT_WRITEFUNCTION:
1024     /*
1025      * Set data write callback
1026      */
1027     data->set.fwrite = va_arg(param, curl_write_callback);
1028     if(!data->set.fwrite)
1029       /* When set to NULL, reset to our internal default function */
1030       data->set.fwrite = (curl_write_callback)fwrite;
1031     break;
1032   case CURLOPT_READFUNCTION:
1033     /*
1034      * Read data callback
1035      */
1036     data->set.fread = va_arg(param, curl_read_callback);
1037     if(!data->set.fread)
1038       /* When set to NULL, reset to our internal default function */
1039       data->set.fread = (curl_read_callback)fread;
1040     break;
1041   case CURLOPT_SSLCERT:
1042     /*
1043      * String that holds file name of the SSL certificate to use
1044      */
1045     data->set.cert = va_arg(param, char *);
1046     break;
1047   case CURLOPT_SSLCERTTYPE:
1048     /*
1049      * String that holds file type of the SSL certificate to use
1050      */
1051     data->set.cert_type = va_arg(param, char *);
1052     break;
1053   case CURLOPT_SSLKEY:
1054     /*
1055      * String that holds file name of the SSL certificate to use
1056      */
1057     data->set.key = va_arg(param, char *);
1058     break;
1059   case CURLOPT_SSLKEYTYPE:
1060     /*
1061      * String that holds file type of the SSL certificate to use
1062      */
1063     data->set.key_type = va_arg(param, char *);
1064     break;
1065   case CURLOPT_SSLKEYPASSWD:
1066     /*
1067      * String that holds the SSL private key password.
1068      */
1069     data->set.key_passwd = va_arg(param, char *);
1070     break;
1071   case CURLOPT_SSLENGINE:
1072     /*
1073      * String that holds the SSL crypto engine.
1074      */
1075 #ifdef HAVE_OPENSSL_ENGINE_H
1076     {
1077       const char *cpTemp = va_arg(param, char *);
1078       ENGINE     *e;
1079       if (cpTemp && cpTemp[0]) {
1080         e = ENGINE_by_id(cpTemp);
1081         if (e) {
1082           if (data->engine) {
1083             ENGINE_free(data->engine);
1084           }
1085           data->engine = e;
1086         }
1087         else {
1088           failf(data, "SSL Engine '%s' not found", cpTemp);
1089           return CURLE_SSL_ENGINE_NOTFOUND;
1090         }
1091       }
1092     }
1093     break;
1094 #else
1095     return CURLE_SSL_ENGINE_NOTFOUND;
1096 #endif
1097   case CURLOPT_SSLENGINE_DEFAULT:
1098     /*
1099      * flag to set engine as default.
1100      */
1101 #ifdef HAVE_OPENSSL_ENGINE_H
1102     if (data->engine) {
1103       if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) {
1104 #ifdef DEBUG
1105         fprintf(stderr,"set default crypto engine\n");
1106 #endif
1107       }
1108       else {
1109 #ifdef DEBUG
1110         failf(data, "set default crypto engine failed");
1111 #endif
1112         return CURLE_SSL_ENGINE_SETFAILED;
1113       }
1114     }
1115 #endif
1116     break;
1117   case CURLOPT_CRLF:
1118     /*
1119      * Kludgy option to enable CRLF convertions. Subject for removal.
1120      */
1121     data->set.crlf = va_arg(param, long)?TRUE:FALSE;
1122     break;
1123   case CURLOPT_INTERFACE:
1124     /*
1125      * Set what interface to bind to when performing an operation and thus
1126      * what from-IP your connection will use.
1127      */
1128     data->set.device = va_arg(param, char *);
1129     break;
1130   case CURLOPT_KRB4LEVEL:
1131     /*
1132      * A string that defines the krb4 security level.
1133      */
1134     data->set.krb4_level = va_arg(param, char *);
1135     data->set.krb4=data->set.krb4_level?TRUE:FALSE;
1136     break;
1137   case CURLOPT_SSL_VERIFYPEER:
1138     /*
1139      * Enable peer SSL verifying.
1140      */
1141     data->set.ssl.verifypeer = va_arg(param, long);
1142     break;
1143   case CURLOPT_SSL_VERIFYHOST:
1144     /*
1145      * Enable verification of the CN contained in the peer certificate
1146      */
1147     data->set.ssl.verifyhost = va_arg(param, long);
1148     break;
1149   case CURLOPT_SSL_CTX_FUNCTION:
1150     /*
1151      * Set a SSL_CTX callback
1152      */
1153        data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
1154     break;
1155   case CURLOPT_SSL_CTX_DATA:
1156     /*
1157      * Set a SSL_CTX callback parameter pointer
1158      */
1159     data->set.ssl.fsslctxp = va_arg(param, void *);
1160     break;
1161   case CURLOPT_CAINFO:
1162     /*
1163      * Set CA info for SSL connection. Specify file name of the CA certificate
1164      */
1165     data->set.ssl.CAfile = va_arg(param, char *);
1166     break;
1167   case CURLOPT_CAPATH:
1168     /*
1169      * Set CA path info for SSL connection. Specify directory name of the CA
1170      * certificates which have been prepared using openssl c_rehash utility.
1171      */
1172     /* This does not work on windows. */
1173     data->set.ssl.CApath = va_arg(param, char *);
1174     break;
1175   case CURLOPT_TELNETOPTIONS:
1176     /*
1177      * Set a linked list of telnet options
1178      */
1179     data->set.telnet_options = va_arg(param, struct curl_slist *);
1180     break;
1181
1182   case CURLOPT_BUFFERSIZE:
1183     /*
1184      * The application kindly asks for a differently sized receive buffer.
1185      * If it seems reasonable, we'll use it.
1186      */
1187     data->set.buffer_size = va_arg(param, long);
1188
1189     if((data->set.buffer_size> (BUFSIZE -1 )) ||
1190        (data->set.buffer_size < 1))
1191       data->set.buffer_size = 0; /* huge internal default */
1192
1193     break;
1194
1195   case CURLOPT_NOSIGNAL:
1196     /*
1197      * The application asks not to set any signal() or alarm() handlers,
1198      * even when using a timeout.
1199      */
1200     data->set.no_signal = va_arg(param, long) ? TRUE : FALSE;
1201     break;
1202
1203   case CURLOPT_SHARE:
1204     {
1205       struct Curl_share *set;
1206       set = va_arg(param, struct Curl_share *);
1207
1208       /* disconnect from old share, if any */
1209       if(data->share) {
1210         Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1211
1212         if(data->share->hostcache == data->hostcache)
1213           data->hostcache = NULL;
1214
1215         if(data->share->cookies == data->cookies)
1216           data->cookies = NULL;
1217
1218         data->share->dirty--;
1219
1220         Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1221         data->share = NULL;
1222       }
1223
1224       /* use new share if it set */
1225       data->share = set;
1226       if(data->share) {
1227
1228         Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1229
1230         data->share->dirty++;
1231
1232         if(data->share->hostcache) {
1233           /* use shared host cache, first free own one if any */
1234           if(data->hostcache)
1235             Curl_hash_destroy(data->hostcache);
1236
1237           data->hostcache = data->share->hostcache;
1238         }
1239         
1240         if(data->share->cookies) {
1241           /* use shared cookie list, first free own one if any */
1242           if (data->cookies)
1243             Curl_cookie_cleanup(data->cookies);
1244           data->cookies = data->share->cookies;
1245         }
1246
1247         Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1248         
1249       }
1250
1251       /* check cookie list is set */
1252       if(!data->cookies)
1253         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
1254       
1255       /* check for host cache not needed,
1256        * it will be done by curl_easy_perform */ 
1257     }
1258     break;
1259
1260   case CURLOPT_PROXYTYPE:
1261     /*
1262      * Set proxy type. HTTP/SOCKS4/SOCKS5
1263      */
1264     data->set.proxytype = (curl_proxytype)va_arg(param, long);
1265     break;
1266
1267   case CURLOPT_PRIVATE:
1268     /*
1269      * Set private data pointer.
1270      */
1271     data->set.private = va_arg(param, char *);
1272     break;
1273
1274   case CURLOPT_HTTP200ALIASES:
1275     /*
1276      * Set a list of aliases for HTTP 200 in response header
1277      */
1278     data->set.http200aliases = va_arg(param, struct curl_slist *);
1279     break;
1280
1281   case CURLOPT_MAXFILESIZE:
1282     /*
1283      * Set the maximum size of a file to download.
1284      */
1285     data->set.max_filesize = va_arg(param, long);
1286     break;
1287
1288   case CURLOPT_FTP_SSL:
1289     /*
1290      * Make FTP transfers attempt to use SSL/TLS.
1291      */
1292     data->set.ftp_ssl = (curl_ftpssl)va_arg(param, long);
1293     break;
1294
1295   case CURLOPT_IPRESOLVE:
1296     data->set.ip_version = va_arg(param, long);
1297     break;
1298
1299   case CURLOPT_MAXFILESIZE_LARGE:
1300     /*
1301      * Set the maximum size of a file to download.
1302      */
1303     data->set.max_filesize = va_arg(param, curl_off_t);
1304     break;
1305
1306   default:
1307     /* unknown tag and its companion, just ignore: */
1308     return CURLE_FAILED_INIT; /* correct this */
1309   }
1310   return CURLE_OK;
1311 }
1312
1313 CURLcode Curl_disconnect(struct connectdata *conn)
1314 {
1315   if(!conn)
1316     return CURLE_OK; /* this is closed and fine already */
1317
1318   /*
1319    * The range string is usually freed in curl_done(), but we might
1320    * get here *instead* if we fail prematurely. Thus we need to be able
1321    * to free this resource here as well.
1322    */
1323   if(conn->bits.rangestringalloc) {
1324     free(conn->range);
1325     conn->bits.rangestringalloc = FALSE;
1326   }
1327
1328   if((conn->ntlm.state != NTLMSTATE_NONE) ||
1329      (conn->proxyntlm.state != NTLMSTATE_NONE))
1330     /* Authentication data is a mix of connection-related and sessionhandle-
1331        related stuff. NTLM is connection-related so when we close the shop
1332        we shall forget. */
1333     conn->data->state.authstage = 0;
1334
1335   if(conn->curl_disconnect)
1336     /* This is set if protocol-specific cleanups should be made */
1337     conn->curl_disconnect(conn);
1338
1339   if(-1 != conn->connectindex) {
1340     /* unlink ourselves! */
1341     infof(conn->data, "Closing connection #%d\n", conn->connectindex);
1342     conn->data->state.connects[conn->connectindex] = NULL;
1343   }
1344
1345   Curl_safefree(conn->proto.generic);
1346   Curl_safefree(conn->newurl);
1347   Curl_safefree(conn->path);  /* the URL path part */
1348   Curl_SSL_Close(conn);
1349
1350   /* close possibly still open sockets */
1351   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
1352     sclose(conn->sock[SECONDARYSOCKET]);
1353   if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
1354     sclose(conn->sock[FIRSTSOCKET]);
1355
1356   Curl_safefree(conn->user);
1357   Curl_safefree(conn->passwd);
1358   Curl_safefree(conn->proxyuser);
1359   Curl_safefree(conn->proxypasswd);
1360   Curl_safefree(conn->allocptr.proxyuserpwd);
1361   Curl_safefree(conn->allocptr.uagent);
1362   Curl_safefree(conn->allocptr.userpwd);
1363   Curl_safefree(conn->allocptr.accept_encoding);
1364   Curl_safefree(conn->allocptr.rangeline);
1365   Curl_safefree(conn->allocptr.ref);
1366   Curl_safefree(conn->allocptr.cookie);
1367   Curl_safefree(conn->allocptr.host);
1368   Curl_safefree(conn->allocptr.cookiehost);
1369   Curl_safefree(conn->proxyhost);
1370 #if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
1371   /* possible left-overs from the async name resolve */
1372   Curl_safefree(conn->async.hostname);
1373   Curl_safefree(conn->async.os_specific);
1374 #endif
1375   
1376   Curl_free_ssl_config(&conn->ssl_config);
1377
1378   free(conn); /* free all the connection oriented data */
1379
1380   return CURLE_OK;
1381 }
1382
1383 /*
1384  * This function should return TRUE if the socket is to be assumed to
1385  * be dead. Most commonly this happens when the server has closed the
1386  * connection due to inactivity.
1387  */
1388 static bool SocketIsDead(curl_socket_t sock)
1389 {
1390   int sval;
1391   bool ret_val = TRUE;
1392   fd_set check_set;
1393   struct timeval to;
1394
1395   FD_ZERO(&check_set);
1396   FD_SET(sock, &check_set);
1397
1398   to.tv_sec = 0;
1399   to.tv_usec = 0;
1400
1401   sval = select(sock + 1, &check_set, 0, 0, &to);
1402   if(sval == 0)
1403     /* timeout */
1404     ret_val = FALSE;
1405
1406   return ret_val;
1407 }
1408
1409 /*
1410  * Given one filled in connection struct (named needle), this function should
1411  * detect if there already is one that have all the significant details
1412  * exactly the same and thus should be used instead.
1413  */
1414 static bool
1415 ConnectionExists(struct SessionHandle *data,
1416                  struct connectdata *needle,
1417                  struct connectdata **usethis)
1418 {
1419   long i;
1420   struct connectdata *check;
1421
1422   for(i=0; i< data->state.numconnects; i++) {
1423     bool match = FALSE;
1424     /*
1425      * Note that if we use a HTTP proxy, we check connections to that
1426      * proxy and not to the actual remote server.
1427      */
1428     check = data->state.connects[i];
1429     if(!check)
1430       /* NULL pointer means not filled-in entry */
1431       continue;
1432
1433     if((needle->protocol&PROT_SSL) != (check->protocol&PROT_SSL))
1434       /* don't do mixed SSL and non-SSL connections */
1435       continue;
1436
1437     if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) {
1438       /* The requested connection does not use a HTTP proxy or it
1439          uses SSL. */
1440
1441       if(!(needle->protocol&PROT_SSL) && check->bits.httpproxy)
1442         /* we don't do SSL but the cached connection has a proxy,
1443            then don't match this */
1444         continue;
1445
1446       if(strequal(needle->protostr, check->protostr) &&
1447          strequal(needle->name, check->name) &&
1448          (needle->remote_port == check->remote_port) ) {
1449         if(needle->protocol & PROT_SSL) {
1450           /* This is SSL, verify that we're using the same
1451              ssl options as well */
1452           if(!Curl_ssl_config_matches(&needle->ssl_config,
1453                                       &check->ssl_config)) {
1454             continue;
1455           }
1456         }
1457         if((needle->protocol & PROT_FTP) ||
1458            ((needle->protocol & PROT_HTTP) &&
1459             (needle->data->state.authwant==CURLAUTH_NTLM))) {
1460           /* This is FTP or HTTP+NTLM, verify that we're using the same name
1461              and password as well */
1462           if(!strequal(needle->user, check->user) ||
1463              !strequal(needle->passwd, check->passwd)) {
1464             /* one of them was different */
1465             continue;
1466           }
1467         }
1468         match = TRUE;
1469       }
1470     }
1471     else { /* The requested needle connection is using a proxy,
1472               is the checked one using the same? */
1473       if(check->bits.httpproxy &&
1474          strequal(needle->proxyhost, check->proxyhost) &&
1475          needle->port == check->port) {
1476         /* This is the same proxy connection, use it! */
1477         match = TRUE;
1478       }
1479     }
1480
1481     if(match) {
1482       bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
1483       if(dead) {
1484         /*
1485          */
1486         infof(data, "Connection %d seems to be dead!\n", i);
1487         Curl_disconnect(check); /* disconnect resources */
1488         data->state.connects[i]=NULL; /* nothing here */
1489
1490         /* There's no need to continue searching, because we only store
1491            one connection for each unique set of identifiers */
1492         return FALSE;
1493       }
1494
1495       *usethis = check;
1496       return TRUE; /* yes, we found one to use! */
1497     }
1498   }
1499   return FALSE; /* no matching connecting exists */
1500 }
1501
1502 /*
1503  * This function frees/closes a connection in the connection cache. This
1504  * should take the previously set policy into account when deciding which
1505  * of the connections to kill.
1506  */
1507 static int
1508 ConnectionKillOne(struct SessionHandle *data)
1509 {
1510   long i;
1511   struct connectdata *conn;
1512   int highscore=-1;
1513   int connindex=-1;
1514   int score;
1515   struct timeval now;
1516
1517   now = Curl_tvnow();
1518
1519   for(i=0; i< data->state.numconnects; i++) {
1520     conn = data->state.connects[i];
1521
1522     if(!conn)
1523       continue;
1524
1525     /*
1526      * By using the set policy, we score each connection.
1527      */
1528     switch(data->set.closepolicy) {
1529     case CURLCLOSEPOLICY_LEAST_RECENTLY_USED:
1530     default:
1531       /*
1532        * Set higher score for the age passed since the connection
1533        * was used.
1534        */
1535       score = Curl_tvdiff(now, conn->now);
1536       break;
1537     case CURLCLOSEPOLICY_OLDEST:
1538       /*
1539        * Set higher score for the age passed since the connection
1540        * was created.
1541        */
1542       score = Curl_tvdiff(now, conn->created);
1543       break;
1544     }
1545
1546     if(score > highscore) {
1547       highscore = score;
1548       connindex = i;
1549     }
1550   }
1551   if(connindex >= 0) {
1552
1553     /* the winner gets the honour of being disconnected */
1554     (void) Curl_disconnect(data->state.connects[connindex]);
1555
1556     /* clean the array entry */
1557     data->state.connects[connindex] = NULL;
1558   }
1559
1560   return connindex; /* return the available index or -1 */
1561 }
1562
1563 /*
1564  * The given input connection struct pointer is to be stored. If the "cache"
1565  * is already full, we must clean out the most suitable using the previously
1566  * set policy.
1567  *
1568  * The given connection should be unique. That must've been checked prior to
1569  * this call.
1570  */
1571 static unsigned int
1572 ConnectionStore(struct SessionHandle *data,
1573                 struct connectdata *conn)
1574 {
1575   long i;
1576   for(i=0; i< data->state.numconnects; i++) {
1577     if(!data->state.connects[i])
1578       break;
1579   }
1580   if(i == data->state.numconnects) {
1581     /* there was no room available, kill one */
1582     i = ConnectionKillOne(data);
1583     infof(data, "Connection (#%d) was killed to make room\n", i);
1584   }
1585
1586   if(-1 != i) {
1587     /* only do this if a true index was returned, if -1 was returned there
1588        is no room in the cache for an unknown reason and we cannot store
1589        this there. */
1590     data->state.connects[i] = conn; /* fill in this */
1591     conn->connectindex = i; /* make the child know where the pointer to this
1592                                particular data is stored */
1593   }
1594   return i;
1595 }
1596
1597 /*
1598  * This function logs in to a SOCKS5 proxy and sends the specifies the final
1599  * desitination server.
1600  */
1601 static int handleSock5Proxy(const char *proxy_name,
1602                             const char *proxy_password,
1603                             struct connectdata *conn)
1604 {
1605   /*
1606     According to the RFC1928, section "6.  Replies". This is what a SOCK5
1607     replies:
1608
1609         +----+-----+-------+------+----------+----------+
1610         |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
1611         +----+-----+-------+------+----------+----------+
1612         | 1  |  1  | X'00' |  1   | Variable |    2     |
1613         +----+-----+-------+------+----------+----------+
1614
1615     Where:
1616
1617     o  VER    protocol version: X'05'
1618     o  REP    Reply field:
1619     o  X'00' succeeded
1620   */
1621
1622   unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
1623   ssize_t actualread;
1624   ssize_t written;
1625   int result;
1626   CURLcode code;
1627   int sock = conn->sock[FIRSTSOCKET];
1628
1629   Curl_nonblock(sock, FALSE);
1630
1631   socksreq[0] = 5; /* version */
1632   socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
1633   socksreq[2] = 0; /* no authentication */
1634   socksreq[3] = 2; /* username/password */
1635
1636   code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
1637                       &written);
1638   if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
1639     failf(conn->data, "Unable to send initial SOCKS5 request.");
1640     return 1;
1641   }
1642
1643   result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
1644   if ((result != CURLE_OK) || (actualread != 2)) {
1645     failf(conn->data, "Unable to receive initial SOCKS5 response.");
1646     return 1;
1647   }
1648
1649   if (socksreq[0] != 5) {
1650     failf(conn->data, "Received invalid version in initial SOCKS5 response.");
1651     return 1;
1652   }
1653   if (socksreq[1] == 0) {
1654     /* Nothing to do, no authentication needed */
1655     ;
1656   }
1657   else if (socksreq[1] == 2) {
1658     /* Needs user name and password */
1659     int userlen, pwlen, len;
1660
1661     userlen = strlen(proxy_name);
1662     pwlen = proxy_password?strlen(proxy_password):0;
1663
1664     /*   username/password request looks like
1665      * +----+------+----------+------+----------+
1666      * |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
1667      * +----+------+----------+------+----------+
1668      * | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
1669      * +----+------+----------+------+----------+
1670      */
1671     len = 0;
1672     socksreq[len++] = 1;    /* username/pw subnegotiation version */
1673     socksreq[len++] = (char) userlen;
1674     memcpy(socksreq + len, proxy_name, (int) userlen);
1675     len += userlen;
1676     socksreq[len++] = (char) pwlen;
1677     memcpy(socksreq + len, proxy_password, (int) pwlen);
1678     len += pwlen;
1679
1680     code = Curl_write(conn, sock, (char *)socksreq, len, &written);
1681     if ((code != CURLE_OK) || (len != written)) {
1682       failf(conn->data, "Failed to send SOCKS5 sub-negotiation request.");
1683       return 1;
1684     }
1685
1686     result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
1687     if ((result != CURLE_OK) || (actualread != 2)) {
1688       failf(conn->data, "Unable to receive SOCKS5 sub-negotiation response.");
1689       return 1;
1690     }
1691
1692     if ((socksreq[0] != 5) || /* version */
1693         (socksreq[1] != 0)) { /* status */
1694       failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).",
1695             socksreq[0], socksreq[1]);
1696       return 1;
1697     }
1698
1699     /* Everything is good so far, user was authenticated! */
1700   }
1701   else {
1702     /* error */
1703     if (socksreq[1] == 1) {
1704       failf(conn->data,
1705             "SOCKS5 GSSAPI per-message authentication is not supported.");
1706       return 1;
1707     }
1708     else if (socksreq[1] == 255) {
1709       if (proxy_name[0] == 0) {
1710         failf(conn->data,
1711               "No authentication method was acceptable. (It is quite likely"
1712               " that the SOCKS5 server wanted a username/password, since none"
1713               " was supplied to the server on this connection.)");
1714       }
1715       else {
1716         failf(conn->data, "No authentication method was acceptable.");
1717       }
1718       return 1;
1719     }
1720     else {
1721       failf(conn->data,
1722             "Undocumented SOCKS5 mode attempted to be used by server.");
1723       return 1;
1724     }
1725   }
1726
1727   /* Authentication is complete, now specify destination to the proxy */
1728   socksreq[0] = 5; /* version (SOCKS5) */
1729   socksreq[1] = 1; /* connect */
1730   socksreq[2] = 0; /* must be zero */
1731   socksreq[3] = 1; /* IPv4 = 1 */
1732
1733   {
1734 #ifndef ENABLE_IPV6
1735     struct Curl_dns_entry *dns;
1736     Curl_addrinfo *hp=NULL;
1737     int rc = Curl_resolv(conn, conn->hostname, conn->remote_port, &dns);
1738     
1739     if(rc == -1)
1740       return 1;
1741
1742     if(rc == 1)
1743       /* this requires that we're in "wait for resolve" state */
1744       rc = Curl_wait_for_resolv(conn, &dns);
1745     
1746     /*
1747      * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
1748      * returns a Curl_addrinfo pointer that may not always look the same.
1749      */
1750     if(dns)
1751       hp=dns->addr;
1752     if (hp && hp->h_addr_list[0]) {
1753       socksreq[4] = ((char*)hp->h_addr_list[0])[0];
1754       socksreq[5] = ((char*)hp->h_addr_list[0])[1];
1755       socksreq[6] = ((char*)hp->h_addr_list[0])[2];
1756       socksreq[7] = ((char*)hp->h_addr_list[0])[3];
1757
1758       Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
1759     }
1760     else {
1761       failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
1762             conn->hostname);
1763       return 1;
1764     }
1765 #else
1766     failf(conn->data,
1767           "%s:%d has an internal error an needs to be fixed to work",
1768           __FILE__, __LINE__);
1769     return 1;
1770 #endif
1771   }
1772
1773   *((unsigned short*)&socksreq[8]) = htons(conn->remote_port);
1774
1775   {
1776     const int packetsize = 10;
1777
1778     code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
1779     if ((code != CURLE_OK) || (written != packetsize)) {
1780       failf(conn->data, "Failed to send SOCKS5 connect request.");
1781       return 1;
1782     }
1783
1784     result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread);
1785     if ((result != CURLE_OK) || (actualread != packetsize)) {
1786       failf(conn->data, "Failed to receive SOCKS5 connect request ack.");
1787       return 1;
1788     }
1789
1790     if (socksreq[0] != 5) { /* version */
1791       failf(conn->data,
1792             "SOCKS5 reply has wrong version, version should be 5.");
1793       return 1;
1794     }
1795     if (socksreq[1] != 0) { /* Anything besides 0 is an error */
1796         failf(conn->data,
1797               "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
1798               (unsigned char)socksreq[4], (unsigned char)socksreq[5],
1799               (unsigned char)socksreq[6], (unsigned char)socksreq[7],
1800               (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
1801               socksreq[1]);
1802         return 1;
1803     }
1804   }
1805
1806   Curl_nonblock(sock, TRUE);
1807   return 0; /* Proxy was successful! */
1808 }
1809
1810 static CURLcode ConnectPlease(struct connectdata *conn,
1811                               struct Curl_dns_entry *hostaddr,
1812                               bool *connected)
1813 {
1814   CURLcode result;
1815   Curl_ipconnect *addr;
1816
1817   /*************************************************************
1818    * Connect to server/proxy
1819    *************************************************************/
1820   result= Curl_connecthost(conn,
1821                            hostaddr,
1822                            conn->port,
1823                            &conn->sock[FIRSTSOCKET],
1824                            &addr,
1825                            connected);
1826   if(CURLE_OK == result) {
1827     /* All is cool, then we store the current information from the hostaddr
1828        struct to the serv_addr, as it might be needed later. The address
1829        returned from the function above is crucial here. */
1830     conn->connect_addr = hostaddr;
1831
1832 #ifdef ENABLE_IPV6
1833     conn->serv_addr = addr;
1834 #else
1835     memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
1836     memcpy((char *)&(conn->serv_addr.sin_addr),
1837            (struct in_addr *)addr, sizeof(struct in_addr));
1838     conn->serv_addr.sin_family = hostaddr->addr->h_addrtype;
1839     conn->serv_addr.sin_port = htons((unsigned short)conn->port);
1840 #endif
1841
1842     if (conn->data->set.proxytype == CURLPROXY_SOCKS5) {
1843       return handleSock5Proxy(conn->proxyuser,
1844                               conn->proxypasswd,
1845                               conn) ?
1846         CURLE_COULDNT_CONNECT : CURLE_OK;
1847     }
1848     else if (conn->data->set.proxytype == CURLPROXY_HTTP) {
1849       /* do nothing here. handled later. */
1850     }
1851     else {
1852       failf(conn->data, "unknown proxytype option given");
1853       return CURLE_COULDNT_CONNECT;
1854     }
1855   }
1856
1857   return result;
1858 }
1859
1860 /*
1861  * ALERT! The 'dns' pointer being passed in here might be NULL at times.
1862  */
1863 static void verboseconnect(struct connectdata *conn,
1864                            struct Curl_dns_entry *dns)
1865 {
1866   struct SessionHandle *data = conn->data;
1867
1868   /* Figure out the ip-number and display the first host name it shows: */
1869 #ifdef ENABLE_IPV6
1870   {
1871     char hbuf[NI_MAXHOST];
1872 #ifdef NI_WITHSCOPEID
1873 #define NIFLAGS NI_NUMERICHOST | NI_WITHSCOPEID
1874 #else
1875 #define NIFLAGS NI_NUMERICHOST
1876 #endif
1877     if(dns) {
1878       struct addrinfo *ai = dns->addr;
1879
1880       /* Lookup the name of the given address. This should probably be remade
1881          to use the DNS cache instead, as the host name is most likely cached
1882          already. */
1883       if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
1884                       NIFLAGS)) {
1885         snprintf(hbuf, sizeof(hbuf), "unknown");
1886       }
1887       else {
1888         if (ai->ai_canonname) {
1889           infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
1890                 conn->port);
1891           return;
1892         }
1893       }
1894     }
1895     else {
1896       snprintf(hbuf, sizeof(hbuf), "same host");
1897     }
1898
1899     infof(data, "Connected to %s port %d\n", hbuf, conn->port);
1900   }
1901 #else
1902   {
1903 #ifdef HAVE_INET_NTOA_R
1904     char ntoa_buf[64];
1905 #endif
1906     Curl_addrinfo *hostaddr=dns?dns->addr:NULL;
1907     struct in_addr in;
1908     (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
1909     infof(data, "Connected to %s (%s) port %d\n",
1910           hostaddr?hostaddr->h_name:"",
1911 #if defined(HAVE_INET_NTOA_R)
1912           inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)),
1913 #else
1914           inet_ntoa(in),
1915 #endif
1916           conn->port);
1917   }
1918 #endif
1919 }
1920
1921 /*
1922  * We have discovered that the TCP connection has been successful, we can now
1923  * proceed with some action.
1924  *
1925  * If we're using the multi interface, this host address pointer is most
1926  * likely NULL at this point as we can't keep the resolved info around. This
1927  * may call for some reworking, like a reference counter in the struct or
1928  * something. The hostaddr is not used for very much though, we have the
1929  * 'serv_addr' field in the connectdata struct for most of it.
1930  */
1931 CURLcode Curl_protocol_connect(struct connectdata *conn,
1932                                struct Curl_dns_entry *hostaddr)
1933 {
1934   struct SessionHandle *data = conn->data;
1935   CURLcode result=CURLE_OK;
1936
1937   if(conn->bits.tcpconnect)
1938     /* We already are connected, get back. This may happen when the connect
1939        worked fine in the first call, like when we connect to a local server
1940        or proxy. */
1941     return CURLE_OK;
1942
1943   Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
1944
1945   if(data->set.verbose)
1946     verboseconnect(conn, hostaddr);
1947
1948   if(conn->curl_connect) {
1949     /* is there a protocol-specific connect() procedure? */
1950
1951     /* set start time here for timeout purposes in the
1952      * connect procedure, it is later set again for the
1953      * progress meter purpose */
1954     conn->now = Curl_tvnow();
1955
1956     /* Call the protocol-specific connect function */
1957     result = conn->curl_connect(conn);
1958   }
1959
1960   return result; /* pass back status */
1961 }
1962
1963 /*
1964  * CreateConnection() sets up a new connectdata struct, or re-uses an already
1965  * existing one, and resolves host name.
1966  *
1967  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
1968  * response will be coming asynchronously. If *async is FALSE, the name is
1969  * already resolved.
1970  */
1971
1972 static CURLcode CreateConnection(struct SessionHandle *data,
1973                                  struct connectdata **in_connect,
1974                                  struct Curl_dns_entry **addr,
1975                                  bool *async)
1976 {
1977   char *tmp;
1978   CURLcode result=CURLE_OK;
1979   char resumerange[40]="";
1980   struct connectdata *conn;
1981   struct connectdata *conn_temp;
1982   int urllen;
1983   struct Curl_dns_entry *hostaddr;
1984 #ifdef HAVE_ALARM
1985   unsigned int prev_alarm=0;
1986 #endif
1987   char endbracket;
1988   char user[MAX_CURL_USER_LENGTH];
1989   char passwd[MAX_CURL_PASSWORD_LENGTH];
1990   int rc;
1991   bool reuse;
1992
1993 #ifdef HAVE_SIGACTION
1994   struct sigaction keep_sigact;   /* store the old struct here */
1995   bool keep_copysig=FALSE;        /* did copy it? */
1996 #else
1997 #ifdef HAVE_SIGNAL
1998   void *keep_sigact;              /* store the old handler here */
1999 #endif
2000 #endif
2001
2002   *addr = NULL; /* nothing yet */
2003   *async = FALSE;
2004   
2005   /*************************************************************
2006    * Check input data
2007    *************************************************************/
2008
2009   if(!data->change.url)
2010     return CURLE_URL_MALFORMAT;
2011
2012   /* First, split up the current URL in parts so that we can use the
2013      parts for checking against the already present connections. In order
2014      to not have to modify everything at once, we allocate a temporary
2015      connection data struct and fill in for comparison purposes. */
2016
2017   conn = (struct connectdata *)malloc(sizeof(struct connectdata));
2018   if(!conn) {
2019     *in_connect = NULL; /* clear the pointer */
2020     return CURLE_OUT_OF_MEMORY;
2021   }
2022   /* We must set the return variable as soon as possible, so that our
2023      parent can cleanup any possible allocs we may have done before
2024      any failure */
2025   *in_connect = conn;
2026
2027   /* we have to init the struct */
2028   memset(conn, 0, sizeof(struct connectdata));
2029
2030   /* and we setup a few fields in case we end up actually using this struct */
2031   conn->data = data;           /* remember our daddy */
2032   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
2033   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
2034   conn->connectindex = -1;    /* no index */
2035   conn->bits.httpproxy = (data->change.proxy && *data->change.proxy &&
2036                           (data->set.proxytype == CURLPROXY_HTTP))?
2037     TRUE:FALSE; /* http proxy or not */
2038
2039   /* Default protocol-independent behavior doesn't support persistant
2040      connections, so we set this to force-close. Protocols that support
2041      this need to set this to FALSE in their "curl_do" functions. */
2042   conn->bits.close = TRUE;
2043
2044   /* maxdownload must be -1 on init, as 0 is a valid value! */
2045   conn->maxdownload = -1;  /* might have been used previously! */
2046
2047   /* Store creation time to help future close decision making */
2048   conn->created = Curl_tvnow();
2049
2050   conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */
2051   conn->range = data->set.set_range;              /* clone the range setting */
2052   conn->resume_from = data->set.set_resume_from;   /* inherite resume_from */
2053
2054   /* Set the start time temporary to this creation time to allow easier
2055      timeout checks before the transfer has started for real. The start time
2056      is later set "for real" using Curl_pgrsStartNow(). */
2057   conn->data->progress.start = conn->created;
2058
2059   conn->bits.user_passwd = data->set.userpwd?1:0;
2060   conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
2061
2062   /* This initing continues below, see the comment "Continue connectdata
2063    * initialization here" */
2064
2065   /***********************************************************
2066    * We need to allocate memory to store the path in. We get the size of the
2067    * full URL to be sure, and we need to make it at least 256 bytes since
2068    * other parts of the code will rely on this fact
2069    ***********************************************************/
2070 #define LEAST_PATH_ALLOC 256
2071   urllen=strlen(data->change.url);
2072   if(urllen < LEAST_PATH_ALLOC)
2073     urllen=LEAST_PATH_ALLOC;
2074
2075   conn->path=(char *)malloc(urllen);
2076   if(NULL == conn->path)
2077     return CURLE_OUT_OF_MEMORY; /* really bad error */
2078
2079   /*************************************************************
2080    * Parse the URL.
2081    *
2082    * We need to parse the url even when using the proxy, because we will need
2083    * the hostname and port in case we are trying to SSL connect through the
2084    * proxy -- and we don't know if we will need to use SSL until we parse the
2085    * url ...
2086    ************************************************************/
2087   if((2 == sscanf(data->change.url, "%64[^:]:%[^\n]",
2088                   conn->protostr,
2089                   conn->path)) && strequal(conn->protostr, "file")) {
2090     if(conn->path[0] == '/' && conn->path[1] == '/') {
2091       /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
2092        * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
2093        * file://localhost/<path> is similar to how other schemes treat missing
2094        * hostnames.  See RFC 1808. */
2095
2096       /* This cannot be done with strcpy() in a portable manner, since the
2097          memory areas overlap! */
2098       memmove(conn->path, conn->path + 2, strlen(conn->path + 2)+1);
2099     }
2100     /*
2101      * we deal with file://<host>/<path> differently since it supports no
2102      * hostname other than "localhost" and "127.0.0.1", which is unique among
2103      * the URL protocols specified in RFC 1738
2104      */
2105     if(conn->path[0] != '/') {
2106       /* the URL included a host name, we ignore host names in file:// URLs
2107          as the standards don't define what to do with them */
2108       char *ptr=strchr(conn->path, '/');
2109       if(ptr) {
2110         /* there was a slash present
2111
2112            RFC1738 (section 3.1, page 5) says:
2113
2114            The rest of the locator consists of data specific to the scheme,
2115            and is known as the "url-path". It supplies the details of how the
2116            specified resource can be accessed. Note that the "/" between the
2117            host (or port) and the url-path is NOT part of the url-path.
2118
2119            As most agents use file://localhost/foo to get '/foo' although the
2120            slash preceeding foo is a separator and not a slash for the path,
2121            a URL as file://localhost//foo must be valid as well, to refer to
2122            the same file with an absolute path.
2123         */
2124
2125         if(ptr[1] && ('/' == ptr[1]))
2126           /* if there was two slashes, we skip the first one as that is then
2127              used truly as a separator */
2128           ptr++;
2129
2130         /* This cannot be made with strcpy, as the memory chunks overlap! */
2131         memmove(conn->path, ptr, strlen(ptr)+1);
2132       }
2133     }
2134
2135     strcpy(conn->protostr, "file"); /* store protocol string lowercase */
2136   }
2137   else {
2138     /* Set default host and default path */
2139     strcpy(conn->gname, "curl.haxx.se");
2140     strcpy(conn->path, "/");
2141     /* We need to search for '/' OR '?' - whichever comes first after host
2142      * name but before the path. We need to change that to handle things like
2143      * http://example.com?param= (notice the missing '/'). Later we'll insert
2144      * that missing slash at the beginning of the path.
2145      */
2146     if (2 > sscanf(data->change.url,
2147                    "%64[^\n:]://%512[^\n/?]%[^\n]",
2148                    conn->protostr, conn->gname, conn->path)) {
2149
2150       /*
2151        * The URL was badly formatted, let's try the browser-style _without_
2152        * protocol specified like 'http://'.
2153        */
2154       if((1 > sscanf(data->change.url, "%512[^\n/?]%[^\n]",
2155                      conn->gname, conn->path)) ) {
2156         /*
2157          * We couldn't even get this format.
2158          */
2159         failf(data, "<url> malformed");
2160         return CURLE_URL_MALFORMAT;
2161       }
2162
2163       /*
2164        * Since there was no protocol part specified, we guess what protocol it
2165        * is based on the first letters of the server name.
2166        */
2167
2168       /* Note: if you add a new protocol, please update the list in
2169        * lib/version.c too! */
2170
2171       if(checkprefix("GOPHER", conn->gname))
2172         strcpy(conn->protostr, "gopher");
2173 #ifdef USE_SSLEAY
2174       else if(checkprefix("HTTPS", conn->gname))
2175         strcpy(conn->protostr, "https");
2176       else if(checkprefix("FTPS", conn->gname))
2177         strcpy(conn->protostr, "ftps");
2178 #endif /* USE_SSLEAY */
2179       else if(checkprefix("FTP", conn->gname))
2180         strcpy(conn->protostr, "ftp");
2181       else if(checkprefix("TELNET", conn->gname))
2182         strcpy(conn->protostr, "telnet");
2183       else if (checkprefix("DICT", conn->gname))
2184         strcpy(conn->protostr, "DICT");
2185       else if (checkprefix("LDAP", conn->gname))
2186         strcpy(conn->protostr, "LDAP");
2187       else {
2188         strcpy(conn->protostr, "http");
2189       }
2190
2191       conn->protocol |= PROT_MISSING; /* not given in URL */
2192     }
2193   }
2194
2195   /* If the URL is malformatted (missing a '/' after hostname before path) we
2196    * insert a slash here. The only letter except '/' we accept to start a path
2197    * is '?'.
2198    */
2199   if(conn->path[0] == '?') {
2200     /* We need this function to deal with overlapping memory areas. We know
2201        that the memory area 'path' points to is 'urllen' bytes big and that
2202        is bigger than the path. Use +1 to move the zero byte too. */
2203     memmove(&conn->path[1], conn->path, strlen(conn->path)+1);
2204     conn->path[0] = '/';
2205   }
2206
2207   /*
2208    * So if the URL was A://B/C,
2209    *   conn->protostr is A
2210    *   conn->gname is B
2211    *   conn->path is /C
2212    */
2213
2214   /*************************************************************
2215    * Take care of proxy authentication stuff
2216    *************************************************************/
2217   if(conn->bits.proxy_user_passwd) {
2218     char proxyuser[MAX_CURL_USER_LENGTH]="";
2219     char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
2220
2221     sscanf(data->set.proxyuserpwd,
2222            "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
2223            "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
2224            proxyuser, proxypasswd);
2225
2226     conn->proxyuser = strdup(proxyuser);
2227     if(!conn->proxyuser)
2228       return CURLE_OUT_OF_MEMORY;
2229     
2230     conn->proxypasswd = strdup(proxypasswd);
2231     if(!conn->proxypasswd)
2232       return CURLE_OUT_OF_MEMORY;
2233   }
2234
2235   /*************************************************************
2236    * Set a few convenience pointers
2237    *************************************************************/
2238   conn->name = conn->gname;
2239   conn->ppath = conn->path;
2240   conn->hostname = conn->name;
2241
2242   /*************************************************************
2243    * Detect what (if any) proxy to use
2244    *************************************************************/
2245   if(!data->change.proxy) {
2246     /* If proxy was not specified, we check for default proxy environment
2247      * variables, to enable i.e Lynx compliance:
2248      *
2249      * http_proxy=http://some.server.dom:port/
2250      * https_proxy=http://some.server.dom:port/
2251      * ftp_proxy=http://some.server.dom:port/
2252      * gopher_proxy=http://some.server.dom:port/
2253      * no_proxy=domain1.dom,host.domain2.dom
2254      *   (a comma-separated list of hosts which should
2255      *   not be proxied, or an asterisk to override
2256      *   all proxy variables)
2257      * all_proxy=http://some.server.dom:port/
2258      *   (seems to exist for the CERN www lib. Probably
2259      *   the first to check for.)
2260      *
2261      * For compatibility, the all-uppercase versions of these variables are
2262      * checked if the lowercase versions don't exist.
2263      */
2264     char *no_proxy=NULL;
2265     char *no_proxy_tok_buf;
2266     char *proxy=NULL;
2267     char proxy_env[128];
2268
2269     no_proxy=curl_getenv("no_proxy");
2270     if(!no_proxy)
2271       no_proxy=curl_getenv("NO_PROXY");
2272
2273     if(!no_proxy || !strequal("*", no_proxy)) {
2274       /* NO_PROXY wasn't specified or it wasn't just an asterisk */
2275       char *nope;
2276
2277       nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
2278       while(nope) {
2279         unsigned int namelen;
2280         char *endptr = strchr(conn->name, ':');
2281         if(endptr)
2282           namelen=endptr-conn->name;
2283         else
2284           namelen=strlen(conn->name);
2285
2286         if(strlen(nope) <= namelen) {
2287           char *checkn=
2288             conn->name + namelen - strlen(nope);
2289           if(checkprefix(nope, checkn)) {
2290             /* no proxy for this host! */
2291             break;
2292           }
2293         }
2294         nope=strtok_r(NULL, ", ", &no_proxy_tok_buf);
2295       }
2296       if(!nope) {
2297         /* It was not listed as without proxy */
2298         char *protop = conn->protostr;
2299         char *envp = proxy_env;
2300         char *prox;
2301
2302         /* Now, build <protocol>_proxy and check for such a one to use */
2303         while(*protop)
2304           *envp++ = tolower(*protop++);
2305
2306         /* append _proxy */
2307         strcpy(envp, "_proxy");
2308
2309         /* read the protocol proxy: */
2310         prox=curl_getenv(proxy_env);
2311
2312         /*
2313          * We don't try the uppercase version of HTTP_PROXY because of
2314          * security reasons:
2315          *
2316          * When curl is used in a webserver application
2317          * environment (cgi or php), this environment variable can
2318          * be controlled by the web server user by setting the
2319          * http header 'Proxy:' to some value.
2320          *
2321          * This can cause 'internal' http/ftp requests to be
2322          * arbitrarily redirected by any external attacker.
2323          */
2324         if(!prox && !strequal("http_proxy", proxy_env)) {
2325           /* There was no lowercase variable, try the uppercase version: */
2326           for(envp = proxy_env; *envp; envp++)
2327             *envp = toupper(*envp);
2328           prox=curl_getenv(proxy_env);
2329         }
2330
2331         if(prox && *prox) { /* don't count "" strings */
2332           proxy = prox; /* use this */
2333         }
2334         else {
2335           proxy = curl_getenv("all_proxy"); /* default proxy to use */
2336           if(!proxy)
2337             proxy=curl_getenv("ALL_PROXY");
2338         }
2339
2340         if(proxy && *proxy) {
2341           /* we have a proxy here to set */
2342           char *ptr;
2343           char proxyuser[MAX_CURL_USER_LENGTH];
2344           char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
2345
2346           /* skip the possible protocol piece */
2347           ptr=strstr(proxy, "://");
2348           if(ptr)
2349             ptr += 3;
2350           else
2351             ptr = proxy;
2352
2353           /* check for an @-letter */
2354           ptr = strchr(ptr, '@');
2355           if(ptr && (2 == sscanf(proxy, "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
2356                                  "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
2357                                  proxyuser, proxypasswd))) {
2358             /* found user and password, rip them out */
2359             Curl_safefree(conn->proxyuser);
2360             conn->proxyuser = strdup(proxyuser);
2361
2362             if(!conn->proxyuser)
2363               return CURLE_OUT_OF_MEMORY;
2364             
2365             Curl_safefree(conn->proxypasswd);
2366             conn->proxypasswd = strdup(proxypasswd);
2367
2368             if(!conn->proxypasswd)
2369               return CURLE_OUT_OF_MEMORY;
2370             
2371             conn->bits.proxy_user_passwd = TRUE; /* enable it */
2372
2373             ptr = strdup(ptr+1);
2374             free(proxy); /* free the former data */
2375             proxy = ptr; /* now use this instead */
2376           }
2377
2378
2379           data->change.proxy = proxy;
2380           data->change.proxy_alloc=TRUE; /* this needs to be freed later */
2381           conn->bits.httpproxy = TRUE;
2382         }
2383       } /* if (!nope) - it wasn't specified non-proxy */
2384     } /* NO_PROXY wasn't specified or '*' */
2385     if(no_proxy)
2386       free(no_proxy);
2387   } /* if not using proxy */
2388
2389   /*************************************************************
2390    * No protocol part in URL was used, add it!
2391    *************************************************************/
2392   if(conn->protocol&PROT_MISSING) {
2393     /* We're guessing prefixes here and if we're told to use a proxy or if
2394        we're gonna follow a Location: later or... then we need the protocol
2395        part added so that we have a valid URL. */
2396     char *reurl;
2397
2398     reurl = aprintf("%s://%s", conn->protostr, data->change.url);
2399
2400     if(!reurl)
2401       return CURLE_OUT_OF_MEMORY;
2402
2403     data->change.url = reurl;
2404     data->change.url_alloc = TRUE; /* free this later */
2405     conn->protocol &= ~PROT_MISSING; /* switch that one off again */
2406   }
2407
2408 #ifndef CURL_DISABLE_HTTP
2409   /************************************************************
2410    * RESUME on a HTTP page is a tricky business. First, let's just check that
2411    * 'range' isn't used, then set the range parameter and leave the resume as
2412    * it is to inform about this situation for later use. We will then
2413    * "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
2414    * server, we will get the document resumed. If we talk to a HTTP/1.0
2415    * server, we just fail since we can't rewind the file writing from within
2416    * this function.
2417    ***********************************************************/
2418   if(conn->resume_from) {
2419     if(!conn->bits.use_range) {
2420       /* if it already was in use, we just skip this */
2421       snprintf(resumerange, sizeof(resumerange), "%" FORMAT_OFF_T "-",
2422                conn->resume_from);
2423       conn->range=strdup(resumerange); /* tell ourselves to fetch this range */
2424       conn->bits.rangestringalloc = TRUE; /* mark as allocated */
2425       conn->bits.use_range = 1; /* switch on range usage */
2426     }
2427   }
2428 #endif
2429   /*************************************************************
2430    * Setup internals depending on protocol
2431    *************************************************************/
2432
2433   if (strequal(conn->protostr, "HTTP")) {
2434 #ifndef CURL_DISABLE_HTTP
2435     conn->port = (data->set.use_port && data->state.allow_port)?
2436       data->set.use_port:PORT_HTTP;
2437     conn->remote_port = PORT_HTTP;
2438     conn->protocol |= PROT_HTTP;
2439     conn->curl_do = Curl_http;
2440     conn->curl_do_more = NULL;
2441     conn->curl_done = Curl_http_done;
2442     conn->curl_connect = Curl_http_connect;
2443 #else
2444     failf(data, LIBCURL_NAME
2445           " was built with HTTP disabled, http: not supported!");
2446     return CURLE_UNSUPPORTED_PROTOCOL;
2447 #endif
2448   }
2449   else if (strequal(conn->protostr, "HTTPS")) {
2450 #if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP)
2451
2452     conn->port = (data->set.use_port && data->state.allow_port)?
2453       data->set.use_port:PORT_HTTPS;
2454     conn->remote_port = PORT_HTTPS;
2455     conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
2456
2457     conn->curl_do = Curl_http;
2458     conn->curl_do_more = NULL;
2459     conn->curl_done = Curl_http_done;
2460     conn->curl_connect = Curl_http_connect;
2461
2462 #else /* USE_SSLEAY */
2463     failf(data, LIBCURL_NAME
2464           " was built with SSL disabled, https: not supported!");
2465     return CURLE_UNSUPPORTED_PROTOCOL;
2466 #endif /* !USE_SSLEAY */
2467   }
2468   else if (strequal(conn->protostr, "GOPHER")) {
2469 #ifndef CURL_DISABLE_GOPHER
2470     conn->port = (data->set.use_port && data->state.allow_port)?
2471       data->set.use_port:PORT_GOPHER;
2472     conn->remote_port = PORT_GOPHER;
2473     /* Skip /<item-type>/ in path if present */
2474     if (isdigit((int)conn->path[1])) {
2475       conn->ppath = strchr(&conn->path[1], '/');
2476       if (conn->ppath == NULL)
2477         conn->ppath = conn->path;
2478       }
2479     conn->protocol |= PROT_GOPHER;
2480     conn->curl_do = Curl_http;
2481     conn->curl_do_more = NULL;
2482     conn->curl_done = Curl_http_done;
2483 #else
2484     failf(data, LIBCURL_NAME
2485           " was built with GOPHER disabled, gopher: not supported!");
2486 #endif
2487   }
2488   else if(strequal(conn->protostr, "FTP") ||
2489           strequal(conn->protostr, "FTPS")) {
2490
2491 /* MN 06/07/02 */
2492 #ifndef CURL_DISABLE_FTP
2493     char *type;
2494     int port = PORT_FTP;
2495
2496     if(strequal(conn->protostr, "FTPS")) {
2497 #ifdef USE_SSLEAY
2498       conn->protocol |= PROT_FTPS|PROT_SSL;
2499       conn->ssl[SECONDARYSOCKET].use = TRUE; /* send data securely */
2500       port = PORT_FTPS;
2501 #else
2502       failf(data, LIBCURL_NAME
2503             " was built with SSL disabled, ftps: not supported!");
2504       return CURLE_UNSUPPORTED_PROTOCOL;
2505 #endif /* !USE_SSLEAY */
2506     }
2507
2508     conn->port = (data->set.use_port && data->state.allow_port)?
2509       data->set.use_port:port;
2510     conn->remote_port = port;
2511     conn->protocol |= PROT_FTP;
2512
2513     if(data->change.proxy &&
2514        *data->change.proxy &&
2515        !data->set.tunnel_thru_httpproxy) {
2516       /* Unless we have asked to tunnel ftp operations through the proxy, we
2517          switch and use HTTP operations only */
2518       if(conn->protocol & PROT_FTPS) {
2519         /* FTPS is a hacked protocol and does not work through your
2520            ordinary http proxy! */
2521         failf(data, "ftps does not work through http proxy!");
2522         return CURLE_UNSUPPORTED_PROTOCOL;
2523       }
2524 #ifndef CURL_DISABLE_HTTP
2525       conn->curl_do = Curl_http;
2526       conn->curl_done = Curl_http_done;
2527 #else
2528       failf(data, "FTP over http proxy requires HTTP support built-in!");
2529       return CURLE_UNSUPPORTED_PROTOCOL;
2530 #endif
2531     }
2532     else {
2533       conn->curl_do = Curl_ftp;
2534       conn->curl_do_more = Curl_ftp_nextconnect;
2535       conn->curl_done = Curl_ftp_done;
2536       conn->curl_connect = Curl_ftp_connect;
2537       conn->curl_disconnect = Curl_ftp_disconnect;
2538     }
2539
2540     conn->ppath++; /* don't include the initial slash */
2541
2542     /* FTP URLs support an extension like ";type=<typecode>" that
2543      * we'll try to get now! */
2544     type=strstr(conn->ppath, ";type=");
2545     if(!type) {
2546       type=strstr(conn->gname, ";type=");
2547     }
2548     if(type) {
2549       char command;
2550       *type=0;                     /* it was in the middle of the hostname */
2551       command = toupper(type[6]);
2552       switch(command) {
2553       case 'A': /* ASCII mode */
2554         data->set.ftp_ascii = 1;
2555         break;
2556       case 'D': /* directory mode */
2557         data->set.ftp_list_only = 1;
2558         break;
2559       case 'I': /* binary mode */
2560       default:
2561         /* switch off ASCII */
2562         data->set.ftp_ascii = 0;
2563         break;
2564       }
2565     }
2566
2567 /* MN 06/07/02 */
2568 #else /* CURL_DISABLE_FTP */
2569     failf(data, LIBCURL_NAME
2570           " was built with FTP disabled, ftp/ftps: not supported!");
2571     return CURLE_UNSUPPORTED_PROTOCOL;
2572 #endif
2573   }
2574   else if(strequal(conn->protostr, "TELNET")) {
2575 #ifndef CURL_DISABLE_TELNET
2576     /* telnet testing factory */
2577     conn->protocol |= PROT_TELNET;
2578
2579     conn->port = (data->set.use_port && data->state.allow_port)?
2580       data->set.use_port: PORT_TELNET;
2581     conn->remote_port = PORT_TELNET;
2582     conn->curl_do = Curl_telnet;
2583     conn->curl_done = Curl_telnet_done;
2584 #else
2585     failf(data, LIBCURL_NAME
2586           " was built with TELNET disabled!");
2587 #endif
2588   }
2589   else if (strequal(conn->protostr, "DICT")) {
2590 #ifndef CURL_DISABLE_DICT
2591     conn->protocol |= PROT_DICT;
2592     conn->port = (data->set.use_port && data->state.allow_port)?
2593       data->set.use_port:PORT_DICT;
2594     conn->remote_port = PORT_DICT;
2595     conn->curl_do = Curl_dict;
2596     conn->curl_done = NULL; /* no DICT-specific done */
2597 #else
2598     failf(data, LIBCURL_NAME
2599           " was built with DICT disabled!");
2600 #endif
2601   }
2602   else if (strequal(conn->protostr, "LDAP")) {
2603 #ifndef CURL_DISABLE_LDAP
2604     conn->protocol |= PROT_LDAP;
2605     conn->port = (data->set.use_port && data->state.allow_port)?
2606       data->set.use_port:PORT_LDAP;
2607     conn->remote_port = PORT_LDAP;
2608     conn->curl_do = Curl_ldap;
2609     conn->curl_done = NULL; /* no LDAP-specific done */
2610 #else
2611     failf(data, LIBCURL_NAME
2612           " was built with LDAP disabled!");
2613 #endif
2614   }
2615   else if (strequal(conn->protostr, "FILE")) {
2616 #ifndef CURL_DISABLE_FILE
2617     conn->protocol |= PROT_FILE;
2618
2619     conn->curl_do = Curl_file;
2620     /* no done() function */
2621
2622     /* anyway, this is supposed to be the connect function so we better
2623        at least check that the file is present here! */
2624     result = Curl_file_connect(conn);
2625
2626     /* Setup a "faked" transfer that'll do nothing */
2627     if(CURLE_OK == result) {
2628       conn->bits.tcpconnect = TRUE; /* we are "connected */
2629       result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
2630                              -1, NULL); /* no upload */
2631     }
2632
2633     return result;
2634 #else
2635     failf(data, LIBCURL_NAME
2636           " was built with FILE disabled!");
2637 #endif
2638   }
2639   else {
2640     /* We fell through all checks and thus we don't support the specified
2641        protocol */
2642     failf(data, "Unsupported protocol: %s", conn->protostr);
2643     return CURLE_UNSUPPORTED_PROTOCOL;
2644   }
2645
2646   /*************************************************************
2647    * Figure out the remote port number
2648    *
2649    * No matter if we use a proxy or not, we have to figure out the remote
2650    * port number of various reasons.
2651    *
2652    * To be able to detect port number flawlessly, we must not confuse them
2653    * IPv6-specified addresses in the [0::1] style. (RFC2732)
2654    *
2655    * The conn->name is currently [user:passwd@]host[:port] where host could
2656    * be a hostname, IPv4 address or IPv6 address.
2657    *************************************************************/
2658   if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
2659      (']' == endbracket)) {
2660     /* this is a RFC2732-style specified IP-address */
2661     conn->bits.ipv6_ip = TRUE;
2662
2663     conn->name++; /* pass the starting bracket */
2664     conn->hostname++;
2665     tmp = strchr(conn->name, ']');
2666     *tmp = 0; /* zero terminate */
2667     tmp++; /* pass the ending bracket */
2668     if(':' != *tmp)
2669       tmp = NULL; /* no port number available */
2670   }
2671   else
2672     tmp = strrchr(conn->name, ':');
2673
2674   if (tmp) {
2675     char *rest;
2676     unsigned long port;
2677
2678     port=strtoul(tmp+1, &rest, 10);  /* Port number must be decimal */
2679
2680     if (rest != (tmp+1) && *rest == '\0') {
2681       /* The colon really did have only digits after it,
2682        * so it is either a port number or a mistake */
2683
2684       if (port > 0xffff) {   /* Single unix standard says port numbers are
2685                               * 16 bits long */
2686         failf(data, "Port number too large: %lu", port);
2687         return CURLE_URL_MALFORMAT;
2688       }
2689
2690       *tmp = '\0'; /* cut off the name there */
2691       conn->remote_port = (unsigned short)port;
2692     }
2693   }
2694
2695   if(data->change.proxy && *data->change.proxy) {
2696     /* If this is supposed to use a proxy, we need to figure out the proxy
2697        host name name, so that we can re-use an existing connection
2698        that may exist registered to the same proxy host. */
2699
2700     char *prox_portno;
2701     char *endofprot;
2702
2703     /* We need to make a duplicate of the proxy so that we can modify the
2704        string safely. */
2705     char *proxydup=strdup(data->change.proxy);
2706
2707     /* We use 'proxyptr' to point to the proxy name from now on... */
2708     char *proxyptr=proxydup;
2709
2710     if(NULL == proxydup) {
2711       failf(data, "memory shortage");
2712       return CURLE_OUT_OF_MEMORY;
2713     }
2714
2715     /* Daniel Dec 10, 1998:
2716        We do the proxy host string parsing here. We want the host name and the
2717        port name. Accept a protocol:// prefix, even though it should just be
2718        ignored. */
2719
2720     /* 1. skip the protocol part if present */
2721     endofprot=strstr(proxyptr, "://");
2722     if(endofprot) {
2723       proxyptr = endofprot+3;
2724     }
2725
2726     /* allow user to specify proxy.server.com:1080 if desired */
2727     prox_portno = strchr (proxyptr, ':');
2728     if (prox_portno) {
2729       *prox_portno = 0x0; /* cut off number from host name */
2730       prox_portno ++;
2731       /* now set the local port number */
2732       conn->port = atoi(prox_portno);
2733     }
2734     else if(data->set.proxyport) {
2735       /* None given in the proxy string, then get the default one if it is
2736          given */
2737       conn->port = data->set.proxyport;
2738     }
2739
2740     /* now, clone the cleaned proxy host name */
2741     conn->proxyhost = strdup(proxyptr);
2742
2743     free(proxydup); /* free the duplicate pointer and not the modified */
2744   }
2745
2746   /*************************************************************
2747    * Take care of user and password authentication stuff
2748    *************************************************************/
2749
2750   /*
2751    * Inputs: data->set.userpwd   (CURLOPT_USERPWD)
2752    *         data->set.fpasswd   (CURLOPT_PASSWDFUNCTION)
2753    *         data->set.use_netrc (CURLOPT_NETRC)
2754    *         conn->hostname
2755    *         netrc file
2756    *         hard-coded defaults
2757    *
2758    * Outputs: (almost :- all currently undefined)
2759    *          conn->bits.user_passwd  - non-zero if non-default passwords exist
2760    *          conn->user              - non-zero length if defined
2761    *          conn->passwd            -   ditto
2762    *          conn->hostname          - remove user name and password
2763    */
2764
2765   /* At this point, we're hoping all the other special cases have
2766    * been taken care of, so conn->hostname is at most
2767    *    [user[:password]]@]hostname
2768    *
2769    * We need somewhere to put the embedded details, so do that first.
2770    */
2771
2772   user[0] =0;   /* to make everything well-defined */
2773   passwd[0]=0;
2774
2775   if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
2776     /* This is a FTP or HTTP URL, we will now try to extract the possible
2777      * user+password pair in a string like:
2778      * ftp://user:password@ftp.my.site:8021/README */
2779     char *ptr=strchr(conn->name, '@');
2780     char *userpass = conn->name;
2781     if(ptr != NULL) {
2782       /* there's a user+password given here, to the left of the @ */
2783
2784       conn->name = conn->hostname = ++ptr;
2785
2786       /* So the hostname is sane.  Only bother interpreting the
2787        * results if we could care.  It could still be wasted
2788        * work because it might be overtaken by the programmatically
2789        * set user/passwd, but doing that first adds more cases here :-(
2790        */
2791
2792       if (data->set.use_netrc != CURL_NETRC_REQUIRED) {
2793         /* We could use the one in the URL */
2794
2795         conn->bits.user_passwd = 1; /* enable user+password */
2796
2797         if(*userpass != ':') {
2798           /* the name is given, get user+password */
2799           sscanf(userpass, "%127[^:@]:%127[^@]",
2800                  user, passwd);
2801         }
2802         else
2803           /* no name given, get the password only */
2804           sscanf(userpass, ":%127[^@]", passwd);
2805
2806         if(user[0]) {
2807           char *newname=curl_unescape(user, 0);
2808           if(strlen(newname) < sizeof(user)) {
2809             strcpy(user, newname);
2810           }
2811           /* if the new name is longer than accepted, then just use
2812              the unconverted name, it'll be wrong but what the heck */
2813           free(newname);
2814         }
2815         if (passwd[0]) {
2816           /* we have a password found in the URL, decode it! */
2817           char *newpasswd=curl_unescape(passwd, 0);
2818           if(strlen(newpasswd) < sizeof(passwd)) {
2819             strcpy(passwd, newpasswd);
2820           }
2821           free(newpasswd);
2822         }
2823       }
2824     }
2825   }
2826
2827   /* Programmatically set password:
2828    *   - always applies, if available
2829    *   - takes precedence over the values we just set above
2830    * so scribble it over the top.
2831    * User-supplied passwords are assumed not to need unescaping.
2832    *
2833    * user_password is set in "inherite initial knowledge' above,
2834    * so it doesn't have to be set in this block
2835    */
2836   if (data->set.userpwd != NULL) {
2837     /* the name is given, get user+password */
2838     sscanf(data->set.userpwd,
2839            "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
2840            "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
2841            user, passwd);
2842   }
2843
2844   if (data->set.use_netrc != CURL_NETRC_IGNORED) {
2845     if(Curl_parsenetrc(conn->hostname,
2846                        user, passwd,
2847                        data->set.netrc_file)) {
2848       infof(data, "Couldn't find host %s in the .netrc file, using defaults\n",
2849             conn->hostname);
2850     }
2851     else
2852       conn->bits.user_passwd = 1; /* enable user+password */
2853   }
2854
2855   /* If our protocol needs a password and we have none, use the defaults */
2856   if ( (conn->protocol & PROT_FTP) &&
2857        !conn->bits.user_passwd) {
2858
2859     conn->user = strdup(CURL_DEFAULT_USER);
2860     conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
2861
2862     /* This is the default password, so DON'T set conn->bits.user_passwd */
2863   }
2864   else {
2865     /* store user + password, zero-length if not set */
2866     conn->user = strdup(user);
2867     conn->passwd = strdup(passwd);
2868   }
2869
2870   /*************************************************************
2871    * Check the current list of connections to see if we can
2872    * re-use an already existing one or if we have to create a
2873    * new one.
2874    *************************************************************/
2875
2876   /* get a cloned copy of the SSL config situation stored in the 
2877      connection struct */
2878   if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
2879     return CURLE_OUT_OF_MEMORY;
2880
2881   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
2882      we only acknowledge this option if this is not a re-used connection
2883      already (which happens due to follow-location or during a HTTP
2884      authentication phase). */
2885   if(data->set.reuse_fresh && !data->state.this_is_a_follow)
2886     reuse = FALSE;
2887   else 
2888     reuse = ConnectionExists(data, conn, &conn_temp);
2889
2890   if(reuse) {
2891     /*
2892      * We already have a connection for this, we got the former connection
2893      * in the conn_temp variable and thus we need to cleanup the one we
2894      * just allocated before we can move along and use the previously
2895      * existing one.
2896      */
2897     struct connectdata *old_conn = conn;
2898     char *path = old_conn->path; /* setup the current path pointer properly */
2899     char *ppath = old_conn->ppath; /* this is the modified path pointer */
2900     if(old_conn->proxyhost)
2901       free(old_conn->proxyhost);
2902
2903     /* free the SSL config struct from this connection struct as this was
2904        allocated in vain and is targeted for destruction */
2905     Curl_free_ssl_config(&conn->ssl_config);
2906
2907     conn = conn_temp;        /* use this connection from now on */
2908
2909     /* get the user+password information from the old_conn struct since it may
2910      * be new for this request even when we re-use an existing connection */
2911     conn->bits.user_passwd = old_conn->bits.user_passwd;
2912     conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
2913
2914     /* If we speak over a proxy, we need to copy the host name too, as it
2915        might be another remote host even when re-using a connection */
2916     strcpy(conn->gname, old_conn->gname); /* safe strcpy() */
2917
2918     /* we need these pointers if we speak over a proxy */
2919     conn->hostname = conn->gname;
2920     conn->name = &conn->gname[old_conn->name - old_conn->gname];
2921
2922     free(conn->path);    /* free the previously allocated path pointer */
2923
2924     /* 'path' points to the allocated data, 'ppath' may have been advanced
2925        to point somewhere within the 'path' area. */
2926     conn->path = path;
2927     conn->ppath = ppath;
2928
2929     /* re-use init */
2930     conn->bits.reuse = TRUE; /* yes, we're re-using here */
2931     conn->bits.chunk = FALSE; /* always assume not chunked unless told
2932                                  otherwise */
2933     conn->maxdownload = -1;  /* might have been used previously! */
2934
2935     Curl_safefree(old_conn->user);
2936     Curl_safefree(old_conn->passwd);
2937     Curl_safefree(old_conn->proxyuser);
2938     Curl_safefree(old_conn->proxypasswd);
2939
2940     if(old_conn->bits.rangestringalloc)
2941       free(old_conn->range);
2942
2943     free(old_conn);          /* we don't need this anymore */
2944
2945     /*
2946      * If we're doing a resumed transfer, we need to setup our stuff
2947      * properly.
2948      */
2949     conn->resume_from = data->set.set_resume_from;
2950     if (conn->resume_from) {
2951       snprintf(resumerange, sizeof(resumerange), "%" FORMAT_OFF_T "-",
2952                conn->resume_from);
2953       if (conn->bits.rangestringalloc == TRUE)
2954         free(conn->range);
2955
2956       /* tell ourselves to fetch this range */
2957       conn->range = strdup(resumerange);
2958       conn->bits.use_range = TRUE;        /* enable range download */
2959       conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
2960     }
2961     else if (data->set.set_range) {
2962       /* There is a range, but is not a resume, useful for random ftp access */
2963       conn->range = strdup(data->set.set_range);
2964       conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
2965       conn->bits.use_range = TRUE;        /* enable range download */
2966     }
2967     else
2968       conn->bits.use_range = FALSE; /* disable range download */
2969
2970     *in_connect = conn;      /* return this instead! */
2971
2972     infof(data, "Re-using existing connection! (#%d)\n", conn->connectindex);
2973   }
2974   else {
2975     /*
2976      * This is a brand new connection, so let's store it in the connection
2977      * cache of ours!
2978      */
2979     ConnectionStore(data, conn);
2980   }
2981
2982   /* Continue connectdata initialization here.
2983    *
2984    * Inherit the proper values from the urldata struct AFTER we have arranged
2985    * the persistant conncetion stuff */
2986   conn->fread = data->set.fread;
2987   conn->fread_in = data->set.in;
2988
2989   conn->bits.upload_chunky =
2990     ((conn->protocol&PROT_HTTP) &&
2991      data->set.upload &&
2992      (data->set.infilesize == -1) &&
2993      (data->set.httpversion != CURL_HTTP_VERSION_1_0))?
2994     /* HTTP, upload, unknown file size and not HTTP 1.0 */
2995     TRUE:
2996   /* else, no chunky upload */
2997   FALSE;
2998
2999 #ifndef USE_ARES
3000   /*************************************************************
3001    * Set timeout if that is being used, and we're not using an asynchronous
3002    * name resolve.
3003    *************************************************************/
3004   if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
3005     /*************************************************************
3006      * Set signal handler to catch SIGALRM
3007      * Store the old value to be able to set it back later!
3008      *************************************************************/
3009
3010 #ifdef SIGALRM
3011 #ifdef HAVE_SIGACTION
3012     struct sigaction sigact;
3013     sigaction(SIGALRM, NULL, &sigact);
3014     keep_sigact = sigact;
3015     keep_copysig = TRUE; /* yes, we have a copy */
3016     sigact.sa_handler = alarmfunc;
3017 #ifdef SA_RESTART
3018     /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
3019     sigact.sa_flags &= ~SA_RESTART;
3020 #endif
3021     /* now set the new struct */
3022     sigaction(SIGALRM, &sigact, NULL);
3023 #else /* HAVE_SIGACTION */
3024     /* no sigaction(), revert to the much lamer signal() */
3025 #ifdef HAVE_SIGNAL
3026     keep_sigact = signal(SIGALRM, alarmfunc);
3027 #endif
3028 #endif /* HAVE_SIGACTION */
3029
3030     /* We set the timeout on the name resolving phase first, separately from
3031      * the download/upload part to allow a maximum time on everything. This is
3032      * a signal-based timeout, why it won't work and shouldn't be used in
3033      * multi-threaded environments. */
3034
3035 #ifdef HAVE_ALARM
3036     /* alarm() makes a signal get sent when the timeout fires off, and that
3037        will abort system calls */
3038     prev_alarm = alarm(data->set.connecttimeout?
3039                        data->set.connecttimeout:
3040                        data->set.timeout);
3041     /* We can expect the conn->created time to be "now", as that was just
3042        recently set in the beginning of this function and nothing slow
3043        has been done since then until now. */
3044 #endif
3045 #endif /* SIGALRM */
3046   }
3047 #endif /* USE_ARES */
3048   
3049   /*************************************************************
3050    * Resolve the name of the server or proxy
3051    *************************************************************/
3052   if(conn->bits.reuse) {
3053     /* re-used connection, no resolving is necessary */
3054     hostaddr = NULL;
3055     conn->connect_addr = NULL; /* we don't connect now so we don't have any
3056                                   fresh connect_addr struct to point to */
3057   }
3058   else if(!data->change.proxy || !*data->change.proxy) {
3059     /* If not connecting via a proxy, extract the port from the URL, if it is
3060      * there, thus overriding any defaults that might have been set above. */
3061     conn->port =  conn->remote_port; /* it is the same port */
3062
3063     /* Resolve target host right on */
3064     rc = Curl_resolv(conn, conn->name, conn->port, &hostaddr);
3065     if(rc == 1)
3066       *async = TRUE;
3067
3068     else if(!hostaddr) {
3069       failf(data, "Couldn't resolve host '%s'", conn->name);
3070       result =  CURLE_COULDNT_RESOLVE_HOST;
3071       /* don't return yet, we need to clean up the timeout first */
3072     }
3073   }
3074   else {
3075     /* This is a proxy that hasn't been resolved yet. */
3076
3077     /* resolve proxy */
3078     rc = Curl_resolv(conn, conn->proxyhost, conn->port, &hostaddr);
3079
3080     if(rc == 1)
3081       *async = TRUE;
3082
3083     else if(!hostaddr) {
3084       failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
3085       result = CURLE_COULDNT_RESOLVE_PROXY;
3086       /* don't return yet, we need to clean up the timeout first */
3087     }
3088   }
3089   *addr = hostaddr;
3090
3091 #if defined(HAVE_ALARM) && defined(SIGALRM)
3092   if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
3093 #ifdef HAVE_SIGACTION
3094     if(keep_copysig) {
3095       /* we got a struct as it looked before, now put that one back nice
3096          and clean */
3097       sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
3098     }
3099 #else
3100 #ifdef HAVE_SIGNAL
3101     /* restore the previous SIGALRM handler */
3102     signal(SIGALRM, keep_sigact);
3103 #endif
3104 #endif /* HAVE_SIGACTION */
3105
3106     /* switch back the alarm() to either zero or to what it was before minus
3107        the time we spent until now! */
3108     if(prev_alarm) {
3109       /* there was an alarm() set before us, now put it back */
3110       long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
3111       long alarm_set;
3112
3113       /* the alarm period is counted in even number of seconds */
3114       alarm_set = prev_alarm - elapsed_ms/1000;
3115
3116       if(alarm_set<=0) {
3117         /* if it turned negative, we should fire off a SIGALRM here, but we
3118            won't, and zero would be to switch it off so we never set it to
3119            less than 1! */
3120         alarm(1);
3121         result = CURLE_OPERATION_TIMEOUTED;
3122         failf(data, "Previous alarm fired off!");
3123       }
3124       else
3125         alarm(alarm_set);
3126     }
3127     else
3128       alarm(0); /* just shut it off */
3129   }
3130 #endif
3131
3132   return result;
3133 }
3134
3135 /* SetupConnection() should be called after the name resolve initiated in
3136  * CreateConnection() is all done.
3137  */
3138  
3139 static CURLcode SetupConnection(struct connectdata *conn,
3140                                 struct Curl_dns_entry *hostaddr)
3141 {
3142   struct SessionHandle *data = conn->data;
3143   CURLcode result=CURLE_OK;
3144
3145   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
3146
3147   if(conn->protocol & PROT_FILE)
3148     /* There's nothing in this function to setup if we're only doing
3149        a file:// transfer */
3150     return result;
3151
3152   /*************************************************************
3153    * Send user-agent to HTTP proxies even if the target protocol
3154    * isn't HTTP.
3155    *************************************************************/
3156   if((conn->protocol&PROT_HTTP) ||
3157      (data->change.proxy && *data->change.proxy)) {
3158     if(data->set.useragent) {
3159       Curl_safefree(conn->allocptr.uagent);
3160       conn->allocptr.uagent =
3161         aprintf("User-Agent: %s\015\012", data->set.useragent);
3162     }
3163   }
3164
3165   if(data->set.encoding) {
3166     Curl_safefree(conn->allocptr.accept_encoding);
3167     conn->allocptr.accept_encoding =
3168       aprintf("Accept-Encoding: %s\015\012", data->set.encoding);
3169   }
3170
3171   conn->bytecount = 0;
3172   conn->headerbytecount = 0;
3173
3174   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
3175     bool connected;
3176
3177     /* Connect only if not already connected! */
3178     result = ConnectPlease(conn, hostaddr, &connected);
3179
3180     if(connected) {
3181       result = Curl_protocol_connect(conn, hostaddr);
3182       if(CURLE_OK == result)
3183         conn->bits.tcpconnect = TRUE;
3184     }
3185     else
3186       conn->bits.tcpconnect = FALSE;
3187
3188
3189     if(CURLE_OK != result)
3190       return result;
3191   }
3192   else {
3193     Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
3194     conn->bits.tcpconnect = TRUE;
3195     if(data->set.verbose)
3196       verboseconnect(conn, hostaddr);
3197   }
3198
3199   conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
3200                                set this here perhaps a second time */
3201
3202 #ifdef __EMX__
3203   /* 20000330 mgs
3204    * the check is quite a hack...
3205    * we're calling _fsetmode to fix the problem with fwrite converting newline
3206    * characters (you get mangled text files, and corrupted binary files when
3207    * you download to stdout and redirect it to a file). */
3208
3209   if ((data->set.out)->_handle == NULL) {
3210     _fsetmode(stdout, "b");
3211   }
3212 #endif
3213
3214   return CURLE_OK;
3215 }
3216
3217 CURLcode Curl_connect(struct SessionHandle *data,
3218                       struct connectdata **in_connect,
3219                       bool *asyncp)
3220 {
3221   CURLcode code;
3222   struct Curl_dns_entry *dns;
3223
3224   *asyncp = FALSE; /* assume synchronous resolves by default */
3225   
3226   /* call the stuff that needs to be called */
3227   code = CreateConnection(data, in_connect, &dns, asyncp);
3228
3229   if(CURLE_OK == code) {
3230     /* no error */
3231     if(dns || !*asyncp)
3232       /* If an address is available it means that we already have the name
3233          resolved, OR it isn't async.
3234          If so => continue connecting from here */
3235       code = SetupConnection(*in_connect, dns);
3236     /* else
3237          response will be received and treated async wise */
3238   }
3239   
3240   if(CURLE_OK != code) {
3241     /* We're not allowed to return failure with memory left allocated
3242        in the connectdata struct, free those here */
3243     if(*in_connect) {
3244       Curl_disconnect(*in_connect); /* close the connection */
3245       *in_connect = NULL;           /* return a NULL */
3246     }
3247   }
3248
3249   return code;
3250 }
3251
3252 /* Call this function after Curl_connect() has returned async=TRUE and
3253    then a successful name resolve has been received */
3254 CURLcode Curl_async_resolved(struct connectdata *conn)
3255 {
3256 #if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
3257   CURLcode code = SetupConnection(conn, conn->async.dns);
3258
3259   if(code)
3260     /* We're not allowed to return failure with memory left allocated
3261        in the connectdata struct, free those here */
3262     Curl_disconnect(conn); /* close the connection */
3263
3264   return code;
3265 #else
3266   (void)conn;
3267   return CURLE_OK;
3268 #endif
3269 }
3270
3271
3272 CURLcode Curl_done(struct connectdata *conn)
3273 {
3274   struct SessionHandle *data=conn->data;
3275   CURLcode result;
3276
3277   /* cleanups done even if the connection is re-used */
3278
3279   if(conn->bits.rangestringalloc) {
3280     free(conn->range);
3281     conn->bits.rangestringalloc = FALSE;
3282   }
3283
3284   /* Cleanup possible redirect junk */
3285   if(conn->newurl) {
3286     free(conn->newurl);
3287     conn->newurl = NULL;
3288   }
3289
3290   if(conn->connect_addr)
3291     Curl_resolv_unlock(conn->data, conn->connect_addr); /* done with this */
3292
3293 #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
3294   /* scan for DNS cache entries still marked as in use */
3295   Curl_hash_apply(data->hostcache,
3296                   NULL, Curl_scan_cache_used);
3297 #endif
3298
3299   Curl_hostcache_prune(data); /* kill old DNS cache entries */
3300
3301   /* this calls the protocol-specific function pointer previously set */
3302   if(conn->curl_done)
3303     result = conn->curl_done(conn);
3304   else
3305     result = CURLE_OK;
3306
3307   Curl_pgrsDone(conn); /* done with the operation */
3308
3309   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
3310      forced us to close this no matter what we think.
3311
3312      if conn->bits.close is TRUE, it means that the connection should be
3313      closed in spite of all our efforts to be nice, due to protocol
3314      restrictions in our or the server's end */
3315   if(data->set.reuse_forbid || conn->bits.close) {
3316     CURLcode res2;
3317     res2 = Curl_disconnect(conn); /* close the connection */
3318
3319     /* If we had an error already, make sure we return that one. But
3320        if we got a new error, return that. */
3321     if(!result && res2)
3322       result = res2;
3323   }
3324   else
3325     infof(data, "Connection #%d left intact\n", conn->connectindex);
3326
3327   return result;
3328 }
3329
3330 CURLcode Curl_do(struct connectdata **connp)
3331 {
3332   CURLcode result=CURLE_OK;
3333   struct connectdata *conn = *connp;
3334   struct SessionHandle *data=conn->data;
3335
3336   conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
3337
3338   if(conn->curl_do) {
3339     /* generic protocol-specific function pointer set in curl_connect() */
3340     result = conn->curl_do(conn);
3341
3342     /* This was formerly done in transfer.c, but we better do it here */
3343
3344     if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
3345       /* This was a re-use of a connection and we got a write error in the
3346        * DO-phase. Then we DISCONNECT this connection and have another attempt
3347        * to CONNECT and then DO again! The retry cannot possibly find another
3348        * connection to re-use, since we only keep one possible connection for
3349        * each.  */
3350
3351       infof(data, "Re-used connection seems dead, get a new one\n");
3352
3353       conn->bits.close = TRUE; /* enforce close of this connection */
3354       result = Curl_done(conn);   /* we are so done with this */
3355
3356       /* conn is no longer a good pointer */
3357
3358       if(CURLE_OK == result) {
3359         bool async;
3360         /* Now, redo the connect and get a new connection */
3361         result = Curl_connect(data, connp, &async);
3362         if(CURLE_OK == result) {
3363           /* We have connected or sent away a name resolve query fine */
3364
3365           conn = *connp; /* setup conn to again point to something nice */
3366           if(async) {
3367             /* Now, if async is TRUE here, we need to wait for the name
3368                to resolve */
3369             result = Curl_wait_for_resolv(conn, NULL);
3370             if(result)
3371               return result;
3372             
3373             /* Resolved, continue with the connection */
3374             result = Curl_async_resolved(conn);              
3375             if(result)
3376               return result;
3377           }
3378           
3379           /* ... finally back to actually retry the DO phase */
3380           result = conn->curl_do(conn);
3381         }
3382       }
3383     }
3384   }
3385   return result;
3386 }
3387
3388 CURLcode Curl_do_more(struct connectdata *conn)
3389 {
3390   CURLcode result=CURLE_OK;
3391
3392   if(conn->curl_do_more)
3393     result = conn->curl_do_more(conn);
3394
3395   return result;
3396 }
3397
3398 static bool safe_strequal(char* str1, char* str2)
3399 {
3400   if(str1 && str2)
3401     /* both pointers point to something then compare them */
3402     return strequal(str1, str2);
3403   else
3404     /* if both pointers are NULL then treat them as equal */
3405     return (!str1 && !str2);
3406 }
3407
3408 bool
3409 Curl_ssl_config_matches(struct ssl_config_data* data,
3410                         struct ssl_config_data* needle)
3411 {
3412   if((data->version == needle->version) &&
3413      (data->verifypeer == needle->verifypeer) &&
3414      (data->verifyhost == needle->verifyhost) &&
3415      safe_strequal(data->CApath, needle->CApath) &&
3416      safe_strequal(data->CAfile, needle->CAfile) &&
3417      safe_strequal(data->random_file, needle->random_file) &&
3418      safe_strequal(data->egdsocket, needle->egdsocket) &&
3419      safe_strequal(data->cipher_list, needle->cipher_list))
3420     return TRUE;
3421
3422   return FALSE;
3423 }
3424
3425 bool
3426 Curl_clone_ssl_config(struct ssl_config_data *source,
3427                       struct ssl_config_data *dest)
3428 {
3429   dest->verifyhost = source->verifyhost;
3430   dest->verifypeer = source->verifypeer;
3431   dest->version = source->version;
3432
3433   if(source->CAfile) {
3434     dest->CAfile = strdup(source->CAfile);
3435     if(!dest->CAfile)
3436       return FALSE;
3437   }
3438
3439   if(source->CApath) {
3440     dest->CApath = strdup(source->CApath);
3441     if(!dest->CApath)
3442       return FALSE;
3443   }
3444
3445   if(source->cipher_list) {
3446     dest->cipher_list = strdup(source->cipher_list);
3447     if(!dest->cipher_list)
3448       return FALSE;
3449   }
3450
3451   if(source->egdsocket) {
3452     dest->egdsocket = strdup(source->egdsocket);
3453     if(!dest->egdsocket)
3454       return FALSE;
3455   }
3456
3457   if(source->random_file) {
3458     dest->random_file = strdup(source->random_file);
3459     if(!dest->random_file)
3460       return FALSE;
3461   }
3462
3463   return TRUE;
3464 }
3465
3466 void Curl_free_ssl_config(struct ssl_config_data* sslc)
3467 {
3468   if(sslc->CAfile)
3469     free(sslc->CAfile);
3470
3471   if(sslc->CApath)
3472     free(sslc->CApath);
3473
3474   if(sslc->cipher_list)
3475     free(sslc->cipher_list);
3476
3477   if(sslc->egdsocket)
3478     free(sslc->egdsocket);
3479
3480   if(sslc->random_file)
3481     free(sslc->random_file);
3482 }