Newer
Older
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
* $Id$
*****************************************************************************/
#include "setup.h"
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifndef HAVE_SELECT
#error "We can't compile without select() support!"
#endif
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
#endif
#include "urldata.h"
#include "netrc.h"
#include "formdata.h"
#include "base64.h"
#include "ssluse.h"
#include "hostip.h"
#include "if2ip.h"
Daniel Stenberg
committed
#include "transfer.h"
#include "sendf.h"
#include "getpass.h"
#include "progress.h"
#include "cookie.h"
#include "escape.h"
/* And now for the protocols */
#include "ftp.h"
#include "dict.h"
#include "telnet.h"
#include "http.h"
#include "file.h"
#include "ldap.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
CURLcode _urlget(struct UrlData *data);
/* does nothing, returns OK */
CURLcode curl_init(void)
void curl_free(void)
{
}
void static urlfree(struct UrlData *data, bool totally)
Daniel Stenberg
committed
if (data->ssl.use) {
if(data->ssl.handle) {
(void)SSL_shutdown(data->ssl.handle);
SSL_set_connect_state(data->ssl.handle);
Daniel Stenberg
committed
SSL_free (data->ssl.handle);
data->ssl.handle = NULL;
Daniel Stenberg
committed
if(data->ssl.ctx) {
SSL_CTX_free (data->ssl.ctx);
data->ssl.ctx = NULL;
Daniel Stenberg
committed
data->ssl.use = FALSE; /* get back to ordinary socket usage */
}
#endif /* USE_SSLEAY */
/* close possibly still open sockets */
if(-1 != data->secondarysocket) {
sclose(data->secondarysocket);
data->secondarysocket = -1;
}
if(-1 != data->firstsocket) {
sclose(data->firstsocket);
data->firstsocket=-1;
}
if(data->bits.proxystringalloc) {
data->bits.proxystringalloc=FALSE;;
free(data->proxy);
data->proxy=NULL;
/* Since we allocated the string the previous round, it means that we
"discovered" the proxy in the environment variables and thus we must
switch off that knowledge again... */
data->bits.httpproxy=FALSE;
if(data->bits.rangestringalloc) {
free(data->range);
data->range=NULL;
data->bits.rangestringalloc=0; /* free now */
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
if(data->ptr_proxyuserpwd) {
free(data->ptr_proxyuserpwd);
data->ptr_proxyuserpwd=NULL;
}
if(data->ptr_uagent) {
free(data->ptr_uagent);
data->ptr_uagent=NULL;
}
if(data->ptr_userpwd) {
free(data->ptr_userpwd);
data->ptr_userpwd=NULL;
}
if(data->ptr_rangeline) {
free(data->ptr_rangeline);
data->ptr_rangeline=NULL;
}
if(data->ptr_ref) {
free(data->ptr_ref);
data->ptr_ref=NULL;
}
if(data->ptr_cookie) {
free(data->ptr_cookie);
data->ptr_cookie=NULL;
}
if(data->ptr_host) {
free(data->ptr_host);
data->ptr_host=NULL;
}
if(totally) {
/* we let the switch decide whether we're doing a part or total
cleanup */
/* check for allocated [URL] memory to free: */
if(data->freethis)
free(data->freethis);
if(data->headerbuff)
free(data->headerbuff);
if(data->free_referer)
free(data->referer);
if(data->bits.urlstringalloc)
/* the URL is allocated, free it! */
free(data->url);
Curl_cookie_cleanup(data->cookies);
/* global cleanup */
curl_free();
}
}
CURLcode curl_close(CURL *curl)
{
struct UrlData *data=(struct UrlData *)curl;
void *protocol = data->proto.generic;
/* total session cleanup (frees 'data' as well!)*/
urlfree(data, TRUE);
if(protocol)
free(protocol);
return CURLE_OK;
}
static
int my_getpass(void *clientp, char *prompt, char* buffer, int buflen )
{
char *retbuf;
retbuf = getpass_r(prompt, buffer, buflen);
if(NULL == retbuf)
return 1;
else
return 0; /* success */
}
CURLcode curl_open(CURL **curl, char *url)
{
/* We don't yet support specifying the URL at this point */
/* Very simple start-up: alloc the struct, init it with zeroes and return */
data = (struct UrlData *)malloc(sizeof(struct UrlData));
memset(data, 0, sizeof(struct UrlData));
data->handle = STRUCT_OPEN;
data->interf = CURLI_NORMAL; /* normal interface by default */
/* We do some initial setup here, all those fields that can't be just 0 */
data-> headerbuff=(char*)malloc(HEADERSIZE);
if(!data->headerbuff) {
free(data); /* free the memory again */
return CURLE_OUT_OF_MEMORY;
}
data-> headersize=HEADERSIZE;
data->out = stdout; /* default output to stdout */
data->in = stdin; /* default input from stdin */
data->err = stderr; /* default stderr to stderr */
data->firstsocket = -1; /* no file descriptor */
data->secondarysocket = -1; /* no file descriptor */
/* use fwrite as default function to store output */
data->fwrite = (size_t (*)(char *, size_t, size_t, FILE *))fwrite;
/* use fread as default function to read input */
data->fread = (size_t (*)(char *, size_t, size_t, FILE *))fread;
/* set the default passwd function */
data->fpasswd = my_getpass;
data->infilesize = -1; /* we don't know any size */
data->current_speed = -1; /* init to negative == impossible */
Daniel Stenberg
committed
data->httpreq = HTTPREQ_GET; /* Default HTTP request */
}
/* this is a very serious error */
CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
{
struct UrlData *data = curl;
va_list param;
char *cookiefile;
va_start(param, option);
switch(option) {
data->bits.verbose = va_arg(param, long)?TRUE:FALSE;
data->bits.http_include_header = va_arg(param, long)?TRUE:FALSE;
data->bits.hide_progress = va_arg(param, long)?TRUE:FALSE;
if(data->bits.hide_progress)
data->progress.flags |= PGRS_HIDE;
break;
case CURLOPT_NOBODY:
data->bits.no_body = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_FAILONERROR:
data->bits.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
data->bits.upload = va_arg(param, long)?TRUE:FALSE;
if(data->bits.upload)
/* If this is HTTP, PUT is what's needed to "upload" */
data->httpreq = HTTPREQ_PUT;
data->bits.http_post = va_arg(param, long)?TRUE:FALSE;
if(data->bits.http_post)
data->httpreq = HTTPREQ_POST;
case CURLOPT_FILETIME:
data->bits.get_filetime = va_arg(param, long)?TRUE:FALSE;
break;
data->bits.ftp_list_only = va_arg(param, long)?TRUE:FALSE;
data->bits.ftp_append = va_arg(param, long)?TRUE:FALSE;
data->bits.use_netrc = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_FOLLOWLOCATION:
data->bits.http_follow_location = va_arg(param, long)?TRUE:FALSE;
data->bits.ftp_ascii = va_arg(param, long)?TRUE:FALSE;
data->bits.http_put = va_arg(param, long)?TRUE:FALSE;
if(data->bits.http_put)
data->httpreq = HTTPREQ_PUT;
data->bits.mute = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_TIMECONDITION:
data->timecondition = va_arg(param, long);
break;
data->timevalue = va_arg(param, long);
break;
Daniel Stenberg
committed
data->ssl.version = va_arg(param, long);
cookiefile = (char *)va_arg(param, void *);
if(cookiefile) {
data->cookies = Curl_cookie_init(cookiefile);
data->writeheader = (FILE *)va_arg(param, FILE *);
break;
data->cookie = va_arg(param, char *);
break;
data->errorbuffer = va_arg(param, char *);
break;
data->out = va_arg(param, FILE *);
break;
data->ftpport = va_arg(param, char *);
data->bits.ftp_use_port = data->ftpport?1:0;
data->headers = va_arg(param, struct curl_slist *);
data->customrequest = va_arg(param, char *);
if(data->customrequest)
data->httpreq = HTTPREQ_CUSTOM;
data->httppost = va_arg(param, struct HttpPost *);
data->bits.http_formpost = data->httppost?1:0;
if(data->bits.http_formpost)
data->httpreq = HTTPREQ_POST_FORM;
data->in = va_arg(param, FILE *);
break;
data->infilesize = va_arg(param, long);
break;
data->low_speed_limit=va_arg(param, long);
break;
data->low_speed_time=va_arg(param, long);
break;
data->url = va_arg(param, char *);
break;
data->port = va_arg(param, long);
data->postfields = va_arg(param, char *);
break;
case CURLOPT_POSTFIELDSIZE:
data->postfieldsize = va_arg(param, long);
break;
data->referer = va_arg(param, char *);
data->bits.http_set_referer = (data->referer && *data->referer)?1:0;
case CURLOPT_AUTOREFERER:
data->bits.http_auto_referer = va_arg(param, long)?1:0;
break;
data->proxy = va_arg(param, char *);
data->bits.httpproxy = data->proxy?1:0;
case CURLOPT_HTTPPROXYTUNNEL:
data->bits.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_PROXYPORT:
data->proxyport = va_arg(param, long);
data->timeout = va_arg(param, long);
break;
case CURLOPT_MAXREDIRS:
data->maxredirs = va_arg(param, long);
break;
data->useragent = va_arg(param, char *);
break;
data->userpwd = va_arg(param, char *);
data->bits.user_passwd = data->userpwd?1:0;
data->postquote = va_arg(param, struct curl_slist *);
break;
case CURLOPT_PROGRESSFUNCTION:
data->fprogress = va_arg(param, curl_progress_callback);
data->progress.callback = TRUE; /* no longer internal */
break;
case CURLOPT_PROGRESSDATA:
data->progress_client = va_arg(param, void *);
break;
case CURLOPT_PASSWDFUNCTION:
data->fpasswd = va_arg(param, curl_passwd_callback);
break;
case CURLOPT_PASSWDDATA:
data->passwd_client = va_arg(param, void *);
break;
data->proxyuserpwd = va_arg(param, char *);
data->bits.proxy_user_passwd = data->proxyuserpwd?1:0;
data->range = va_arg(param, char *);
data->bits.set_range = data->range?1:0;
data->resume_from = va_arg(param, long);
break;
data->err = va_arg(param, FILE *);
break;
data->fwrite = va_arg(param, curl_write_callback);
data->fread = va_arg(param, curl_read_callback);
data->cert = va_arg(param, char *);
break;
data->cert_passwd = va_arg(param, char *);
break;
data->crlf = va_arg(param, long);
break;
data->quote = va_arg(param, struct curl_slist *);
break;
case CURLOPT_INTERFACE:
data->device = va_arg(param, char *);
break;
case CURLOPT_KRB4LEVEL:
data->krb4_level = va_arg(param, char *);
data->bits.krb4=data->krb4_level?TRUE:FALSE;
break;
Daniel Stenberg
committed
case CURLOPT_SSL_VERIFYPEER:
data->ssl.verifypeer = va_arg(param, long);
break;
case CURLOPT_CAINFO:
data->ssl.CAfile = va_arg(param, char *);
data->ssl.CApath = NULL; /*This does not work on windows.*/
break;
default:
/* unknown tag and its companion, just ignore: */
return CURLE_READ_ERROR; /* correct this */
#if !defined(WIN32)||defined(__CYGWIN32__)
#ifndef RETSIGTYPE
#define RETSIGTYPE void
#endif
static
RETSIGTYPE alarmfunc(int signal)
{
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void)signal;
return;
}
#endif
CURLcode curl_disconnect(CURLconnect *c_connect)
{
struct connectdata *conn = c_connect;
struct UrlData *data = conn->data;
#ifdef ENABLE_IPV6
if(conn->res) /* host name info */
freeaddrinfo(conn->res);
#else
if(conn->hostent_buf) /* host name info */
free(conn->hostent_buf);
if(conn->path) /* the URL path part */
free(conn->path);
free(conn); /* free the connection oriented data */
/* clean up the sockets and SSL stuff from the previous "round" */
urlfree(data, FALSE);
return CURLE_OK;
}
static CURLcode _connect(CURL *curl, CURLconnect **in_connect)
char resumerange[40]="";
struct UrlData *data = curl;
struct connectdata *conn;
Daniel Stenberg
committed
char endbracket;
Daniel Stenberg
committed
#ifdef HAVE_SIGACTION
struct sigaction sigact;
#endif
#ifdef ENABLE_IPV6
struct addrinfo *ai;
#endif
/*************************************************************
* Check input data
*************************************************************/
if(!data || (data->handle != STRUCT_OPEN))
return CURLE_BAD_FUNCTION_ARGUMENT; /* TBD: make error codes */
if(!data->url)
return CURLE_URL_MALFORMAT;
/*************************************************************
* Allocate and initiate a connection struct
*************************************************************/
conn = (struct connectdata *)malloc(sizeof(struct connectdata));
if(!conn) {
*in_connect = NULL; /* clear the pointer */
return CURLE_OUT_OF_MEMORY;
}
*in_connect = conn;
memset(conn, 0, sizeof(struct connectdata));
conn->handle = STRUCT_CONNECT;
conn->data = data; /* remember our daddy */
conn->state = CONN_INIT;
conn->upload_bufsize = UPLOAD_BUFSIZE; /* the smallest upload buffer size
we use */
/*************************************************************
* Set signal handler
*************************************************************/
Daniel Stenberg
committed
#ifdef HAVE_SIGACTION
sigaction(SIGALRM, NULL, &sigact);
sigact.sa_handler = alarmfunc;
Daniel Stenberg
committed
#ifdef SA_RESTART
/* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
Daniel Stenberg
committed
sigact.sa_flags &= ~SA_RESTART;
Daniel Stenberg
committed
#endif
Daniel Stenberg
committed
sigaction(SIGALRM, &sigact, NULL);
#else
/* no sigaction(), revert to the much lamer signal() */
#ifdef HAVE_SIGNAL
signal(SIGALRM, alarmfunc);
#endif
/***********************************************************
* We need to allocate memory to store the path in. We get the size of the
* full URL to be sure, and we need to make it at least 256 bytes since
* other parts of the code will rely on this fact
***********************************************************/
#define LEAST_PATH_ALLOC 256
urllen=strlen(data->url);
if(urllen < LEAST_PATH_ALLOC)
urllen=LEAST_PATH_ALLOC;
conn->path=(char *)malloc(urllen);
if(NULL == conn->path)
return CURLE_OUT_OF_MEMORY; /* really bad error */
/*************************************************************
* Parse the URL.
*
* We need to parse the url even when using the proxy, because we will need
* the hostname and port in case we are trying to SSL connect through the
* proxy -- and we don't know if we will need to use SSL until we parse the
* url ...
************************************************************/
if((2 == sscanf(data->url, "%64[^:]://%[^\n]",
conn->proto,
conn->path)) && strequal(conn->proto, "file")) {
/*
* we deal with file://<host>/<path> differently since it supports no
* hostname other than "localhost" and "127.0.0.1", which is unique among
* the URL protocols specified in RFC 1738
*/
if (strnequal(conn->path, "localhost/", 10) ||
strnequal(conn->path, "127.0.0.1/", 10))
/* If there's another host name than the one we support, <host>/ is
* quietly ommitted */
strcpy(conn->path, &conn->path[10]);
strcpy(conn->proto, "file"); /* store protocol string lowercase */
else {
/* Set default host and default path */
strcpy(conn->path, "/");
if (2 > sscanf(data->url,
conn->proto, conn->gname, conn->path)) {
/*
* The URL was badly formatted, let's try the browser-style _without_
* protocol specified like 'http://'.
*/
if((1 > sscanf(data->url, "%256[^\n/]%[^\n]",
/*
* We couldn't even get this format.
*/
failf(data, "<url> malformed");
return CURLE_URL_MALFORMAT;
}
/*
* Since there was no protocol part specified, we guess what protocol it
* is based on the first letters of the server name.
*/
if(strnequal(conn->gname, "FTP", 3)) {
strcpy(conn->proto, "ftp");
}
else if(strnequal(conn->gname, "GOPHER", 6))
strcpy(conn->proto, "gopher");
else if(strnequal(conn->gname, "HTTPS", 5))
strcpy(conn->proto, "https");
else if(strnequal(conn->gname, "TELNET", 6))
strcpy(conn->proto, "telnet");
else if (strnequal(conn->gname, "DICT", sizeof("DICT")-1))
strcpy(conn->proto, "DICT");
else if (strnequal(conn->gname, "LDAP", sizeof("LDAP")-1))
strcpy(conn->proto, "LDAP");
else {
strcpy(conn->proto, "http");
}
conn->protocol |= PROT_MISSING; /* not given in URL */
}
/*************************************************************
* Take care of user and password authentication stuff
*************************************************************/
if(data->bits.user_passwd && !data->bits.use_netrc) {
data->user[0] =0;
data->passwd[0]=0;
if(*data->userpwd != ':') {
/* the name is given, get user+password */
sscanf(data->userpwd, "%127[^:]:%127[^\n]",
else
/* no name given, get the password only */
sscanf(data->userpwd+1, "%127[^\n]", data->passwd);
/* check for password, if no ask for one */
if( !data->passwd[0] ) {
if(!data->fpasswd ||
data->fpasswd(data->passwd_client,
"password:", data->passwd, sizeof(data->passwd)))
return CURLE_BAD_PASSWORD_ENTERED;
/*************************************************************
* Take care of proxy authentication stuff
*************************************************************/
data->proxyuser[0] =0;
data->proxypasswd[0]=0;
if(*data->proxyuserpwd != ':') {
/* the name is given, get user+password */
sscanf(data->proxyuserpwd, "%127[^:]:%127[^\n]",
data->proxyuser, data->proxypasswd);
else
/* no name given, get the password only */
sscanf(data->proxyuserpwd+1, "%127[^\n]", data->proxypasswd);
/* check for password, if no ask for one */
if( !data->proxypasswd[0] ) {
if(!data->fpasswd ||
data->fpasswd( data->passwd_client,
"proxy password:",
data->proxypasswd,
sizeof(data->proxypasswd)))
return CURLE_BAD_PASSWORD_ENTERED;
/*************************************************************
* Set a few convenience pointers
*************************************************************/
conn->name = conn->gname;
conn->ppath = conn->path;
data->hostname = conn->name;
/*************************************************************
* Detect what (if any) proxy to use
*************************************************************/
/* If proxy was not specified, we check for default proxy environment
* variables, to enable i.e Lynx compliance:
*
* http_proxy=http://some.server.dom:port/
* https_proxy=http://some.server.dom:port/
* ftp_proxy=http://some.server.dom:port/
* gopher_proxy=http://some.server.dom:port/
* no_proxy=domain1.dom,host.domain2.dom
* (a comma-separated list of hosts which should
* not be proxied, or an asterisk to override
* all proxy variables)
* all_proxy=http://some.server.dom:port/
* (seems to exist for the CERN www lib. Probably
* the first to check for.)
*
* For compatibility, the all-uppercase versions of these variables are
* checked if the lowercase versions don't exist.
*/
char *no_proxy=NULL;
no_proxy=curl_getenv("no_proxy");
no_proxy=curl_getenv("NO_PROXY");
if(!no_proxy || !strequal("*", no_proxy)) {
/* NO_PROXY wasn't specified or it wasn't just an asterisk */
char *nope;
nope=no_proxy?strtok(no_proxy, ", "):NULL;
while(nope) {
if(strlen(nope) <= strlen(conn->name)) {
conn->name + strlen(conn->name) - strlen(nope);
if(strnequal(nope, checkn, strlen(nope))) {
/* no proxy for this host! */
break;
}
}
nope=strtok(NULL, ", ");
}
if(!nope) {
/* It was not listed as without proxy */
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
*envp++ = tolower(*protop++);
/* append _proxy */
strcpy(envp, "_proxy");
prox=curl_getenv(proxy_env);
if(!prox) {
/* There was no lowercase variable, try the uppercase version: */
for(envp = proxy_env; *envp; envp++)
*envp = toupper(*envp);
prox=curl_getenv(proxy_env);
if(prox && *prox) { /* don't count "" strings */
proxy = prox; /* use this */
proxy = curl_getenv("all_proxy"); /* default proxy to use */
proxy=curl_getenv("ALL_PROXY");
if(proxy && *proxy) {
/* we have a proxy here to set */
data->proxy = proxy;
data->bits.proxystringalloc=1; /* this needs to be freed later */
} /* if (!nope) - it wasn't specified non-proxy */
if(no_proxy)
free(no_proxy);
/*************************************************************
* No protocol but proxy usage needs attention
*************************************************************/
if((conn->protocol&PROT_MISSING) && data->bits.httpproxy ) {
/* We're guessing prefixes here and since we're told to use a proxy, we
need to add the protocol prefix to the URL string before we continue!
*/
char *reurl;
reurl = aprintf("%s://%s", conn->proto, data->url);
data->url = reurl;
if(data->freethis)
free(data->freethis);
data->freethis = reurl;
conn->protocol &= ~PROT_MISSING; /* switch that one off again */
/************************************************************
* RESUME on a HTTP page is a tricky business. First, let's just check that
* 'range' isn't used, then set the range parameter and leave the resume as
* it is to inform about this situation for later use. We will then
* "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
* server, we will get the document resumed. If we talk to a HTTP/1.0
* server, we just fail since we can't rewind the file writing from within
* this function.
***********************************************************/
snprintf(resumerange, sizeof(resumerange), "%d-", data->resume_from);
data->range=strdup(resumerange); /* tell ourselves to fetch this range */
data->bits.rangestringalloc = TRUE; /* mark as allocated */
data->bits.set_range = 1; /* switch on range usage */
/*************************************************************
* Set timeout if that is being used
*************************************************************/
if(data->timeout) {
/* We set the timeout on the connection/resolving phase first, separately
* from the download/upload part to allow a maximum time on everything */
myalarm(data->timeout); /* this sends a signal when the timeout fires
off, and that will abort system calls */
}
/*************************************************************
* Setup internals depending on protocol
*************************************************************/
if (strequal(conn->proto, "HTTP")) {
if(!data->port)
data->port = PORT_HTTP;
data->remote_port = PORT_HTTP;
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
conn->curl_close = Curl_http_close;
else if (strequal(conn->proto, "HTTPS")) {
#ifdef USE_SSLEAY
if(!data->port)
data->port = PORT_HTTPS;
data->remote_port = PORT_HTTPS;
conn->protocol |= PROT_HTTP;
conn->protocol |= PROT_HTTPS;
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
conn->curl_connect = Curl_http_connect;
conn->curl_close = Curl_http_close;
failf(data, "libcurl was built with SSL disabled, https: not supported!");
else if (strequal(conn->proto, "GOPHER")) {
if(!data->port)
data->port = PORT_GOPHER;
data->remote_port = PORT_GOPHER;
/* Skip /<item-type>/ in path if present */
if (isdigit((int)conn->path[1])) {
conn->ppath = strchr(&conn->path[1], '/');
if (conn->ppath == NULL)
conn->ppath = conn->path;
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;
conn->curl_close = Curl_http_close;
else if(strequal(conn->proto, "FTP")) {
char *type;
if(!data->port)
data->port = PORT_FTP;
data->remote_port = PORT_FTP;
if(data->bits.httpproxy &&
!data->bits.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel ftp operations through the proxy, we
switch and use HTTP operations only */
conn->curl_do = Curl_http;
conn->curl_done = Curl_http_done;