Newer
Older
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
* 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 COPYING file.
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
***************************************************************************/
#include "curl_setup.h"
#ifdef HAVE_NETINET_IN_H
#endif
#ifdef HAVE_NETDB_H
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
#ifdef USE_LIBIDN2
#include <idn2.h>
#elif defined(USE_WIN32_IDN)
/* prototype for curl_win32_idn_to_ascii() */
bool curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_LIBIDN2 */
#include "urldata.h"
#include "netrc.h"
#include "formdata.h"
#include "hostip.h"
#include "transfer.h"
#include "sendf.h"
#include "progress.h"
#include "cookie.h"
#include "strerror.h"
#include "escape.h"
#include "strtok.h"
#include "share.h"
#include "content_encoding.h"
#include "http_digest.h"
#include "http_negotiate.h"
#include "select.h"
#include "multiif.h"
#include "easyif.h"
#include "speedcheck.h"
#include "warnless.h"
#include "non-ascii.h"
#include "inet_pton.h"
#include "ftp.h"
#include "dict.h"
#include "telnet.h"
#include "tftp.h"
#include "http.h"
Daniel Stenberg
committed
#include "curl_ldap.h"
#include "ssh.h"
#include "imap.h"
#include "url.h"
#include "connect.h"
#include "inet_ntop.h"
#include "curl_ntlm_wb.h"
#include "gopher.h"
#include "http_proxy.h"
#include "conncache.h"
#include "pipeline.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
/* Local static prototypes */
find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
struct connectbundle *bundle);
static void conn_free(struct connectdata *conn);
static void free_fixed_hostname(struct hostname *host);
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
static CURLcode parse_url_login(struct Curl_easy *data,
struct connectdata *conn,
char **userptr, char **passwdptr,
char **optionsptr);
static CURLcode parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
static unsigned int get_protocol_family(unsigned int protocol);
Patrick Monnerat
committed
/*
* Protocol table.
*/
static const struct Curl_handler * const protocols[] = {
Patrick Monnerat
committed
#ifndef CURL_DISABLE_HTTP
&Curl_handler_http,
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
&Curl_handler_https,
#endif
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
&Curl_handler_ftps,
#endif
#ifndef CURL_DISABLE_TELNET
&Curl_handler_telnet,
#endif
#ifndef CURL_DISABLE_DICT
&Curl_handler_dict,
#endif
Patrick Monnerat
committed
&Curl_handler_ldap,
#if !defined(CURL_DISABLE_LDAPS) && \
((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
(!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
Patrick Monnerat
committed
&Curl_handler_ldaps,
#endif
Patrick Monnerat
committed
#ifndef CURL_DISABLE_FILE
&Curl_handler_file,
#endif
#ifndef CURL_DISABLE_TFTP
&Curl_handler_tftp,
#endif
#ifdef USE_LIBSSH2
&Curl_handler_scp,
&Curl_handler_sftp,
#endif
#ifndef CURL_DISABLE_IMAP
&Curl_handler_imap,
#ifdef USE_SSL
&Curl_handler_imaps,
#endif
#endif
#ifndef CURL_DISABLE_POP3
&Curl_handler_pop3,
#ifdef USE_SSL
&Curl_handler_pop3s,
#endif
#endif
#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
(CURL_SIZEOF_CURL_OFF_T > 4) && \
(!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
&Curl_handler_smb,
#ifdef USE_SSL
&Curl_handler_smbs,
#endif
#endif
#ifndef CURL_DISABLE_SMTP
&Curl_handler_smtp,
#ifdef USE_SSL
&Curl_handler_smtps,
#endif
#endif
Daniel Stenberg
committed
#ifndef CURL_DISABLE_RTSP
&Curl_handler_rtsp,
#endif
#ifndef CURL_DISABLE_GOPHER
&Curl_handler_gopher,
#endif
#ifdef USE_LIBRTMP
&Curl_handler_rtmp,
&Curl_handler_rtmpt,
&Curl_handler_rtmpe,
&Curl_handler_rtmpte,
&Curl_handler_rtmps,
&Curl_handler_rtmpts,
#endif
Patrick Monnerat
committed
(struct Curl_handler *) NULL
};
/*
* Dummy handler for undefined protocol schemes.
*/
static const struct Curl_handler Curl_handler_dummy = {
Patrick Monnerat
committed
"<no protocol>", /* scheme */
ZERO_NULL, /* setup_connection */
ZERO_NULL, /* do_it */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
Daniel Stenberg
committed
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
Patrick Monnerat
committed
0, /* defport */
Patrick Monnerat
committed
};
void Curl_freeset(struct Curl_easy *data)
Daniel Stenberg
committed
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
for(i=(enum dupstring)0; i < STRING_LAST; i++) {
Daniel Stenberg
committed
Curl_safefree(data->set.str[i]);
if(data->change.referer_alloc) {
Curl_safefree(data->change.referer);
data->change.referer_alloc = FALSE;
}
data->change.referer = NULL;
if(data->change.url_alloc) {
Curl_safefree(data->change.url);
data->change.url_alloc = FALSE;
}
data->change.url = NULL;
Daniel Stenberg
committed
}
static CURLcode setstropt(char **charp, const char *s)
Daniel Stenberg
committed
{
/* Release the previous storage at `charp' and replace by a dynamic storage
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
Daniel Stenberg
committed
Daniel Stenberg
committed
if(s) {
Daniel Stenberg
committed
Daniel Stenberg
committed
return CURLE_OUT_OF_MEMORY;
Daniel Stenberg
committed
}
return CURLE_OK;
}
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
Daniel Stenberg
committed
{
CURLcode result = CURLE_OK;
char *user = NULL;
char *passwd = NULL;
Daniel Stenberg
committed
/* Parse the login details if specified. It not then we treat NULL as a hint
to clear the existing data */
if(option) {
result = parse_login_details(option, strlen(option),
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
NULL);
Daniel Stenberg
committed
}
if(!result) {
/* Store the username part of option if required */
if(!user && option && option[0] == ':') {
/* Allocate an empty string instead of returning NULL as user name */
user = strdup("");
if(!user)
result = CURLE_OUT_OF_MEMORY;
}
Curl_safefree(*userp);
*userp = user;
Daniel Stenberg
committed
/* Store the password part of option if required */
if(passwdp) {
Curl_safefree(*passwdp);
*passwdp = passwd;
Daniel Stenberg
committed
}
Daniel Stenberg
committed
return result;
}
CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
Daniel Stenberg
committed
{
Daniel Stenberg
committed
enum dupstring i;
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
dst->set = src->set;
/* clear all string pointers first */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
/* duplicate all strings */
for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
result = setstropt(&dst->set.str[i], src->set.str[i]);
if(result)
return result;
Daniel Stenberg
committed
}
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
if(src->set.postfieldsize && src->set.str[i]) {
/* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
dst->set.str[i] = Curl_memdup(src->set.str[i],
curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
dst->set.postfields = dst->set.str[i];
}
return CURLE_OK;
Daniel Stenberg
committed
}
/*
* This is the internal function curl_easy_cleanup() calls. This should
* cleanup and free all resources associated with this sessionhandle.
*
* NOTE: if we ever add something that attempts to write to a socket or
* similar here, we must ignore SIGPIPE first. It is currently only done
* when curl_easy_perform() is invoked.
*/
CURLcode Curl_close(struct Curl_easy *data)
struct Curl_multi *m;
if(!data)
return CURLE_OK;
Curl_expire_clear(data); /* shut off timers */
m = data->multi;
if(m)
/* This handle is still part of a multi handle, take care of this first
and detach this handle from there. */
curl_multi_remove_handle(data->multi, data);
if(data->multi_easy)
/* when curl_easy_perform() is used, it creates its own multi handle to
use and this is the one */
curl_multi_cleanup(data->multi_easy);
/* Destroy the timeout list that is held in the easy handle. It is
/normally/ done by curl_multi_remove_handle() but this is "just in
case" */
if(data->state.timeoutlist) {
Curl_llist_destroy(data->state.timeoutlist, NULL);
data->state.timeoutlist = NULL;
}
Daniel Stenberg
committed
data->magic = 0; /* force a clear AFTER the possibly enforced removal from
the multi handle, since that function uses the magic
field! */
Daniel Stenberg
committed
if(data->state.rangestringalloc)
free(data->state.range);
Daniel Stenberg
committed
/* Free the pathbuffer */
Daniel Stenberg
committed
Curl_safefree(data->state.pathbuffer);
/* freed here just in case DONE wasn't called */
Curl_free_request_state(data);
/* Close down all open SSL info and sessions */
Daniel Stenberg
committed
Curl_ssl_close_all(data);
Daniel Stenberg
committed
Curl_safefree(data->state.first_host);
Curl_safefree(data->state.scratch);
Daniel Stenberg
committed
Curl_ssl_free_certinfo(data);
/* Cleanup possible redirect junk */
Markus Elfring
committed
free(data->req.newurl);
data->req.newurl = NULL;
if(data->change.referer_alloc) {
Curl_safefree(data->change.referer);
data->change.referer_alloc = FALSE;
}
data->change.referer = NULL;
if(data->change.url_alloc) {
Curl_safefree(data->change.url);
data->change.url_alloc = FALSE;
}
data->change.url = NULL;
Curl_safefree(data->state.headerbuff);
Curl_flush_cookies(data, 1);
Curl_digest_cleanup(data);
Curl_safefree(data->info.contenttype);
Daniel Stenberg
committed
Curl_safefree(data->info.wouldredirect);
Daniel Stenberg
committed
/* this destroys the channel and we cannot use it anymore after this */
Curl_resolver_cleanup(data->state.resolver);
Daniel Stenberg
committed
Daniel Stenberg
committed
/* No longer a dirty share, if it exists */
Daniel Stenberg
committed
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
Daniel Stenberg
committed
data->share->dirty--;
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
Daniel Stenberg
committed
if(data->set.wildcardmatch) {
/* destruct wildcard structures if it is needed */
struct WildcardData *wc = &data->wildcard;
Curl_wildcard_dtor(wc);
}
Daniel Stenberg
committed
Curl_freeset(data);
/*
* Initialize the UserDefined fields within a Curl_easy.
* This may be safely called on a new or existing Curl_easy.
*/
CURLcode Curl_init_userdefined(struct UserDefined *set)
{
set->out = stdout; /* default output to stdout */
set->in_set = stdin; /* default input from stdin */
set->err = stderr; /* default stderr to stderr */
/* use fwrite as default function to store output */
set->fwrite_func = (curl_write_callback)fwrite;
/* use fread as default function to read input */
set->fread_func_set = (curl_read_callback)fread;
set->is_fread_set = 0;
set->is_fwrite_set = 0;
set->seek_func = ZERO_NULL;
set->seek_client = ZERO_NULL;
/* conversion callbacks for non-ASCII hosts */
set->convfromnetwork = ZERO_NULL;
set->convtonetwork = ZERO_NULL;
set->convfromutf8 = ZERO_NULL;
set->filesize = -1; /* we don't know the size */
set->postfieldsize = -1; /* unknown size */
set->maxredirs = -1; /* allow any amount by default */
set->httpreq = HTTPREQ_GET; /* Default HTTP request */
Daniel Stenberg
committed
set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
Daniel Stenberg
committed
set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
set->ftp_filemethod = FTPFILE_MULTICWD;
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* Set the default size of the SSL session ID cache */
set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
/* make libcurl quiet by default: */
set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
/*
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
*/
set->ssl.verifypeer = TRUE;
set->ssl.verifyhost = TRUE;
#ifdef USE_TLS_SRP
set->ssl.authtype = CURL_TLSAUTH_NONE;
#endif
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
type */
set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
/* for the *protocols fields we don't use the CURLPROTO_ALL convenience
define since we internally only use the lower 16 bits for the passed
in bitmask to not conflict with the private bits */
set->allowed_protocols = CURLPROTO_ALL;
set->redir_protocols = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
CURLPROTO_SMBS);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* disallow unprotected protection negotiation NEC reference implementation
* seem not to follow rfc1961 section 4.3/4.4
*/
set->socks5_gssapi_nec = FALSE;
#endif
/* This is our preferred CA cert bundle/path since install time */
#if defined(CURL_CA_BUNDLE)
result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
return result;
#endif
#if defined(CURL_CA_PATH)
result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
if(result)
return result;
#endif
set->wildcardmatch = FALSE;
set->chunk_bgn = ZERO_NULL;
set->chunk_end = ZERO_NULL;
/* tcp keepalives are disabled by default, but provide reasonable values for
* the interval and idle times.
*/
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
Curl_http2_init_userset(set);
}
Daniel Stenberg
committed
/**
* Curl_open()
*
* @param curl is a pointer to a sessionhandle pointer that gets set by this
* function.
* @return CURLcode
*/
CURLcode Curl_open(struct Curl_easy **curl)
struct Curl_easy *data;
/* Very simple start-up: alloc the struct, init it with zeroes and return */
data = calloc(1, sizeof(struct Curl_easy));
Daniel Stenberg
committed
/* this is a very serious error */
DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
Daniel Stenberg
committed
return CURLE_OUT_OF_MEMORY;
data->magic = CURLEASY_MAGIC_NUMBER;
result = Curl_resolver_init(&data->state.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
Daniel Stenberg
committed
free(data);
Daniel Stenberg
committed
}
Daniel Stenberg
committed
/* We do some initial setup here, all those fields that can't be just 0 */
data->state.headerbuff = malloc(HEADERSIZE);
if(!data->state.headerbuff) {
DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_init_userdefined(&data->set);
Daniel Stenberg
committed
data->state.headersize=HEADERSIZE;
/* most recent connection is not yet defined */
data->state.lastconnect = NULL;
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
Daniel Stenberg
committed
data->wildcard.state = CURLWC_INIT;
data->wildcard.filelist = NULL;
data->set.fnmatch = ZERO_NULL;
data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
Curl_http2_init_state(&data->state);
}
Curl_resolver_cleanup(data->state.resolver);
Markus Elfring
committed
free(data->state.headerbuff);
Daniel Stenberg
committed
Curl_freeset(data);
free(data);
data = NULL;
}
else
*curl = data;
CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
va_list param)
char *argptr;
Daniel Stenberg
committed
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_HTTP
curl_off_t bigsize;
#endif
switch(option) {
Sterling Hughes
committed
case CURLOPT_DNS_CACHE_TIMEOUT:
data->set.dns_cache_timeout = va_arg(param, long);
Sterling Hughes
committed
break;
/* remember we want this enabled */
data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
case CURLOPT_RANDOM_FILE:
/*
* This is the path name to a file that contains random data to seed
* the random SSL stuff with. The file is only used for reading.
*/
result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
break;
case CURLOPT_EGDSOCKET:
/*
* The Entropy Gathering Daemon socket pathname
*/
result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
break;
case CURLOPT_MAXCONNECTS:
/*
* Set the absolute number of maximum simultaneous alive connection that
* libcurl is allowed to have.
*/
data->set.maxconnects = va_arg(param, long);
break;
case CURLOPT_FORBID_REUSE:
/*
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
*/
data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
/*
* Set to include the header in the general data output stream.
*/
data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
/*
* Shut off the internal supported progress meter
*/
data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
Daniel Stenberg
committed
if(data->set.hide_progress)
else
data->progress.flags &= ~PGRS_HIDE;
/*
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_FAILONERROR:
* Don't output the >=400 error code HTML-page, but instead only
* return error.
*/
data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_KEEP_SENDING_ON_ERROR:
data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
TRUE : FALSE;
break;
case CURLOPT_PUT:
* We want to sent data to the remote host. If this is HTTP, that equals
* using the PUT request.
data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
Daniel Stenberg
committed
if(data->set.upload) {
/* If this is HTTP, PUT is what's needed to "upload" */
Daniel Stenberg
committed
data->set.httpreq = HTTPREQ_PUT;
Daniel Stenberg
committed
data->set.opt_no_body = FALSE; /* this is implied */
}
else
Daniel Stenberg
committed
/* In HTTP, the opposite of upload is GET (unless NOBODY is true as
then this can be changed to HEAD later on) */
data->set.httpreq = HTTPREQ_GET;
/*
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_FTP_CREATE_MISSING_DIRS:
/*
* An FTP option that modifies an upload to create missing directories on
* the server.
switch(va_arg(param, long)) {
case 0:
data->set.ftp_create_missing_dirs = 0;
break;
case 1:
data->set.ftp_create_missing_dirs = 1;
break;
case 2:
data->set.ftp_create_missing_dirs = 2;
break;
default:
/* reserve other values for future use */
result = CURLE_UNKNOWN_OPTION;
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
* Option that specifies how quickly an server response must be obtained
* before it is considered failure. For pingpong protocols.
data->set.server_response_timeout = va_arg(param, long) * 1000;
case CURLOPT_TFTP_NO_OPTIONS:
/*
* Option that prevents libcurl from sending TFTP option requests to the
* server.
*/
data->set.tftp_no_options = va_arg(param, long) != 0;
break;
Daniel Stenberg
committed
case CURLOPT_TFTP_BLKSIZE:
/*
* TFTP option that specifies the block size to use for data transmission.
Daniel Stenberg
committed
*/
data->set.tftp_blksize = va_arg(param, long);
break;
case CURLOPT_DIRLISTONLY:
* An option that changes the command to one that asks for a list
* only, no file info details.
*/
data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_APPEND:
* We want to upload and append to an existing file.
data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_FTP_FILEMETHOD:
/*
* How do access files over FTP.
*/
data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
/*
* Parse the $HOME/.netrc file
*/
data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
case CURLOPT_NETRC_FILE:
/*
* Use this file instead of the $HOME/.netrc file
*/
result = setstropt(&data->set.str[STRING_NETRC_FILE],
case CURLOPT_TRANSFERTEXT:
* This option was previously named 'FTPASCII'. Renamed to work with
* more protocols than merely FTP.
*
* Transfer using ASCII (instead of BINARY).
data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_TIMECONDITION:
/*
* Set HTTP time condition. This must be one of the defines in the
* curl/curl.h header file.
*/
data->set.timecondition = (curl_TimeCond)va_arg(param, long);
/*
* This is the value to compare with the remote document with the
* method set with CURLOPT_TIMECONDITION
*/
data->set.timevalue = (time_t)va_arg(param, long);
/*
* Set explicit SSL version to try to connect with, as some SSL
* implementations are lame.
*/
#ifdef USE_SSL
Daniel Stenberg
committed
data->set.ssl.version = va_arg(param, long);
#else
result = CURLE_UNKNOWN_OPTION;
#endif
#ifndef CURL_DISABLE_HTTP
case CURLOPT_AUTOREFERER:
* Switch on automatic referer that gets set if curl follows locations.
data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_ACCEPT_ENCODING:
* String to use at the value of Accept-Encoding header.
*
* If the encoding is set to "" we use an Accept-Encoding header that
* encompasses all the encodings we support.
* If the encoding is set to NULL we don't send an Accept-Encoding header
* and ignore an received Content-Encoding header.
*
Daniel Stenberg
committed
argptr = va_arg(param, char *);
result = setstropt(&data->set.str[STRING_ENCODING],
break;
case CURLOPT_TRANSFER_ENCODING:
data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
TRUE : FALSE;
case CURLOPT_FOLLOWLOCATION:
* Follow Location: header hints on a HTTP-server.
data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_UNRESTRICTED_AUTH:
* Send authentication (user+password) when following locations, even when
* hostname changed.
data->set.http_disable_hostname_check_before_authentication =
(0 != va_arg(param, long)) ? TRUE : FALSE;
case CURLOPT_MAXREDIRS:
* The maximum amount of hops you allow curl to follow Location:
* headers. This should mostly be used to detect never-ending loops.
data->set.maxredirs = va_arg(param, long);
case CURLOPT_POSTREDIR:
{
* Set the behaviour of POST when redirecting
* CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
* CURL_REDIR_POST_301 - POST is kept as POST after 301
* CURL_REDIR_POST_302 - POST is kept as POST after 302
* CURL_REDIR_POST_303 - POST is kept as POST after 303
* CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
* other - POST is kept as POST after 301 and 302
int postRedir = curlx_sltosi(va_arg(param, long));
data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
}
break;
case CURLOPT_POST:
/* Does this option serve a purpose anymore? Yes it does, when
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
callback! */
Daniel Stenberg
committed
if(va_arg(param, long)) {
data->set.httpreq = HTTPREQ_POST;
Daniel Stenberg
committed
data->set.opt_no_body = FALSE; /* this is implied */
}
else
data->set.httpreq = HTTPREQ_GET;
case CURLOPT_COPYPOSTFIELDS:
Daniel Stenberg
committed
* A string with POST data. Makes curl HTTP POST. Even if it is NULL.
* If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
* CURLOPT_COPYPOSTFIELDS and not altered later.
argptr = va_arg(param, char *);
Daniel Stenberg
committed
if(!argptr || data->set.postfieldsize == -1)
result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);