summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2017-11-10 17:45:54 +0100
committerDaniel Stenberg <daniel@haxx.se>2017-11-10 17:47:47 +0100
commitc6fe6129ce558e1c2e8495542404a2763bbc0e83 (patch)
tree8ad4efe6fdf8c50cd1f9aa5f6c64fe63b051220d
parent3619ee5febb220de917db642352f9ea4fc3e7843 (diff)
downloadcurl-bagder/setopt.c.tar.gz
setopt: split out curl_easy_setopt() to its own filebagder/setopt.c
... to make url.c smaller.
-rw-r--r--lib/Makefile.inc6
-rw-r--r--lib/easy.c60
-rw-r--r--lib/setopt.c2549
-rw-r--r--lib/setopt.h27
-rw-r--r--lib/url.c2556
-rw-r--r--lib/url.h8
6 files changed, 2640 insertions, 2566 deletions
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index a9de05a9c..0a88b8eb8 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2017, 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
@@ -54,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
- mime.c sha256.c
+ mime.c sha256.c setopt.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
@@ -73,7 +73,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
- curl_printf.h system_win32.h rand.h mime.h curl_sha256.h
+ curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h
LIB_RCFILES = libcurl.rc
diff --git a/lib/easy.c b/lib/easy.c
index d8079bb8e..2f5cc7f89 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -71,6 +71,8 @@
#include "multiif.h"
#include "sigpipe.h"
#include "ssh.h"
+#include "setopt.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -364,28 +366,6 @@ struct Curl_easy *curl_easy_init(void)
return data;
}
-/*
- * curl_easy_setopt() is the external interface for setting options on an
- * easy handle.
- */
-
-#undef curl_easy_setopt
-CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
-{
- va_list arg;
- CURLcode result;
-
- if(!data)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- va_start(arg, tag);
-
- result = Curl_setopt(data, tag, arg);
-
- va_end(arg);
- return result;
-}
-
#ifdef CURLDEBUG
struct socketmonitor {
@@ -860,6 +840,40 @@ CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
return result;
}
+static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
+{
+ CURLcode result = CURLE_OK;
+ 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 = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
+ if(result)
+ return result;
+ }
+
+ /* 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;
+}
+
/*
* curl_easy_duphandle() is an external interface to allow duplication of a
* given input easy handle. The returned handle will be a new working handle
@@ -887,7 +901,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->state.headersize = HEADERSIZE;
/* copy all userdefined values */
- if(Curl_dupset(outcurl, data))
+ if(dupset(outcurl, data))
goto fail;
/* the connection cache is setup on demand */
diff --git a/lib/setopt.c b/lib/setopt.c
new file mode 100644
index 000000000..200bfc5ab
--- /dev/null
+++ b/lib/setopt.c
@@ -0,0 +1,2549 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "content_encoding.h"
+#include "strcase.h"
+#include "share.h"
+#include "vtls/vtls.h"
+#include "warnless.h"
+#include "sendf.h"
+#include "http2.h"
+#include "setopt.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+CURLcode Curl_setstropt(char **charp, const char *s)
+{
+ /* Release the previous storage at `charp' and replace by a dynamic storage
+ copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
+
+ Curl_safefree(*charp);
+
+ if(s) {
+ char *str = strdup(s);
+
+ if(!str)
+ return CURLE_OUT_OF_MEMORY;
+
+ *charp = str;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
+{
+ CURLcode result = CURLE_OK;
+ char *user = NULL;
+ char *passwd = NULL;
+
+ /* Parse the login details if specified. It not then we treat NULL as a hint
+ to clear the existing data */
+ if(option) {
+ result = Curl_parse_login_details(option, strlen(option),
+ (userp ? &user : NULL),
+ (passwdp ? &passwd : NULL),
+ NULL);
+ }
+
+ if(!result) {
+ /* Store the username part of option if required */
+ if(userp) {
+ 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;
+ }
+
+ /* Store the password part of option if required */
+ if(passwdp) {
+ Curl_safefree(*passwdp);
+ *passwdp = passwd;
+ }
+ }
+
+ return result;
+}
+
+#define C_SSLVERSION_VALUE(x) (x & 0xffff)
+#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
+
+static CURLcode setopt(struct Curl_easy *data, CURLoption option,
+ va_list param)
+{
+ char *argptr;
+ CURLcode result = CURLE_OK;
+ long arg;
+ curl_off_t bigsize;
+
+ switch(option) {
+ case CURLOPT_DNS_CACHE_TIMEOUT:
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.dns_cache_timeout = arg;
+ break;
+ case CURLOPT_DNS_USE_GLOBAL_CACHE:
+ /* remember we want this enabled */
+ arg = va_arg(param, long);
+ data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
+ break;
+ case CURLOPT_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection for proxy */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
+ va_arg(param, char *));
+ break;
+
+ 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 = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_EGDSOCKET:
+ /*
+ * The Entropy Gathering Daemon socket pathname
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_MAXCONNECTS:
+ /*
+ * Set the absolute number of maximum simultaneous alive connection that
+ * libcurl is allowed to have.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.maxconnects = arg;
+ 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;
+ break;
+ case CURLOPT_VERBOSE:
+ /*
+ * 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;
+ break;
+ case CURLOPT_HEADER:
+ /*
+ * Set to include the header in the general data output stream.
+ */
+ data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_NOPROGRESS:
+ /*
+ * Shut off the internal supported progress meter
+ */
+ data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ if(data->set.hide_progress)
+ data->progress.flags |= PGRS_HIDE;
+ else
+ data->progress.flags &= ~PGRS_HIDE;
+ break;
+ case CURLOPT_NOBODY:
+ /*
+ * 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;
+ break;
+ case CURLOPT_KEEP_SENDING_ON_ERROR:
+ data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+ case CURLOPT_UPLOAD:
+ 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;
+ if(data->set.upload) {
+ /* If this is HTTP, PUT is what's needed to "upload" */
+ data->set.httpreq = HTTPREQ_PUT;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ /* 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;
+ break;
+ case CURLOPT_REQUEST_TARGET:
+ result = Curl_setstropt(&data->set.str[STRING_TARGET],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_FILETIME:
+ /*
+ * 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;
+ break;
+ 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;
+ }
+ 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.
+ */
+ arg = va_arg(param, long);
+ if((arg >= 0) && (arg < (INT_MAX/1000)))
+ data->set.server_response_timeout = arg * 1000;
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
+ 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;
+ case CURLOPT_TFTP_BLKSIZE:
+ /*
+ * TFTP option that specifies the block size to use for data transmission.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.tftp_blksize = arg;
+ 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;
+ break;
+ case CURLOPT_APPEND:
+ /*
+ * We want to upload and append to an existing file.
+ */
+ data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_FTP_FILEMETHOD:
+ /*
+ * How do access files over FTP.
+ */
+ arg = va_arg(param, long);
+ if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.ftp_filemethod = (curl_ftpfile)arg;
+ break;
+ case CURLOPT_NETRC:
+ /*
+ * Parse the $HOME/.netrc file
+ */
+ arg = va_arg(param, long);
+ if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
+ break;
+ case CURLOPT_NETRC_FILE:
+ /*
+ * Use this file instead of the $HOME/.netrc file
+ */
+ result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
+ va_arg(param, char *));
+ break;
+ 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.
+ */
+ arg = va_arg(param, long);
+ if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.timecondition = (curl_TimeCond)arg;
+ break;
+ case CURLOPT_TIMEVALUE:
+ /*
+ * 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);
+ break;
+ case CURLOPT_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with, as some SSL
+ * implementations are lame.
+ */
+#ifdef USE_SSL
+ arg = va_arg(param, long);
+ if((arg < CURL_SSLVERSION_DEFAULT) || (arg > CURL_SSLVERSION_TLSv1_3))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg);
+ data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
+#else
+ result = CURLE_UNKNOWN_OPTION;
+#endif
+ break;
+ case CURLOPT_PROXY_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with for proxy, as some SSL
+ * implementations are lame.
+ */
+#ifdef USE_SSL
+ arg = va_arg(param, long);
+ if((arg < CURL_SSLVERSION_DEFAULT) || (arg > CURL_SSLVERSION_TLSv1_3))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg);
+ data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
+#else
+ result = CURLE_UNKNOWN_OPTION;
+#endif
+ break;
+
+#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;
+ break;
+
+ 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.
+ *
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && !*argptr) {
+ argptr = Curl_all_content_encodings();
+ if(!argptr)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ free(argptr);
+ }
+ }
+ else
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ break;
+
+ case CURLOPT_TRANSFER_ENCODING:
+ data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+
+ case CURLOPT_FOLLOWLOCATION:
+ /*
+ * Follow Location: header hints on a HTTP-server.
+ */
+ data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ 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;
+ break;
+
+ 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.
+ */
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.maxredirs = arg;
+ break;
+
+ 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
+ */
+ arg = va_arg(param, long);
+ if(arg < CURL_REDIR_GET_ALL)
+ /* no return error on too high numbers since the bitmask could be
+ extended in a future */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.keep_post = arg & 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! */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_POST;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ data->set.httpreq = HTTPREQ_GET;
+ break;
+
+ case CURLOPT_COPYPOSTFIELDS:
+ /*
+ * 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 *);
+
+ if(!argptr || data->set.postfieldsize == -1)
+ result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
+ else {
+ /*
+ * Check that requested length does not overflow the size_t type.
+ */
+
+ if((data->set.postfieldsize < 0) ||
+ ((sizeof(curl_off_t) != sizeof(size_t)) &&
+ (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ char *p;
+
+ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+
+ /* Allocate even when size == 0. This satisfies the need of possible
+ later address compare to detect the COPYPOSTFIELDS mode, and
+ to mark that postfields is used rather than read function or
+ form data.
+ */
+ p = malloc((size_t)(data->set.postfieldsize?
+ data->set.postfieldsize:1));
+
+ if(!p)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ if(data->set.postfieldsize)
+ memcpy(p, argptr, (size_t)data->set.postfieldsize);
+
+ data->set.str[STRING_COPYPOSTFIELDS] = p;
+ }
+ }
+ }
+
+ data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDS:
+ /*
+ * Like above, but use static data instead of copying it.
+ */
+ data->set.postfields = va_arg(param, void *);
+ /* Release old copied data. */
+ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, long);
+ if(bigsize < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE_LARGE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_HTTPPOST:
+ /*
+ * Set to make us do HTTP POST
+ */
+ data->set.httppost = va_arg(param, struct curl_httppost *);
+ data->set.httpreq = HTTPREQ_POST_FORM;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ break;
+#endif /* CURL_DISABLE_HTTP */
+
+ case CURLOPT_MIMEPOST:
+ /*
+ * Set to make us do MIME/form POST
+ */
+ result = Curl_mime_set_subparts(&data->set.mimepost,
+ va_arg(param, curl_mime *), FALSE);
+ if(!result) {
+ data->set.httpreq = HTTPREQ_POST_MIME;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_REFERER:
+ /*
+ * String to set in the HTTP Referer: field.
+ */
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
+ va_arg(param, char *));
+ data->change.referer = data->set.str[STRING_SET_REFERER];
+ break;
+
+ case CURLOPT_USERAGENT:
+ /*
+ * String to use in the HTTP User-Agent field
+ */
+ result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+
+#ifndef CURL_DISABLE_HTTP
+ case CURLOPT_PROXYHEADER:
+ /*
+ * Set a list with proxy headers to use (or replace internals with)
+ *
+ * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
+ * long time we remain doing it this way until CURLOPT_PROXYHEADER is
+ * used. As soon as this option has been used, if set to anything but
+ * NULL, custom headers for proxies are only picked from this list.
+ *
+ * Set this option to NULL to restore the previous behavior.
+ */
+ data->set.proxyheaders = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_HEADEROPT:
+ /*
+ * Set header option.
+ */
+ arg = va_arg(param, long);
+ data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
+ break;
+
+ case CURLOPT_HTTP200ALIASES:
+ /*
+ * Set a list of aliases for HTTP 200 in response header
+ */
+ data->set.http200aliases = va_arg(param, struct curl_slist *);
+ break;
+
+#if !defined(CURL_DISABLE_COOKIES)
+ case CURLOPT_COOKIE:
+ /*
+ * Cookie string to send to the remote server in the request.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_COOKIE],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_COOKIEFILE:
+ /*
+ * Set cookie file to read and parse. Can be used multiple times.
+ */
+ argptr = (char *)va_arg(param, void *);
+ if(argptr) {
+ struct curl_slist *cl;
+ /* append the cookie file name to the list of file names, and deal with
+ them later */
+ cl = curl_slist_append(data->change.cookielist, argptr);
+ if(!cl) {
+ curl_slist_free_all(data->change.cookielist);
+ data->change.cookielist = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->change.cookielist = cl; /* store the list for later use */
+ }
+ break;
+
+ case CURLOPT_COOKIEJAR:
+ /*
+ * Set cookie file name to dump all cookies to when we're done.
+ */
+ {
+ struct CookieInfo *newcookies;
+ result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
+ va_arg(param, char *));
+
+ /*
+ * Activate the cookie parser. This may or may not already
+ * have been made.
+ */
+ newcookies = Curl_cookie_init(data, NULL, data->cookies,
+ data->set.cookiesession);
+ if(!newcookies)
+ result = CURLE_OUT_OF_MEMORY;
+ data->cookies = newcookies;
+ }
+ break;
+
+ case CURLOPT_COOKIESESSION:
+ /*
+ * Set this option to TRUE to start a new "cookie session". It will
+ * prevent the forthcoming read-cookies-from-file actions to accept
+ * cookies that are marked as being session cookies, as they belong to a
+ * previous session.
+ *
+ * In the original Netscape cookie spec, "session cookies" are cookies
+ * with no expire date set. RFC2109 describes the same action if no
+ * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
+ * a 'Discard' action that can enforce the discard even for cookies that
+ * have a Max-Age.
+ *
+ * We run mostly with the original cookie spec, as hardly anyone implements
+ * anything else.
+ */
+ data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_COOKIELIST:
+ argptr = va_arg(param, char *);
+
+ if(argptr == NULL)
+ break;
+
+ if(strcasecompare(argptr, "ALL")) {
+ /* clear all cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearall(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(strcasecompare(argptr, "SESS")) {
+ /* clear session cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearsess(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(strcasecompare(argptr, "FLUSH")) {
+ /* flush cookies to file, takes care of the locking */
+ Curl_flush_cookies(data, 0);
+ }
+ else if(strcasecompare(argptr, "RELOAD")) {
+ /* reload cookies from file */
+ Curl_cookie_loadfiles(data);
+ break;
+ }
+ else {
+ if(!data->cookies)
+ /* if cookie engine was not running, activate it */
+ data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+
+ argptr = strdup(argptr);
+ if(!argptr || !data->cookies) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(argptr);
+ }
+ else {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(checkprefix("Set-Cookie:", argptr))
+ /* HTTP Header format line */
+ Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+
+ else
+ /* Netscape format line */
+ Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ free(argptr);
+ }
+ }
+
+ break;
+#endif /* !CURL_DISABLE_COOKIES */
+
+ case CURLOPT_HTTPGET:
+ /*
+ * Set to force us do HTTP GET
+ */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_GET;
+ data->set.upload = FALSE; /* switch off upload */
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_HTTP_VERSION:
+ /*
+ * This sets a requested HTTP version to be used. The value is one of
+ * the listed enums in curl/curl.h.
+ */
+ arg = va_arg(param, long);
+ if(arg < CURL_HTTP_VERSION_NONE)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#ifndef USE_NGHTTP2
+ if(arg >= CURL_HTTP_VERSION_2)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#else
+ if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ data->set.httpversion = arg;
+ break;
+
+ case CURLOPT_EXPECT_100_TIMEOUT_MS:
+ /*
+ * Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.expect_100_timeout = arg;
+ break;
+
+#endif /* CURL_DISABLE_HTTP */
+
+ case CURLOPT_HTTPAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.httpauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.httpauth = auth;
+ }
+ break;
+
+ case CURLOPT_CUSTOMREQUEST:
+ /*
+ * Set a custom string to use as request
+ */
+ result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
+ va_arg(param, char *));
+
+ /* we don't set
+ data->set.httpreq = HTTPREQ_CUSTOM;
+ here, we continue as if we were using the already set type
+ and this just changes the actual request keyword */
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_HTTPPROXYTUNNEL:
+ /*
+ * Tunnel operations through the proxy instead of normal proxy use
+ */
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+
+ case CURLOPT_PROXYPORT:
+ /*
+ * Explicitly set HTTP proxy port number.
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.proxyport = arg;
+ break;
+
+ case CURLOPT_PROXYAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.proxyauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.proxyauth = auth;
+ }
+ break;
+
+ case CURLOPT_PROXY:
+ /*
+ * Set proxy server:port to use as proxy.
+ *
+ * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+ * we explicitly say that we don't want to use a proxy
+ * (even though there might be environment variables saying so).
+ *
+ * Setting it to NULL, means no proxy but allows the environment variables
+ * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PROXY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PRE_PROXY:
+ /*
+ * Set proxy server:port to use as SOCKS proxy.
+ *
+ * If the proxy is set to "" or NULL we explicitly say that we don't want
+ * to use the socks proxy.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PROXYTYPE:
+ /*
+ * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+ */
+ arg = va_arg(param, long);
+ if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.proxytype = (curl_proxytype)arg;
+ break;
+
+ case CURLOPT_PROXY_TRANSFER_MODE:
+ /*
+ * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
+ */
+ switch(va_arg(param, long)) {
+ case 0:
+ data->set.proxy_transfer_mode = FALSE;
+ break;
+ case 1:
+ data->set.proxy_transfer_mode = TRUE;
+ break;
+ default:
+ /* reserve other values for future use */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+ break;
+#endif /* CURL_DISABLE_PROXY */
+
+ case CURLOPT_SOCKS5_AUTH:
+ data->set.socks5auth = va_arg(param, unsigned long);
+ if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
+ result = CURLE_NOT_BUILT_IN;
+ break;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ case CURLOPT_SOCKS5_GSSAPI_NEC:
+ /*
+ * Set flag for NEC SOCK5 support
+ */
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+ case CURLOPT_PROXY_SERVICE_NAME:
+ /*
+ * Set proxy authentication service name for Kerberos 5 and SPNEGO
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
+ va_arg(param, char *));
+ break;
+#endif
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_SPNEGO)
+ case CURLOPT_SERVICE_NAME:
+ /*
+ * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME],
+ va_arg(param, char *));
+ break;
+
+#endif
+
+ case CURLOPT_HEADERDATA:
+ /*
+ * Custom pointer to pass the header write callback function
+ */
+ data->set.writeheader = (void *)va_arg(param, void *);
+ break;
+ case CURLOPT_ERRORBUFFER:
+ /*
+ * Error buffer provided by the caller to get the human readable
+ * error string in.
+ */
+ data->set.errorbuffer = va_arg(param, char *);
+ break;
+ case CURLOPT_WRITEDATA:
+ /*
+ * FILE pointer to write to. Or possibly
+ * used as argument to the write callback.
+ */
+ data->set.out = va_arg(param, void *);
+ break;
+ case CURLOPT_FTPPORT:
+ /*
+ * Use FTP PORT, this also specifies which IP address to use
+ */
+ result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
+ va_arg(param, char *));
+ data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPRT:
+ data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPSV:
+ data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_PRET:
+ data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_SSL_CCC:
+ arg = va_arg(param, long);
+ if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.ftp_ccc = (curl_ftpccc)arg;
+ break;
+
+ case CURLOPT_FTP_SKIP_PASV_IP:
+ /*
+ * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
+ * bypass of the IP address in PASV responses.
+ */
+ data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_READDATA:
+ /*
+ * FILE pointer to read the file to be uploaded from. Or possibly
+ * used as argument to the read callback.
+ */
+ data->set.in_set = va_arg(param, void *);
+ break;
+ case CURLOPT_INFILESIZE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.filesize = arg;
+ break;
+ case CURLOPT_INFILESIZE_LARGE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.filesize = bigsize;
+ break;
+ case CURLOPT_LOW_SPEED_LIMIT:
+ /*
+ * The low speed limit that if transfers are below this for
+ * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.low_speed_limit = arg;
+ break;
+ case CURLOPT_MAX_SEND_SPEED_LARGE:
+ /*
+ * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
+ * bytes per second the transfer is throttled..
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.max_send_speed = bigsize;
+ break;
+ case CURLOPT_MAX_RECV_SPEED_LARGE:
+ /*
+ * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
+ * second the transfer is throttled..
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.max_recv_speed = bigsize;
+ break;
+ case CURLOPT_LOW_SPEED_TIME:
+ /*
+ * The low speed time that if transfers are below the set
+ * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.low_speed_time = arg;
+ break;
+ case CURLOPT_URL:
+ /*
+ * The URL to fetch.
+ */
+ if(data->change.url_alloc) {
+ /* the already set URL is allocated, free it first! */
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ result = Curl_setstropt(&data->set.str[STRING_SET_URL],
+ va_arg(param, char *));
+ data->change.url = data->set.str[STRING_SET_URL];
+ break;
+ case CURLOPT_PORT:
+ /*
+ * The port number to use when getting the URL
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.use_port = arg;
+ break;
+ case CURLOPT_TIMEOUT:
+ /*
+ * The maximum time you allow curl to use for a single transfer
+ * operation.
+ */
+ arg = va_arg(param, long);
+ if((arg >= 0) && (arg < (INT_MAX/1000)))
+ data->set.timeout = arg * 1000;
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
+
+ case CURLOPT_TIMEOUT_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.timeout = arg;
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT:
+ /*
+ * The maximum time you allow curl to use to connect.
+ */
+ arg = va_arg(param, long);
+ if((arg >= 0) && (arg < (INT_MAX/1000)))
+ data->set.connecttimeout = arg * 1000;
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.connecttimeout = arg;
+ break;
+
+ case CURLOPT_ACCEPTTIMEOUT_MS:
+ /*
+ * The maximum time you allow curl to wait for server connect
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.accepttimeout = arg;
+ break;
+
+ case CURLOPT_USERPWD:
+ /*
+ * user:password to use in the operation
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_USERNAME],
+ &data->set.str[STRING_PASSWORD]);
+ break;
+
+ case CURLOPT_USERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_USERNAME],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PASSWORD],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_LOGIN_OPTIONS:
+ /*
+ * authentication options to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_OPTIONS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_XOAUTH2_BEARER:
+ /*
+ * OAuth 2.0 bearer token to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_BEARER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_POSTQUOTE:
+ /*
+ * List of RAW FTP commands to use after a transfer
+ */
+ data->set.postquote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_PREQUOTE:
+ /*
+ * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
+ */
+ data->set.prequote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_QUOTE:
+ /*
+ * List of RAW FTP commands to use before a transfer
+ */
+ data->set.quote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_RESOLVE:
+ /*
+ * List of NAME:[address] names to populate the DNS cache with
+ * Prefix the NAME with dash (-) to _remove_ the name from the cache.
+ *
+ * Names added with this API will remain in the cache until explicitly
+ * removed or the handle is cleaned up.
+ *
+ * This API can remove any name from the DNS cache, but only entries
+ * that aren't actually in use right now will be pruned immediately.
+ */
+ data->set.resolve = va_arg(param, struct curl_slist *);
+ data->change.resolve = data->set.resolve;
+ break;
+ case CURLOPT_PROGRESSFUNCTION:
+ /*
+ * Progress callback function
+ */
+ data->set.fprogress = va_arg(param, curl_progress_callback);
+ if(data->set.fprogress)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+ break;
+
+ case CURLOPT_XFERINFOFUNCTION:
+ /*
+ * Transfer info callback function
+ */
+ data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
+ if(data->set.fxferinfo)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+
+ break;
+
+ case CURLOPT_PROGRESSDATA:
+ /*
+ * Custom client data to pass to the progress callback
+ */
+ data->set.progress_client = va_arg(param, void *);
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_PROXYUSERPWD:
+ /*
+ * user:password needed to use the proxy
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_PROXYUSERNAME],
+ &data->set.str[STRING_PROXYPASSWORD]);
+ break;
+ case CURLOPT_PROXYUSERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXYPASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_NOPROXY:
+ /*
+ * proxy exception list
+ */
+ result = Curl_setstropt(&data->set.str[STRING_NOPROXY],
+ va_arg(param, char *));
+ break;
+#endif
+
+ case CURLOPT_RANGE:
+ /*
+ * What range of the file you want to transfer
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_RESUME_FROM:
+ /*
+ * Resume transfer at the given file position
+ */
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.set_resume_from = arg;
+ break;
+ case CURLOPT_RESUME_FROM_LARGE:
+ /*
+ * Resume transfer at the given file position
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.set_resume_from = bigsize;
+ break;
+ case CURLOPT_DEBUGFUNCTION:
+ /*
+ * stderr write callback.
+ */
+ data->set.fdebug = va_arg(param, curl_debug_callback);
+ /*
+ * if the callback provided is NULL, it'll use the default callback
+ */
+ break;
+ case CURLOPT_DEBUGDATA:
+ /*
+ * Set to a void * that should receive all error writes. This
+ * defaults to CURLOPT_STDERR for normal operations.
+ */
+ data->set.debugdata = va_arg(param, void *);
+ break;
+ case CURLOPT_STDERR:
+ /*
+ * Set to a FILE * that should receive all error writes. This
+ * defaults to stderr for normal operations.
+ */
+ data->set.err = va_arg(param, FILE *);
+ if(!data->set.err)
+ data->set.err = stderr;
+ break;
+ case CURLOPT_HEADERFUNCTION:
+ /*
+ * Set header write callback
+ */
+ data->set.fwrite_header = va_arg(param, curl_write_callback);
+ break;
+ case CURLOPT_WRITEFUNCTION:
+ /*
+ * Set data write callback
+ */
+ data->set.fwrite_func = va_arg(param, curl_write_callback);
+ if(!data->set.fwrite_func) {
+ data->set.is_fwrite_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fwrite_func = (curl_write_callback)fwrite;
+ }
+ else
+ data->set.is_fwrite_set = 1;
+ break;
+ case CURLOPT_READFUNCTION:
+ /*
+ * Read data callback
+ */
+ data->set.fread_func_set = va_arg(param, curl_read_callback);
+ if(!data->set.fread_func_set) {
+ data->set.is_fread_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fread_func_set = (curl_read_callback)fread;
+ }
+ else
+ data->set.is_fread_set = 1;
+ break;
+ case CURLOPT_SEEKFUNCTION:
+ /*
+ * Seek callback. Might be NULL.
+ */
+ data->set.seek_func = va_arg(param, curl_seek_callback);
+ break;
+ case CURLOPT_SEEKDATA:
+ /*
+ * Seek control callback. Might be NULL.
+ */
+ data->set.seek_client = va_arg(param, void *);
+ break;
+ case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
+ /*
+ * "Convert from network encoding" callback
+ */
+ data->set.convfromnetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_TO_NETWORK_FUNCTION:
+ /*
+ * "Convert to network encoding" callback
+ */
+ data->set.convtonetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_FROM_UTF8_FUNCTION:
+ /*
+ * "Convert from UTF-8 encoding" callback
+ */
+ data->set.convfromutf8 = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_IOCTLFUNCTION:
+ /*
+ * I/O control callback. Might be NULL.
+ */
+ data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
+ break;
+ case CURLOPT_IOCTLDATA:
+ /*
+ * I/O control data pointer. Might be NULL.
+ */
+ data->set.ioctl_client = va_arg(param, void *);
+ break;
+ case CURLOPT_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use
+ */
+ result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use for proxy
+ */
+ result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use
+ */
+ result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use for proxy
+ */
+ result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use for proxy
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use for proxy
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_KEYPASSWD:
+ /*
+ * String that holds the SSL or SSH private key password.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_KEYPASSWD:
+ /*
+ * String that holds the SSL private key password for proxy.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLENGINE:
+ /*
+ * String that holds the SSL crypto engine.
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && argptr[0])
+ result = Curl_ssl_set_engine(data, argptr);
+ break;
+
+ case CURLOPT_SSLENGINE_DEFAULT:
+ /*
+ * flag to set engine as default.
+ */
+ result = Curl_ssl_set_engine_default(data);
+ break;
+ case CURLOPT_CRLF:
+ /*
+ * Kludgy option to enable CRLF conversions. Subject for removal.
+ */
+ data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_INTERFACE:
+ /*
+ * Set what interface or address/hostname to bind the socket to when
+ * performing an operation and thus what from-IP your connection will use.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_DEVICE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_LOCALPORT:
+ /*
+ * Set what local port to bind the socket to when performing an operation.
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.localport = curlx_sltous(arg);
+ break;
+ case CURLOPT_LOCALPORTRANGE:
+ /*
+ * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.localportrange = curlx_sltosi(arg);
+ break;
+ case CURLOPT_KRBLEVEL:
+ /*
+ * A string that defines the kerberos security level.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
+ va_arg(param, char *));
+ data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
+ break;
+ case CURLOPT_GSSAPI_DELEGATION:
+ /*
+ * GSS-API credential delegation bitmask
+ */
+ arg = va_arg(param, long);
+ if(arg < CURLGSSAPI_DELEGATION_NONE)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.gssapi_delegation = arg;
+ break;
+ case CURLOPT_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying.
+ */
+ data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+
+ /* Update the current connection ssl_config. */
+ if(data->easy_conn) {
+ data->easy_conn->ssl_config.verifypeer =
+ data->set.ssl.primary.verifypeer;
+ }
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying for proxy.
+ */
+ data->set.proxy_ssl.primary.verifypeer =
+ (0 != va_arg(param, long))?TRUE:FALSE;
+
+ /* Update the current connection proxy_ssl_config. */
+ if(data->easy_conn) {
+ data->easy_conn->proxy_ssl_config.verifypeer =
+ data->set.proxy_ssl.primary.verifypeer;
+ }
+ break;
+ case CURLOPT_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+
+ /* Update the current connection ssl_config. */
+ if(data->easy_conn) {
+ data->easy_conn->ssl_config.verifyhost =
+ data->set.ssl.primary.verifyhost;
+ }
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate for proxy
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
+
+ /* Update the current connection proxy_ssl_config. */
+ if(data->easy_conn) {
+ data->easy_conn->proxy_ssl_config.verifyhost =
+ data->set.proxy_ssl.primary.verifyhost;
+ }
+ break;
+ case CURLOPT_SSL_VERIFYSTATUS:
+ /*
+ * Enable certificate status verifying.
+ */
+ if(!Curl_ssl_cert_status_request()) {
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+
+ /* Update the current connection ssl_config. */
+ if(data->easy_conn) {
+ data->easy_conn->ssl_config.verifystatus =
+ data->set.ssl.primary.verifystatus;
+ }
+ break;
+ case CURLOPT_SSL_CTX_FUNCTION:
+ /*
+ * Set a SSL_CTX callback
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_ssl_ctx)
+ data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_SSL_CTX_DATA:
+ /*
+ * Set a SSL_CTX callback parameter pointer
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_ssl_ctx)
+ data->set.ssl.fsslctxp = va_arg(param, void *);
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_SSL_FALSESTART:
+ /*
+ * Enable TLS false start.
+ */
+ if(!Curl_ssl_false_start()) {
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_CERTINFO:
+#ifdef USE_SSL
+ if(Curl_ssl->have_certinfo)
+ data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_PINNEDPUBLICKEY:
+ /*
+ * Set pinned public key for SSL connection.
+ * Specify file name of the public key in DER format.
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_pinnedpubkey)
+ result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ va_arg(param, char *));
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_PROXY_PINNEDPUBLICKEY:
+ /*
+ * Set pinned public key for SSL connection.
+ * Specify file name of the public key in DER format.
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_pinnedpubkey)
+ result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
+ va_arg(param, char *));
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_CAINFO:
+ /*
+ * Set CA info for SSL connection. Specify file name of the CA certificate
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CAINFO:
+ /*
+ * Set CA info SSL connection for proxy. Specify file name of the
+ * CA certificate
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_CAPATH:
+ /*
+ * Set CA path info for SSL connection. Specify directory name of the CA
+ * certificates which have been prepared using openssl c_rehash utility.
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_ca_path)
+ /* This does not work on windows. */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ va_arg(param, char *));
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_PROXY_CAPATH:
+ /*
+ * Set CA path info for SSL connection proxy. Specify directory name of the
+ * CA certificates which have been prepared using openssl c_rehash utility.
+ */
+#ifdef USE_SSL
+ if(Curl_ssl->have_ca_path)
+ /* This does not work on windows. */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
+ va_arg(param, char *));
+ else
+#endif
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection. Specify file name of the CRL
+ * to check certificates revocation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection for proxy. Specify file name of the
+ * CRL to check certificates revocation
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_ISSUERCERT:
+ /*
+ * Set Issuer certificate file
+ * to check certificates issuer
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_TELNETOPTIONS:
+ /*
+ * Set a linked list of telnet options
+ */
+ data->set.telnet_options = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_BUFFERSIZE:
+ /*
+ * The application kindly asks for a differently sized receive buffer.
+ * If it seems reasonable, we'll use it.
+ */
+ arg = va_arg(param, long);
+
+ if(arg > READBUFFER_MAX)
+ arg = READBUFFER_MAX;
+ else if(arg < 1)
+ arg = READBUFFER_SIZE;
+ else if(arg < READBUFFER_MIN)
+ arg = READBUFFER_MIN;
+
+ /* Resize if new size */
+ if(arg != data->set.buffer_size) {
+ char *newbuff = realloc(data->state.buffer, arg + 1);
+ if(!newbuff) {
+ DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else
+ data->state.buffer = newbuff;
+ }
+ data->set.buffer_size = arg;
+
+ break;
+
+ case CURLOPT_NOSIGNAL:
+ /*
+ * The application asks not to set any signal() or alarm() handlers,
+ * even when using a timeout.
+ */
+ data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_SHARE:
+ {
+ struct Curl_share *set;
+ set = va_arg(param, struct Curl_share *);
+
+ /* disconnect from old share, if any */
+ if(data->share) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(data->dns.hostcachetype == HCACHE_SHARED) {
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies == data->cookies)
+ data->cookies = NULL;
+#endif
+
+ if(data->share->sslsession == data->state.session)
+ data->state.session = NULL;
+
+ data->share->dirty--;
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+ data->share = NULL;
+ }
+
+ /* use new share if it set */
+ data->share = set;
+ if(data->share) {
+
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ data->share->dirty++;
+
+ if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
+ /* use shared host cache */
+ data->dns.hostcache = &data->share->hostcache;
+ data->dns.hostcachetype = HCACHE_SHARED;
+ }
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies) {
+ /* use shared cookie list, first free own one if any */
+ Curl_cookie_cleanup(data->cookies);
+ /* enable cookies since we now use a share that uses cookies! */
+ data->cookies = data->share->cookies;
+ }
+#endif /* CURL_DISABLE_HTTP */
+ if(data->share->sslsession) {
+ data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+ data->state.session = data->share->sslsession;
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+
+ }
+ /* check for host cache not needed,
+ * it will be done by curl_easy_perform */
+ }
+ break;
+
+ case CURLOPT_PRIVATE:
+ /*
+ * Set private data pointer.
+ */
+ data->set.private_data = va_arg(param, void *);
+ break;
+
+ case CURLOPT_MAXFILESIZE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.max_filesize = arg;
+ break;
+
+#ifdef USE_SSL
+ case CURLOPT_USE_SSL:
+ /*
+ * Make transfers attempt to use SSL/TLS.
+ */
+ arg = va_arg(param, long);
+ if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.use_ssl = (curl_usessl)arg;
+ break;
+
+ case CURLOPT_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ break;
+
+ case CURLOPT_PROXY_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ break;
+
+#endif
+ case CURLOPT_FTPSSLAUTH:
+ /*
+ * Set a specific auth for FTP-SSL transfers.
+ */
+ arg = va_arg(param, long);
+ if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.ftpsslauth = (curl_ftpauth)arg;
+ break;
+
+ case CURLOPT_IPRESOLVE:
+ arg = va_arg(param, long);
+ if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.ipver = arg;
+ break;
+
+ case CURLOPT_MAXFILESIZE_LARGE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ bigsize = va_arg(param, curl_off_t);
+ if(bigsize < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.max_filesize = bigsize;
+ break;
+
+ case CURLOPT_TCP_NODELAY:
+ /*
+ * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
+ * algorithm
+ */
+ data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_ACCOUNT:
+ result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_IGNORE_CONTENT_LENGTH:
+ data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_CONNECT_ONLY:
+ /*
+ * No data transfer, set up connection and let application use the socket
+ */
+ data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+ result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SOCKOPTFUNCTION:
+ /*
+ * socket callback function: called after socket() but before connect()
+ */
+ data->set.fsockopt = va_arg(param, curl_sockopt_callback);
+ break;
+
+ case CURLOPT_SOCKOPTDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.sockopt_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_OPENSOCKETFUNCTION:
+ /*
+ * open/create socket callback function: called instead of socket(),
+ * before connect()
+ */
+ data->set.fopensocket = va_arg(param, curl_opensocket_callback);
+ break;
+
+ case CURLOPT_OPENSOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.opensocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_CLOSESOCKETFUNCTION:
+ /*
+ * close socket callback function: called instead of close()
+ * when shutting down a connection
+ */
+ data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
+ break;
+
+ case CURLOPT_CLOSESOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.closesocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_SSL_SESSIONID_CACHE:
+ data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
+ break;
+
+#ifdef USE_LIBSSH2
+ /* we only include SSH options if explicitly built to support SSH */
+ case CURLOPT_SSH_AUTH_TYPES:
+ data->set.ssh_auth_types = va_arg(param, long);
+ break;
+
+ case CURLOPT_SSH_PUBLIC_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa.pub file
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_PRIVATE_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa file
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+ /*
+ * Option to allow for the MD5 of the host public key to be checked
+ * for validation purposes.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
+ va_arg(param, char *));
+ break;
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ case CURLOPT_SSH_KNOWNHOSTS:
+ /*
+ * Store the file name to read known hosts from.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_KEYFUNCTION:
+ /* setting to NULL is fine since the ssh.c functions themselves will
+ then rever to use the internal default */
+ data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
+ break;
+
+ case CURLOPT_SSH_KEYDATA:
+ /*
+ * Custom client data to pass to the SSH keyfunc callback
+ */
+ data->set.ssh_keyfunc_userp = va_arg(param, void *);
+ break;
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+#endif /* USE_LIBSSH2 */
+
+ case CURLOPT_HTTP_TRANSFER_DECODING:
+ /*
+ * disable libcurl transfer encoding is used
+ */
+ data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_HTTP_CONTENT_DECODING:
+ /*
+ * raw data passed to the application when content encoding is used
+ */
+ data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_NEW_FILE_PERMS:
+ /*
+ * Uses these permissions instead of 0644
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 0777))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.new_file_perms = arg;
+ break;
+
+ case CURLOPT_NEW_DIRECTORY_PERMS:
+ /*
+ * Uses these permissions instead of 0755
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 0777))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.new_directory_perms = arg;
+ break;
+
+ case CURLOPT_ADDRESS_SCOPE:
+ /*
+ * We always get longs when passed plain numericals, but for this value we
+ * know that an unsigned int will always hold the value so we blindly
+ * typecast to this type
+ */
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 0xf))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.scope_id = curlx_sltoui(arg);
+ break;
+
+ case CURLOPT_PROTOCOLS:
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ data->set.allowed_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_REDIR_PROTOCOLS:
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ data->set.redir_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_DEFAULT_PROTOCOL:
+ /* Set the protocol to use when the URL doesn't include any protocol */
+ result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_FROM:
+ /* Set the SMTP mail originator */
+ result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_AUTH:
+ /* Set the SMTP auth originator */
+ result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_RCPT:
+ /* Set the list of mail recipients */
+ data->set.mail_rcpt = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_SASL_IR:
+ /* Enable/disable SASL initial response */
+ data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_RTSP_REQUEST:
+ {
+ /*
+ * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
+ * Would this be better if the RTSPREQ_* were just moved into here?
+ */
+ long curl_rtspreq = va_arg(param, long);
+ Curl_RtspReq rtspreq = RTSPREQ_NONE;
+ switch(curl_rtspreq) {
+ case CURL_RTSPREQ_OPTIONS:
+ rtspreq = RTSPREQ_OPTIONS;
+ break;
+
+ case CURL_RTSPREQ_DESCRIBE:
+ rtspreq = RTSPREQ_DESCRIBE;
+ break;
+
+ case CURL_RTSPREQ_ANNOUNCE:
+ rtspreq = RTSPREQ_ANNOUNCE;
+ break;
+
+ case CURL_RTSPREQ_SETUP:
+ rtspreq = RTSPREQ_SETUP;
+ break;
+
+ case CURL_RTSPREQ_PLAY:
+ rtspreq = RTSPREQ_PLAY;
+ break;
+
+ case CURL_RTSPREQ_PAUSE:
+ rtspreq = RTSPREQ_PAUSE;
+ break;
+
+ case CURL_RTSPREQ_TEARDOWN:
+ rtspreq = RTSPREQ_TEARDOWN;
+ break;
+
+ case CURL_RTSPREQ_GET_PARAMETER:
+ rtspreq = RTSPREQ_GET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_SET_PARAMETER:
+ rtspreq = RTSPREQ_SET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_RECORD:
+ rtspreq = RTSPREQ_RECORD;
+ break;
+
+ case CURL_RTSPREQ_RECEIVE:
+ rtspreq = RTSPREQ_RECEIVE;
+ break;
+ default:
+ rtspreq = RTSPREQ_NONE;
+ }
+
+ data->set.rtspreq = rtspreq;
+ break;
+ }
+
+
+ case CURLOPT_RTSP_SESSION_ID:
+ /*
+ * Set the RTSP Session ID manually. Useful if the application is
+ * resuming a previously established RTSP session
+ */
+ result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_STREAM_URI:
+ /*
+ * Set the Stream URI for the RTSP request. Unless the request is
+ * for generic server options, the application will need to set this.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_TRANSPORT:
+ /*
+ * The content of the Transport: header for the RTSP request
+ */
+ result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_CLIENT_CSEQ:
+ /*
+ * Set the CSEQ number to issue for the next RTSP request. Useful if the
+ * application is resuming a previously broken connection. The CSEQ
+ * will increment from this new number henceforth.
+ */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_RTSP_SERVER_CSEQ:
+ /* Same as the above, but for server-initiated requests */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_INTERLEAVEDATA:
+ data->set.rtp_out = va_arg(param, void *);
+ break;
+ case CURLOPT_INTERLEAVEFUNCTION:
+ /* Set the user defined RTP write function */
+ data->set.fwrite_rtp = va_arg(param, curl_write_callback);
+ break;
+
+ case CURLOPT_WILDCARDMATCH:
+ data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_CHUNK_BGN_FUNCTION:
+ data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
+ break;
+ case CURLOPT_CHUNK_END_FUNCTION:
+ data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
+ break;
+ case CURLOPT_FNMATCH_FUNCTION:
+ data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
+ break;
+ case CURLOPT_CHUNK_DATA:
+ data->wildcard.customptr = va_arg(param, void *);
+ break;
+ case CURLOPT_FNMATCH_DATA:
+ data->set.fnmatch_data = va_arg(param, void *);
+ break;
+#ifdef USE_TLS_SRP
+ case CURLOPT_TLSAUTH_USERNAME:
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_PROXY_TLSAUTH_USERNAME:
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_PASSWORD:
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_TYPE:
+ argptr = va_arg(param, char *);
+ if(!argptr ||
+ strncasecompare(argptr, "SRP", strlen("SRP")))
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
+ case CURLOPT_PROXY_TLSAUTH_TYPE:
+ argptr = va_arg(param, char *);
+ if(!argptr ||
+ strncasecompare(argptr, "SRP", strlen("SRP")))
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
+#endif
+ case CURLOPT_DNS_SERVERS:
+ result = Curl_set_dns_servers(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_INTERFACE:
+ result = Curl_set_dns_interface(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP4:
+ result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP6:
+ result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+ break;
+
+ case CURLOPT_TCP_KEEPALIVE:
+ data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_TCP_KEEPIDLE:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.tcp_keepidle = arg;
+ break;
+ case CURLOPT_TCP_KEEPINTVL:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.tcp_keepintvl = arg;
+ break;
+ case CURLOPT_TCP_FASTOPEN:
+#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
+ data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_SSL_ENABLE_NPN:
+ data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_SSL_ENABLE_ALPN:
+ data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+#ifdef USE_UNIX_SOCKETS
+ case CURLOPT_UNIX_SOCKET_PATH:
+ data->set.abstract_unix_socket = FALSE;
+ result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_ABSTRACT_UNIX_SOCKET:
+ data->set.abstract_unix_socket = TRUE;
+ result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+ va_arg(param, char *));
+ break;
+#endif
+
+ case CURLOPT_PATH_AS_IS:
+ data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_PIPEWAIT:
+ data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_STREAM_WEIGHT:
+#ifndef USE_NGHTTP2
+ return CURLE_NOT_BUILT_IN;
+#else
+ arg = va_arg(param, long);
+ if((arg >= 1) && (arg <= 256))
+ data->set.stream_weight = (int)arg;
+ break;
+#endif
+ case CURLOPT_STREAM_DEPENDS:
+ case CURLOPT_STREAM_DEPENDS_E:
+ {
+#ifndef USE_NGHTTP2
+ return CURLE_NOT_BUILT_IN;
+#else
+ struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
+ if(!dep || GOOD_EASY_HANDLE(dep)) {
+ if(data->set.stream_depends_on) {
+ Curl_http2_remove_child(data->set.stream_depends_on, data);
+ }
+ Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
+ }
+ break;
+#endif
+ }
+ case CURLOPT_CONNECT_TO:
+ data->set.connect_to = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_SUPPRESS_CONNECT_HEADERS:
+ data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSH_COMPRESSION:
+ data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ default:
+ /* unknown tag and its companion, just ignore: */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * curl_easy_setopt() is the external interface for setting options on an
+ * easy handle.
+ */
+
+#undef curl_easy_setopt
+CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
+{
+ va_list arg;
+ CURLcode result;
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ va_start(arg, tag);
+
+ result = setopt(data, tag, arg);
+
+ va_end(arg);
+ return result;
+}
+
diff --git a/lib/setopt.h b/lib/setopt.h
new file mode 100644
index 000000000..35769440f
--- /dev/null
+++ b/lib/setopt.h
@@ -0,0 +1,27 @@
+#ifndef HEADER_CURL_SETOPT_H
+#define HEADER_CURL_SETOPT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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.
+ *
+ ***************************************************************************/
+
+CURLcode Curl_setstropt(char **charp, const char *s);
+
+#endif /* HEADER_CURL_SETOPT_H */
diff --git a/lib/url.c b/lib/url.c
index 7e0fc9b20..6d7d2d460 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -120,6 +120,8 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "pipeline.h"
#include "dotdot.h"
#include "strdup.h"
+#include "setopt.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -136,15 +138,8 @@ 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);
-#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
-#define READBUFFER_MAX CURL_MAX_READ_SIZE
-#define READBUFFER_MIN 1024
-
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
* more than just a few bytes to play with. Don't let it become too small or
* bad things will happen.
@@ -301,98 +296,6 @@ void Curl_freeset(struct Curl_easy *data)
data->change.url = NULL;
}
-static CURLcode setstropt(char **charp, const char *s)
-{
- /* Release the previous storage at `charp' and replace by a dynamic storage
- copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
-
- Curl_safefree(*charp);
-
- if(s) {
- char *str = strdup(s);
-
- if(!str)
- return CURLE_OUT_OF_MEMORY;
-
- *charp = str;
- }
-
- return CURLE_OK;
-}
-
-static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
-{
- CURLcode result = CURLE_OK;
- char *user = NULL;
- char *passwd = NULL;
-
- /* 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);
- }
-
- if(!result) {
- /* Store the username part of option if required */
- if(userp) {
- 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;
- }
-
- /* Store the password part of option if required */
- if(passwdp) {
- Curl_safefree(*passwdp);
- *passwdp = passwd;
- }
- }
-
- return result;
-}
-
-CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
-{
- CURLcode result = CURLE_OK;
- 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;
- }
-
- /* 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;
-}
-
/*
* This is the internal function curl_easy_cleanup() calls. This should
* cleanup and free all resources associated with this sessionhandle.
@@ -587,20 +490,20 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
/* This is our preferred CA cert bundle/path since install time */
#if defined(CURL_CA_BUNDLE)
- result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
if(result)
return result;
- result = setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
if(result)
return result;
#endif
#if defined(CURL_CA_PATH)
- result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
if(result)
return result;
- result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
if(result)
return result;
#endif
@@ -708,2432 +611,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
return result;
}
-#define C_SSLVERSION_VALUE(x) (x & 0xffff)
-#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
-
-CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
- va_list param)
-{
- char *argptr;
- CURLcode result = CURLE_OK;
- long arg;
- curl_off_t bigsize;
-
- switch(option) {
- case CURLOPT_DNS_CACHE_TIMEOUT:
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.dns_cache_timeout = arg;
- break;
- case CURLOPT_DNS_USE_GLOBAL_CACHE:
- /* remember we want this enabled */
- arg = va_arg(param, long);
- data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
- break;
- 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_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_SSL_CIPHER_LIST:
- /* set a list of cipher we want to use in the SSL connection for proxy */
- result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
- va_arg(param, char *));
- break;
-
- 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],
- va_arg(param, char *));
- break;
- case CURLOPT_EGDSOCKET:
- /*
- * The Entropy Gathering Daemon socket pathname
- */
- result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
- va_arg(param, char *));
- break;
- case CURLOPT_MAXCONNECTS:
- /*
- * Set the absolute number of maximum simultaneous alive connection that
- * libcurl is allowed to have.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxconnects = arg;
- 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;
- break;
- case CURLOPT_VERBOSE:
- /*
- * 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;
- break;
- case CURLOPT_HEADER:
- /*
- * Set to include the header in the general data output stream.
- */
- data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_NOPROGRESS:
- /*
- * Shut off the internal supported progress meter
- */
- data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
- if(data->set.hide_progress)
- data->progress.flags |= PGRS_HIDE;
- else
- data->progress.flags &= ~PGRS_HIDE;
- break;
- case CURLOPT_NOBODY:
- /*
- * 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;
- break;
- case CURLOPT_KEEP_SENDING_ON_ERROR:
- data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- break;
- case CURLOPT_UPLOAD:
- 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;
- if(data->set.upload) {
- /* If this is HTTP, PUT is what's needed to "upload" */
- data->set.httpreq = HTTPREQ_PUT;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- else
- /* 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;
- break;
- case CURLOPT_REQUEST_TARGET:
- result = setstropt(&data->set.str[STRING_TARGET],
- va_arg(param, char *));
- break;
- case CURLOPT_FILETIME:
- /*
- * 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;
- break;
- 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;
- }
- 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.
- */
- arg = va_arg(param, long);
- if((arg >= 0) && (arg < (INT_MAX/1000)))
- data->set.server_response_timeout = arg * 1000;
- else
- return CURLE_BAD_FUNCTION_ARGUMENT;
- break;
- 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;
- case CURLOPT_TFTP_BLKSIZE:
- /*
- * TFTP option that specifies the block size to use for data transmission.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.tftp_blksize = arg;
- 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;
- break;
- case CURLOPT_APPEND:
- /*
- * We want to upload and append to an existing file.
- */
- data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_FTP_FILEMETHOD:
- /*
- * How do access files over FTP.
- */
- arg = va_arg(param, long);
- if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_filemethod = (curl_ftpfile)arg;
- break;
- case CURLOPT_NETRC:
- /*
- * Parse the $HOME/.netrc file
- */
- arg = va_arg(param, long);
- if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
- break;
- case CURLOPT_NETRC_FILE:
- /*
- * Use this file instead of the $HOME/.netrc file
- */
- result = setstropt(&data->set.str[STRING_NETRC_FILE],
- va_arg(param, char *));
- break;
- 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.
- */
- arg = va_arg(param, long);
- if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.timecondition = (curl_TimeCond)arg;
- break;
- case CURLOPT_TIMEVALUE:
- /*
- * 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);
- break;
- case CURLOPT_SSLVERSION:
- /*
- * Set explicit SSL version to try to connect with, as some SSL
- * implementations are lame.
- */
-#ifdef USE_SSL
- arg = va_arg(param, long);
- if((arg < CURL_SSLVERSION_DEFAULT) || (arg > CURL_SSLVERSION_TLSv1_3))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg);
- data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
-#else
- result = CURLE_UNKNOWN_OPTION;
-#endif
- break;
- case CURLOPT_PROXY_SSLVERSION:
- /*
- * Set explicit SSL version to try to connect with for proxy, as some SSL
- * implementations are lame.
- */
-#ifdef USE_SSL
- arg = va_arg(param, long);
- if((arg < CURL_SSLVERSION_DEFAULT) || (arg > CURL_SSLVERSION_TLSv1_3))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg);
- data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
-#else
- result = CURLE_UNKNOWN_OPTION;
-#endif
- break;
-
-#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;
- break;
-
- 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.
- *
- */
- argptr = va_arg(param, char *);
- if(argptr && !*argptr) {
- argptr = Curl_all_content_encodings();
- if(!argptr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = setstropt(&data->set.str[STRING_ENCODING], argptr);
- free(argptr);
- }
- }
- else
- result = setstropt(&data->set.str[STRING_ENCODING], argptr);
- break;
-
- case CURLOPT_TRANSFER_ENCODING:
- data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- break;
-
- case CURLOPT_FOLLOWLOCATION:
- /*
- * Follow Location: header hints on a HTTP-server.
- */
- data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- 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;
- break;
-
- 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.
- */
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxredirs = arg;
- break;
-
- 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
- */
- arg = va_arg(param, long);
- if(arg < CURL_REDIR_GET_ALL)
- /* no return error on too high numbers since the bitmask could be
- extended in a future */
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.keep_post = arg & 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! */
- if(va_arg(param, long)) {
- data->set.httpreq = HTTPREQ_POST;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- else
- data->set.httpreq = HTTPREQ_GET;
- break;
-
- case CURLOPT_COPYPOSTFIELDS:
- /*
- * 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 *);
-
- if(!argptr || data->set.postfieldsize == -1)
- result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
- else {
- /*
- * Check that requested length does not overflow the size_t type.
- */
-
- if((data->set.postfieldsize < 0) ||
- ((sizeof(curl_off_t) != sizeof(size_t)) &&
- (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
- result = CURLE_OUT_OF_MEMORY;
- else {
- char *p;
-
- (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-
- /* Allocate even when size == 0. This satisfies the need of possible
- later address compare to detect the COPYPOSTFIELDS mode, and
- to mark that postfields is used rather than read function or
- form data.
- */
- p = malloc((size_t)(data->set.postfieldsize?
- data->set.postfieldsize:1));
-
- if(!p)
- result = CURLE_OUT_OF_MEMORY;
- else {
- if(data->set.postfieldsize)
- memcpy(p, argptr, (size_t)data->set.postfieldsize);
-
- data->set.str[STRING_COPYPOSTFIELDS] = p;
- }
- }
- }
-
- data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
- data->set.httpreq = HTTPREQ_POST;
- break;
-
- case CURLOPT_POSTFIELDS:
- /*
- * Like above, but use static data instead of copying it.
- */
- data->set.postfields = va_arg(param, void *);
- /* Release old copied data. */
- (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
- data->set.httpreq = HTTPREQ_POST;
- break;
-
- case CURLOPT_POSTFIELDSIZE:
- /*
- * The size of the POSTFIELD data to prevent libcurl to do strlen() to
- * figure it out. Enables binary posts.
- */
- bigsize = va_arg(param, long);
- if(bigsize < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- if(data->set.postfieldsize < bigsize &&
- data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
- /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
- (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
- data->set.postfields = NULL;
- }
-
- data->set.postfieldsize = bigsize;
- break;
-
- case CURLOPT_POSTFIELDSIZE_LARGE:
- /*
- * The size of the POSTFIELD data to prevent libcurl to do strlen() to
- * figure it out. Enables binary posts.
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- if(data->set.postfieldsize < bigsize &&
- data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
- /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
- (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
- data->set.postfields = NULL;
- }
-
- data->set.postfieldsize = bigsize;
- break;
-
- case CURLOPT_HTTPPOST:
- /*
- * Set to make us do HTTP POST
- */
- data->set.httppost = va_arg(param, struct curl_httppost *);
- data->set.httpreq = HTTPREQ_POST_FORM;
- data->set.opt_no_body = FALSE; /* this is implied */
- break;
-#endif /* CURL_DISABLE_HTTP */
-
- case CURLOPT_MIMEPOST:
- /*
- * Set to make us do MIME/form POST
- */
- result = Curl_mime_set_subparts(&data->set.mimepost,
- va_arg(param, curl_mime *), FALSE);
- if(!result) {
- data->set.httpreq = HTTPREQ_POST_MIME;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- break;
-
- case CURLOPT_REFERER:
- /*
- * String to set in the HTTP Referer: field.
- */
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
- }
- result = setstropt(&data->set.str[STRING_SET_REFERER],
- va_arg(param, char *));
- data->change.referer = data->set.str[STRING_SET_REFERER];
- break;
-
- case CURLOPT_USERAGENT:
- /*
- * String to use in the HTTP User-Agent field
- */
- result = setstropt(&data->set.str[STRING_USERAGENT],
- va_arg(param, char *));
- break;
-
- case CURLOPT_HTTPHEADER:
- /*
- * Set a list with HTTP headers to use (or replace internals with)
- */
- data->set.headers = va_arg(param, struct curl_slist *);
- break;
-
-#ifndef CURL_DISABLE_HTTP
- case CURLOPT_PROXYHEADER:
- /*
- * Set a list with proxy headers to use (or replace internals with)
- *
- * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
- * long time we remain doing it this way until CURLOPT_PROXYHEADER is
- * used. As soon as this option has been used, if set to anything but
- * NULL, custom headers for proxies are only picked from this list.
- *
- * Set this option to NULL to restore the previous behavior.
- */
- data->set.proxyheaders = va_arg(param, struct curl_slist *);
- break;
-
- case CURLOPT_HEADEROPT:
- /*
- * Set header option.
- */
- arg = va_arg(param, long);
- data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
- break;
-
- case CURLOPT_HTTP200ALIASES:
- /*
- * Set a list of aliases for HTTP 200 in response header
- */
- data->set.http200aliases = va_arg(param, struct curl_slist *);
- break;
-
-#if !defined(CURL_DISABLE_COOKIES)
- case CURLOPT_COOKIE:
- /*
- * Cookie string to send to the remote server in the request.
- */
- result = setstropt(&data->set.str[STRING_COOKIE],
- va_arg(param, char *));
- break;
-
- case CURLOPT_COOKIEFILE:
- /*
- * Set cookie file to read and parse. Can be used multiple times.
- */
- argptr = (char *)va_arg(param, void *);
- if(argptr) {
- struct curl_slist *cl;
- /* append the cookie file name to the list of file names, and deal with
- them later */
- cl = curl_slist_append(data->change.cookielist, argptr);
- if(!cl) {
- curl_slist_free_all(data->change.cookielist);
- data->change.cookielist = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
- data->change.cookielist = cl; /* store the list for later use */
- }
- break;
-
- case CURLOPT_COOKIEJAR:
- /*
- * Set cookie file name to dump all cookies to when we're done.
- */
- {
- struct CookieInfo *newcookies;
- result = setstropt(&data->set.str[STRING_COOKIEJAR],
- va_arg(param, char *));
-
- /*
- * Activate the cookie parser. This may or may not already
- * have been made.
- */
- newcookies = Curl_cookie_init(data, NULL, data->cookies,
- data->set.cookiesession);
- if(!newcookies)
- result = CURLE_OUT_OF_MEMORY;
- data->cookies = newcookies;
- }
- break;
-
- case CURLOPT_COOKIESESSION:
- /*
- * Set this option to TRUE to start a new "cookie session". It will
- * prevent the forthcoming read-cookies-from-file actions to accept
- * cookies that are marked as being session cookies, as they belong to a
- * previous session.
- *
- * In the original Netscape cookie spec, "session cookies" are cookies
- * with no expire date set. RFC2109 describes the same action if no
- * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
- * a 'Discard' action that can enforce the discard even for cookies that
- * have a Max-Age.
- *
- * We run mostly with the original cookie spec, as hardly anyone implements
- * anything else.
- */
- data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_COOKIELIST:
- argptr = va_arg(param, char *);
-
- if(argptr == NULL)
- break;
-
- if(strcasecompare(argptr, "ALL")) {
- /* clear all cookies */
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- Curl_cookie_clearall(data->cookies);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
- else if(strcasecompare(argptr, "SESS")) {
- /* clear session cookies */
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- Curl_cookie_clearsess(data->cookies);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
- else if(strcasecompare(argptr, "FLUSH")) {
- /* flush cookies to file, takes care of the locking */
- Curl_flush_cookies(data, 0);
- }
- else if(strcasecompare(argptr, "RELOAD")) {
- /* reload cookies from file */
- Curl_cookie_loadfiles(data);
- break;
- }
- else {
- if(!data->cookies)
- /* if cookie engine was not running, activate it */
- data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
-
- argptr = strdup(argptr);
- if(!argptr || !data->cookies) {
- result = CURLE_OUT_OF_MEMORY;
- free(argptr);
- }
- else {
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-
- if(checkprefix("Set-Cookie:", argptr))
- /* HTTP Header format line */
- Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
-
- else
- /* Netscape format line */
- Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
-
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- free(argptr);
- }
- }
-
- break;
-#endif /* !CURL_DISABLE_COOKIES */
-
- case CURLOPT_HTTPGET:
- /*
- * Set to force us do HTTP GET
- */
- if(va_arg(param, long)) {
- data->set.httpreq = HTTPREQ_GET;
- data->set.upload = FALSE; /* switch off upload */
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- break;
-
- case CURLOPT_HTTP_VERSION:
- /*
- * This sets a requested HTTP version to be used. The value is one of
- * the listed enums in curl/curl.h.
- */
- arg = va_arg(param, long);
- if(arg < CURL_HTTP_VERSION_NONE)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-#ifndef USE_NGHTTP2
- if(arg >= CURL_HTTP_VERSION_2)
- return CURLE_UNSUPPORTED_PROTOCOL;
-#else
- if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
- return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
- data->set.httpversion = arg;
- break;
-
- case CURLOPT_EXPECT_100_TIMEOUT_MS:
- /*
- * Time to wait for a response to a HTTP request containing an
- * Expect: 100-continue header before sending the data anyway.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.expect_100_timeout = arg;
- break;
-
-#endif /* CURL_DISABLE_HTTP */
-
- case CURLOPT_HTTPAUTH:
- /*
- * Set HTTP Authentication type BITMASK.
- */
- {
- int bitcheck;
- bool authbits;
- unsigned long auth = va_arg(param, unsigned long);
-
- if(auth == CURLAUTH_NONE) {
- data->set.httpauth = auth;
- break;
- }
-
- /* the DIGEST_IE bit is only used to set a special marker, for all the
- rest we need to handle it as normal DIGEST */
- data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
-
- if(auth & CURLAUTH_DIGEST_IE) {
- auth |= CURLAUTH_DIGEST; /* set standard digest bit */
- auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
- }
-
- /* switch off bits we can't support */
-#ifndef USE_NTLM
- auth &= ~CURLAUTH_NTLM; /* no NTLM support */
- auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
- auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#endif
-#ifndef USE_SPNEGO
- auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
- GSS-API or SSPI */
-#endif
-
- /* check if any auth bit lower than CURLAUTH_ONLY is still set */
- bitcheck = 0;
- authbits = FALSE;
- while(bitcheck < 31) {
- if(auth & (1UL << bitcheck++)) {
- authbits = TRUE;
- break;
- }
- }
- if(!authbits)
- return CURLE_NOT_BUILT_IN; /* no supported types left! */
-
- data->set.httpauth = auth;
- }
- break;
-
- case CURLOPT_CUSTOMREQUEST:
- /*
- * Set a custom string to use as request
- */
- result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
- va_arg(param, char *));
-
- /* we don't set
- data->set.httpreq = HTTPREQ_CUSTOM;
- here, we continue as if we were using the already set type
- and this just changes the actual request keyword */
- break;
-
-#ifndef CURL_DISABLE_PROXY
- case CURLOPT_HTTPPROXYTUNNEL:
- /*
- * Tunnel operations through the proxy instead of normal proxy use
- */
- data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- break;
-
- case CURLOPT_PROXYPORT:
- /*
- * Explicitly set HTTP proxy port number.
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 65535))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.proxyport = arg;
- break;
-
- case CURLOPT_PROXYAUTH:
- /*
- * Set HTTP Authentication type BITMASK.
- */
- {
- int bitcheck;
- bool authbits;
- unsigned long auth = va_arg(param, unsigned long);
-
- if(auth == CURLAUTH_NONE) {
- data->set.proxyauth = auth;
- break;
- }
-
- /* the DIGEST_IE bit is only used to set a special marker, for all the
- rest we need to handle it as normal DIGEST */
- data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
-
- if(auth & CURLAUTH_DIGEST_IE) {
- auth |= CURLAUTH_DIGEST; /* set standard digest bit */
- auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
- }
- /* switch off bits we can't support */
-#ifndef USE_NTLM
- auth &= ~CURLAUTH_NTLM; /* no NTLM support */
- auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
- auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#endif
-#ifndef USE_SPNEGO
- auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
- GSS-API or SSPI */
-#endif
-
- /* check if any auth bit lower than CURLAUTH_ONLY is still set */
- bitcheck = 0;
- authbits = FALSE;
- while(bitcheck < 31) {
- if(auth & (1UL << bitcheck++)) {
- authbits = TRUE;
- break;
- }
- }
- if(!authbits)
- return CURLE_NOT_BUILT_IN; /* no supported types left! */
-
- data->set.proxyauth = auth;
- }
- break;
-
- case CURLOPT_PROXY:
- /*
- * Set proxy server:port to use as proxy.
- *
- * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
- * we explicitly say that we don't want to use a proxy
- * (even though there might be environment variables saying so).
- *
- * Setting it to NULL, means no proxy but allows the environment variables
- * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
- */
- result = setstropt(&data->set.str[STRING_PROXY],
- va_arg(param, char *));
- break;
-
- case CURLOPT_PRE_PROXY:
- /*
- * Set proxy server:port to use as SOCKS proxy.
- *
- * If the proxy is set to "" or NULL we explicitly say that we don't want
- * to use the socks proxy.
- */
- result = setstropt(&data->set.str[STRING_PRE_PROXY],
- va_arg(param, char *));
- break;
-
- case CURLOPT_PROXYTYPE:
- /*
- * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
- */
- arg = va_arg(param, long);
- if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.proxytype = (curl_proxytype)arg;
- break;
-
- case CURLOPT_PROXY_TRANSFER_MODE:
- /*
- * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
- */
- switch(va_arg(param, long)) {
- case 0:
- data->set.proxy_transfer_mode = FALSE;
- break;
- case 1:
- data->set.proxy_transfer_mode = TRUE;
- break;
- default:
- /* reserve other values for future use */
- result = CURLE_UNKNOWN_OPTION;
- break;
- }
- break;
-#endif /* CURL_DISABLE_PROXY */
-
- case CURLOPT_SOCKS5_AUTH:
- data->set.socks5auth = va_arg(param, unsigned long);
- if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
- result = CURLE_NOT_BUILT_IN;
- break;
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- case CURLOPT_SOCKS5_GSSAPI_NEC:
- /*
- * Set flag for NEC SOCK5 support
- */
- data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_SOCKS5_GSSAPI_SERVICE:
- case CURLOPT_PROXY_SERVICE_NAME:
- /*
- * Set proxy authentication service name for Kerberos 5 and SPNEGO
- */
- result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
- va_arg(param, char *));
- break;
-#endif
-
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO)
- case CURLOPT_SERVICE_NAME:
- /*
- * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
- */
- result = setstropt(&data->set.str[STRING_SERVICE_NAME],
- va_arg(param, char *));
- break;
-
-#endif
-
- case CURLOPT_HEADERDATA:
- /*
- * Custom pointer to pass the header write callback function
- */
- data->set.writeheader = (void *)va_arg(param, void *);
- break;
- case CURLOPT_ERRORBUFFER:
- /*
- * Error buffer provided by the caller to get the human readable
- * error string in.
- */
- data->set.errorbuffer = va_arg(param, char *);
- break;
- case CURLOPT_WRITEDATA:
- /*
- * FILE pointer to write to. Or possibly
- * used as argument to the write callback.
- */
- data->set.out = va_arg(param, void *);
- break;
- case CURLOPT_FTPPORT:
- /*
- * Use FTP PORT, this also specifies which IP address to use
- */
- result = setstropt(&data->set.str[STRING_FTPPORT],
- va_arg(param, char *));
- data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_USE_EPRT:
- data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_USE_EPSV:
- data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_USE_PRET:
- data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_SSL_CCC:
- arg = va_arg(param, long);
- if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_ccc = (curl_ftpccc)arg;
- break;
-
- case CURLOPT_FTP_SKIP_PASV_IP:
- /*
- * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
- * bypass of the IP address in PASV responses.
- */
- data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_READDATA:
- /*
- * FILE pointer to read the file to be uploaded from. Or possibly
- * used as argument to the read callback.
- */
- data->set.in_set = va_arg(param, void *);
- break;
- case CURLOPT_INFILESIZE:
- /*
- * If known, this should inform curl about the file size of the
- * to-be-uploaded file.
- */
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.filesize = arg;
- break;
- case CURLOPT_INFILESIZE_LARGE:
- /*
- * If known, this should inform curl about the file size of the
- * to-be-uploaded file.
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.filesize = bigsize;
- break;
- case CURLOPT_LOW_SPEED_LIMIT:
- /*
- * The low speed limit that if transfers are below this for
- * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.low_speed_limit = arg;
- break;
- case CURLOPT_MAX_SEND_SPEED_LARGE:
- /*
- * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
- * bytes per second the transfer is throttled..
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.max_send_speed = bigsize;
- break;
- case CURLOPT_MAX_RECV_SPEED_LARGE:
- /*
- * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
- * second the transfer is throttled..
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.max_recv_speed = bigsize;
- break;
- case CURLOPT_LOW_SPEED_TIME:
- /*
- * The low speed time that if transfers are below the set
- * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.low_speed_time = arg;
- break;
- case CURLOPT_URL:
- /*
- * The URL to fetch.
- */
- if(data->change.url_alloc) {
- /* the already set URL is allocated, free it first! */
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
- result = setstropt(&data->set.str[STRING_SET_URL],
- va_arg(param, char *));
- data->change.url = data->set.str[STRING_SET_URL];
- break;
- case CURLOPT_PORT:
- /*
- * The port number to use when getting the URL
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 65535))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_port = arg;
- break;
- case CURLOPT_TIMEOUT:
- /*
- * The maximum time you allow curl to use for a single transfer
- * operation.
- */
- arg = va_arg(param, long);
- if((arg >= 0) && (arg < (INT_MAX/1000)))
- data->set.timeout = arg * 1000;
- else
- return CURLE_BAD_FUNCTION_ARGUMENT;
- break;
-
- case CURLOPT_TIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.timeout = arg;
- break;
-
- case CURLOPT_CONNECTTIMEOUT:
- /*
- * The maximum time you allow curl to use to connect.
- */
- arg = va_arg(param, long);
- if((arg >= 0) && (arg < (INT_MAX/1000)))
- data->set.connecttimeout = arg * 1000;
- else
- return CURLE_BAD_FUNCTION_ARGUMENT;
- break;
-
- case CURLOPT_CONNECTTIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.connecttimeout = arg;
- break;
-
- case CURLOPT_ACCEPTTIMEOUT_MS:
- /*
- * The maximum time you allow curl to wait for server connect
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.accepttimeout = arg;
- break;
-
- case CURLOPT_USERPWD:
- /*
- * user:password to use in the operation
- */
- result = setstropt_userpwd(va_arg(param, char *),
- &data->set.str[STRING_USERNAME],
- &data->set.str[STRING_PASSWORD]);
- break;
-
- case CURLOPT_USERNAME:
- /*
- * authentication user name to use in the operation
- */
- result = setstropt(&data->set.str[STRING_USERNAME],
- va_arg(param, char *));
- break;
-
- case CURLOPT_PASSWORD:
- /*
- * authentication password to use in the operation
- */
- result = setstropt(&data->set.str[STRING_PASSWORD],
- va_arg(param, char *));
- break;
-
- case CURLOPT_LOGIN_OPTIONS:
- /*
- * authentication options to use in the operation
- */
- result = setstropt(&data->set.str[STRING_OPTIONS],
- va_arg(param, char *));
- break;
-
- case CURLOPT_XOAUTH2_BEARER:
- /*
- * OAuth 2.0 bearer token to use in the operation
- */
- result = setstropt(&data->set.str[STRING_BEARER],
- va_arg(param, char *));
- break;
-
- case CURLOPT_POSTQUOTE:
- /*
- * List of RAW FTP commands to use after a transfer
- */
- data->set.postquote = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_PREQUOTE:
- /*
- * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
- */
- data->set.prequote = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_QUOTE:
- /*
- * List of RAW FTP commands to use before a transfer
- */
- data->set.quote = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_RESOLVE:
- /*
- * List of NAME:[address] names to populate the DNS cache with
- * Prefix the NAME with dash (-) to _remove_ the name from the cache.
- *
- * Names added with this API will remain in the cache until explicitly
- * removed or the handle is cleaned up.
- *
- * This API can remove any name from the DNS cache, but only entries
- * that aren't actually in use right now will be pruned immediately.
- */
- data->set.resolve = va_arg(param, struct curl_slist *);
- data->change.resolve = data->set.resolve;
- break;
- case CURLOPT_PROGRESSFUNCTION:
- /*
- * Progress callback function
- */
- data->set.fprogress = va_arg(param, curl_progress_callback);
- if(data->set.fprogress)
- data->progress.callback = TRUE; /* no longer internal */
- else
- data->progress.callback = FALSE; /* NULL enforces internal */
- break;
-
- case CURLOPT_XFERINFOFUNCTION:
- /*
- * Transfer info callback function
- */
- data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
- if(data->set.fxferinfo)
- data->progress.callback = TRUE; /* no longer internal */
- else
- data->progress.callback = FALSE; /* NULL enforces internal */
-
- break;
-
- case CURLOPT_PROGRESSDATA:
- /*
- * Custom client data to pass to the progress callback
- */
- data->set.progress_client = va_arg(param, void *);
- break;
-
-#ifndef CURL_DISABLE_PROXY
- case CURLOPT_PROXYUSERPWD:
- /*
- * user:password needed to use the proxy
- */
- result = setstropt_userpwd(va_arg(param, char *),
- &data->set.str[STRING_PROXYUSERNAME],
- &data->set.str[STRING_PROXYPASSWORD]);
- break;
- case CURLOPT_PROXYUSERNAME:
- /*
- * authentication user name to use in the operation
- */
- result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXYPASSWORD:
- /*
- * authentication password to use in the operation
- */
- result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
- va_arg(param, char *));
- break;
- case CURLOPT_NOPROXY:
- /*
- * proxy exception list
- */
- result = setstropt(&data->set.str[STRING_NOPROXY],
- va_arg(param, char *));
- break;
-#endif
-
- case CURLOPT_RANGE:
- /*
- * What range of the file you want to transfer
- */
- result = setstropt(&data->set.str[STRING_SET_RANGE],
- va_arg(param, char *));
- break;
- case CURLOPT_RESUME_FROM:
- /*
- * Resume transfer at the given file position
- */
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.set_resume_from = arg;
- break;
- case CURLOPT_RESUME_FROM_LARGE:
- /*
- * Resume transfer at the given file position
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.set_resume_from = bigsize;
- break;
- case CURLOPT_DEBUGFUNCTION:
- /*
- * stderr write callback.
- */
- data->set.fdebug = va_arg(param, curl_debug_callback);
- /*
- * if the callback provided is NULL, it'll use the default callback
- */
- break;
- case CURLOPT_DEBUGDATA:
- /*
- * Set to a void * that should receive all error writes. This
- * defaults to CURLOPT_STDERR for normal operations.
- */
- data->set.debugdata = va_arg(param, void *);
- break;
- case CURLOPT_STDERR:
- /*
- * Set to a FILE * that should receive all error writes. This
- * defaults to stderr for normal operations.
- */
- data->set.err = va_arg(param, FILE *);
- if(!data->set.err)
- data->set.err = stderr;
- break;
- case CURLOPT_HEADERFUNCTION:
- /*
- * Set header write callback
- */
- data->set.fwrite_header = va_arg(param, curl_write_callback);
- break;
- case CURLOPT_WRITEFUNCTION:
- /*
- * Set data write callback
- */
- data->set.fwrite_func = va_arg(param, curl_write_callback);
- if(!data->set.fwrite_func) {
- data->set.is_fwrite_set = 0;
- /* When set to NULL, reset to our internal default function */
- data->set.fwrite_func = (curl_write_callback)fwrite;
- }
- else
- data->set.is_fwrite_set = 1;
- break;
- case CURLOPT_READFUNCTION:
- /*
- * Read data callback
- */
- data->set.fread_func_set = va_arg(param, curl_read_callback);
- if(!data->set.fread_func_set) {
- data->set.is_fread_set = 0;
- /* When set to NULL, reset to our internal default function */
- data->set.fread_func_set = (curl_read_callback)fread;
- }
- else
- data->set.is_fread_set = 1;
- break;
- case CURLOPT_SEEKFUNCTION:
- /*
- * Seek callback. Might be NULL.
- */
- data->set.seek_func = va_arg(param, curl_seek_callback);
- break;
- case CURLOPT_SEEKDATA:
- /*
- * Seek control callback. Might be NULL.
- */
- data->set.seek_client = va_arg(param, void *);
- break;
- case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
- /*
- * "Convert from network encoding" callback
- */
- data->set.convfromnetwork = va_arg(param, curl_conv_callback);
- break;
- case CURLOPT_CONV_TO_NETWORK_FUNCTION:
- /*
- * "Convert to network encoding" callback
- */
- data->set.convtonetwork = va_arg(param, curl_conv_callback);
- break;
- case CURLOPT_CONV_FROM_UTF8_FUNCTION:
- /*
- * "Convert from UTF-8 encoding" callback
- */
- data->set.convfromutf8 = va_arg(param, curl_conv_callback);
- break;
- case CURLOPT_IOCTLFUNCTION:
- /*
- * I/O control callback. Might be NULL.
- */
- data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
- break;
- case CURLOPT_IOCTLDATA:
- /*
- * I/O control data pointer. Might be NULL.
- */
- data->set.ioctl_client = va_arg(param, void *);
- break;
- case CURLOPT_SSLCERT:
- /*
- * String that holds file name of the SSL certificate to use
- */
- result = setstropt(&data->set.str[STRING_CERT_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_SSLCERT:
- /*
- * String that holds file name of the SSL certificate to use for proxy
- */
- result = setstropt(&data->set.str[STRING_CERT_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_SSLCERTTYPE:
- /*
- * String that holds file type of the SSL certificate to use
- */
- result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_SSLCERTTYPE:
- /*
- * String that holds file type of the SSL certificate to use for proxy
- */
- result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_SSLKEY:
- /*
- * String that holds file name of the SSL key to use
- */
- result = setstropt(&data->set.str[STRING_KEY_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_SSLKEY:
- /*
- * String that holds file name of the SSL key to use for proxy
- */
- result = setstropt(&data->set.str[STRING_KEY_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_SSLKEYTYPE:
- /*
- * String that holds file type of the SSL key to use
- */
- result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_SSLKEYTYPE:
- /*
- * String that holds file type of the SSL key to use for proxy
- */
- result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_KEYPASSWD:
- /*
- * String that holds the SSL or SSH private key password.
- */
- result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_KEYPASSWD:
- /*
- * String that holds the SSL private key password for proxy.
- */
- result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_SSLENGINE:
- /*
- * String that holds the SSL crypto engine.
- */
- argptr = va_arg(param, char *);
- if(argptr && argptr[0])
- result = Curl_ssl_set_engine(data, argptr);
- break;
-
- case CURLOPT_SSLENGINE_DEFAULT:
- /*
- * flag to set engine as default.
- */
- result = Curl_ssl_set_engine_default(data);
- break;
- case CURLOPT_CRLF:
- /*
- * Kludgy option to enable CRLF conversions. Subject for removal.
- */
- data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_INTERFACE:
- /*
- * Set what interface or address/hostname to bind the socket to when
- * performing an operation and thus what from-IP your connection will use.
- */
- result = setstropt(&data->set.str[STRING_DEVICE],
- va_arg(param, char *));
- break;
- case CURLOPT_LOCALPORT:
- /*
- * Set what local port to bind the socket to when performing an operation.
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 65535))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.localport = curlx_sltous(arg);
- break;
- case CURLOPT_LOCALPORTRANGE:
- /*
- * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 65535))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.localportrange = curlx_sltosi(arg);
- break;
- case CURLOPT_KRBLEVEL:
- /*
- * A string that defines the kerberos security level.
- */
- result = setstropt(&data->set.str[STRING_KRB_LEVEL],
- va_arg(param, char *));
- data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
- break;
- case CURLOPT_GSSAPI_DELEGATION:
- /*
- * GSS-API credential delegation bitmask
- */
- arg = va_arg(param, long);
- if(arg < CURLGSSAPI_DELEGATION_NONE)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.gssapi_delegation = arg;
- break;
- case CURLOPT_SSL_VERIFYPEER:
- /*
- * Enable peer SSL verifying.
- */
- data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
-
- /* Update the current connection ssl_config. */
- if(data->easy_conn) {
- data->easy_conn->ssl_config.verifypeer =
- data->set.ssl.primary.verifypeer;
- }
- break;
- case CURLOPT_PROXY_SSL_VERIFYPEER:
- /*
- * Enable peer SSL verifying for proxy.
- */
- data->set.proxy_ssl.primary.verifypeer =
- (0 != va_arg(param, long))?TRUE:FALSE;
-
- /* Update the current connection proxy_ssl_config. */
- if(data->easy_conn) {
- data->easy_conn->proxy_ssl_config.verifypeer =
- data->set.proxy_ssl.primary.verifypeer;
- }
- break;
- case CURLOPT_SSL_VERIFYHOST:
- /*
- * Enable verification of the host name in the peer certificate
- */
- arg = va_arg(param, long);
-
- /* Obviously people are not reading documentation and too many thought
- this argument took a boolean when it wasn't and misused it. We thus ban
- 1 as a sensible input and we warn about its use. Then we only have the
- 2 action internally stored as TRUE. */
-
- if(1 == arg) {
- failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
-
- data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
-
- /* Update the current connection ssl_config. */
- if(data->easy_conn) {
- data->easy_conn->ssl_config.verifyhost =
- data->set.ssl.primary.verifyhost;
- }
- break;
- case CURLOPT_PROXY_SSL_VERIFYHOST:
- /*
- * Enable verification of the host name in the peer certificate for proxy
- */
- arg = va_arg(param, long);
-
- /* Obviously people are not reading documentation and too many thought
- this argument took a boolean when it wasn't and misused it. We thus ban
- 1 as a sensible input and we warn about its use. Then we only have the
- 2 action internally stored as TRUE. */
-
- if(1 == arg) {
- failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
-
- data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
-
- /* Update the current connection proxy_ssl_config. */
- if(data->easy_conn) {
- data->easy_conn->proxy_ssl_config.verifyhost =
- data->set.proxy_ssl.primary.verifyhost;
- }
- break;
- case CURLOPT_SSL_VERIFYSTATUS:
- /*
- * Enable certificate status verifying.
- */
- if(!Curl_ssl_cert_status_request()) {
- result = CURLE_NOT_BUILT_IN;
- break;
- }
-
- data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
-
- /* Update the current connection ssl_config. */
- if(data->easy_conn) {
- data->easy_conn->ssl_config.verifystatus =
- data->set.ssl.primary.verifystatus;
- }
- break;
- case CURLOPT_SSL_CTX_FUNCTION:
- /*
- * Set a SSL_CTX callback
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
- data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_SSL_CTX_DATA:
- /*
- * Set a SSL_CTX callback parameter pointer
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
- data->set.ssl.fsslctxp = va_arg(param, void *);
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_SSL_FALSESTART:
- /*
- * Enable TLS false start.
- */
- if(!Curl_ssl_false_start()) {
- result = CURLE_NOT_BUILT_IN;
- break;
- }
-
- data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_CERTINFO:
-#ifdef USE_SSL
- if(Curl_ssl->have_certinfo)
- data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_PINNEDPUBLICKEY:
- /*
- * Set pinned public key for SSL connection.
- * Specify file name of the public key in DER format.
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
- va_arg(param, char *));
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_PROXY_PINNEDPUBLICKEY:
- /*
- * Set pinned public key for SSL connection.
- * Specify file name of the public key in DER format.
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
- va_arg(param, char *));
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_CAINFO:
- /*
- * Set CA info for SSL connection. Specify file name of the CA certificate
- */
- result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_CAINFO:
- /*
- * Set CA info SSL connection for proxy. Specify file name of the
- * CA certificate
- */
- result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_CAPATH:
- /*
- * Set CA path info for SSL connection. Specify directory name of the CA
- * certificates which have been prepared using openssl c_rehash utility.
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
- /* This does not work on windows. */
- result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
- va_arg(param, char *));
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_PROXY_CAPATH:
- /*
- * Set CA path info for SSL connection proxy. Specify directory name of the
- * CA certificates which have been prepared using openssl c_rehash utility.
- */
-#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
- /* This does not work on windows. */
- result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
- va_arg(param, char *));
- else
-#endif
- result = CURLE_NOT_BUILT_IN;
- break;
- case CURLOPT_CRLFILE:
- /*
- * Set CRL file info for SSL connection. Specify file name of the CRL
- * to check certificates revocation
- */
- result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_PROXY_CRLFILE:
- /*
- * Set CRL file info for SSL connection for proxy. Specify file name of the
- * CRL to check certificates revocation
- */
- result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
- va_arg(param, char *));
- break;
- case CURLOPT_ISSUERCERT:
- /*
- * Set Issuer certificate file
- * to check certificates issuer
- */
- result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
- va_arg(param, char *));
- break;
- case CURLOPT_TELNETOPTIONS:
- /*
- * Set a linked list of telnet options
- */
- data->set.telnet_options = va_arg(param, struct curl_slist *);
- break;
-
- case CURLOPT_BUFFERSIZE:
- /*
- * The application kindly asks for a differently sized receive buffer.
- * If it seems reasonable, we'll use it.
- */
- arg = va_arg(param, long);
-
- if(arg > READBUFFER_MAX)
- arg = READBUFFER_MAX;
- else if(arg < 1)
- arg = READBUFFER_SIZE;
- else if(arg < READBUFFER_MIN)
- arg = READBUFFER_MIN;
-
- /* Resize if new size */
- if(arg != data->set.buffer_size) {
- char *newbuff = realloc(data->state.buffer, arg + 1);
- if(!newbuff) {
- DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- data->state.buffer = newbuff;
- }
- data->set.buffer_size = arg;
-
- break;
-
- case CURLOPT_NOSIGNAL:
- /*
- * The application asks not to set any signal() or alarm() handlers,
- * even when using a timeout.
- */
- data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_SHARE:
- {
- struct Curl_share *set;
- set = va_arg(param, struct Curl_share *);
-
- /* disconnect from old share, if any */
- if(data->share) {
- Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
-
- if(data->dns.hostcachetype == HCACHE_SHARED) {
- data->dns.hostcache = NULL;
- data->dns.hostcachetype = HCACHE_NONE;
- }
-
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
- if(data->share->cookies == data->cookies)
- data->cookies = NULL;
-#endif
-
- if(data->share->sslsession == data->state.session)
- data->state.session = NULL;
-
- data->share->dirty--;
-
- Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
- data->share = NULL;
- }
-
- /* use new share if it set */
- data->share = set;
- if(data->share) {
-
- Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
-
- data->share->dirty++;
-
- if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
- /* use shared host cache */
- data->dns.hostcache = &data->share->hostcache;
- data->dns.hostcachetype = HCACHE_SHARED;
- }
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
- if(data->share->cookies) {
- /* use shared cookie list, first free own one if any */
- Curl_cookie_cleanup(data->cookies);
- /* enable cookies since we now use a share that uses cookies! */
- data->cookies = data->share->cookies;
- }
-#endif /* CURL_DISABLE_HTTP */
- if(data->share->sslsession) {
- data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
- data->state.session = data->share->sslsession;
- }
- Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
-
- }
- /* check for host cache not needed,
- * it will be done by curl_easy_perform */
- }
- break;
-
- case CURLOPT_PRIVATE:
- /*
- * Set private data pointer.
- */
- data->set.private_data = va_arg(param, void *);
- break;
-
- case CURLOPT_MAXFILESIZE:
- /*
- * Set the maximum size of a file to download.
- */
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.max_filesize = arg;
- break;
-
-#ifdef USE_SSL
- case CURLOPT_USE_SSL:
- /*
- * Make transfers attempt to use SSL/TLS.
- */
- arg = va_arg(param, long);
- if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_ssl = (curl_usessl)arg;
- break;
-
- case CURLOPT_SSL_OPTIONS:
- arg = va_arg(param, long);
- data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
- data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
- break;
-
- case CURLOPT_PROXY_SSL_OPTIONS:
- arg = va_arg(param, long);
- data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
- data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
- break;
-
-#endif
- case CURLOPT_FTPSSLAUTH:
- /*
- * Set a specific auth for FTP-SSL transfers.
- */
- arg = va_arg(param, long);
- if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftpsslauth = (curl_ftpauth)arg;
- break;
-
- case CURLOPT_IPRESOLVE:
- arg = va_arg(param, long);
- if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ipver = arg;
- break;
-
- case CURLOPT_MAXFILESIZE_LARGE:
- /*
- * Set the maximum size of a file to download.
- */
- bigsize = va_arg(param, curl_off_t);
- if(bigsize < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.max_filesize = bigsize;
- break;
-
- case CURLOPT_TCP_NODELAY:
- /*
- * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
- * algorithm
- */
- data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_ACCOUNT:
- result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
- va_arg(param, char *));
- break;
-
- case CURLOPT_IGNORE_CONTENT_LENGTH:
- data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_CONNECT_ONLY:
- /*
- * No data transfer, set up connection and let application use the socket
- */
- data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_FTP_ALTERNATIVE_TO_USER:
- result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
- va_arg(param, char *));
- break;
-
- case CURLOPT_SOCKOPTFUNCTION:
- /*
- * socket callback function: called after socket() but before connect()
- */
- data->set.fsockopt = va_arg(param, curl_sockopt_callback);
- break;
-
- case CURLOPT_SOCKOPTDATA:
- /*
- * socket callback data pointer. Might be NULL.
- */
- data->set.sockopt_client = va_arg(param, void *);
- break;
-
- case CURLOPT_OPENSOCKETFUNCTION:
- /*
- * open/create socket callback function: called instead of socket(),
- * before connect()
- */
- data->set.fopensocket = va_arg(param, curl_opensocket_callback);
- break;
-
- case CURLOPT_OPENSOCKETDATA:
- /*
- * socket callback data pointer. Might be NULL.
- */
- data->set.opensocket_client = va_arg(param, void *);
- break;
-
- case CURLOPT_CLOSESOCKETFUNCTION:
- /*
- * close socket callback function: called instead of close()
- * when shutting down a connection
- */
- data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
- break;
-
- case CURLOPT_CLOSESOCKETDATA:
- /*
- * socket callback data pointer. Might be NULL.
- */
- data->set.closesocket_client = va_arg(param, void *);
- break;
-
- case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
- break;
-
-#ifdef USE_LIBSSH2
- /* we only include SSH options if explicitly built to support SSH */
- case CURLOPT_SSH_AUTH_TYPES:
- data->set.ssh_auth_types = va_arg(param, long);
- break;
-
- case CURLOPT_SSH_PUBLIC_KEYFILE:
- /*
- * Use this file instead of the $HOME/.ssh/id_dsa.pub file
- */
- result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
- va_arg(param, char *));
- break;
-
- case CURLOPT_SSH_PRIVATE_KEYFILE:
- /*
- * Use this file instead of the $HOME/.ssh/id_dsa file
- */
- result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
- va_arg(param, char *));
- break;
- case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
- /*
- * Option to allow for the MD5 of the host public key to be checked
- * for validation purposes.
- */
- result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
- va_arg(param, char *));
- break;
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
- case CURLOPT_SSH_KNOWNHOSTS:
- /*
- * Store the file name to read known hosts from.
- */
- result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
- va_arg(param, char *));
- break;
-
- case CURLOPT_SSH_KEYFUNCTION:
- /* setting to NULL is fine since the ssh.c functions themselves will
- then rever to use the internal default */
- data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
- break;
-
- case CURLOPT_SSH_KEYDATA:
- /*
- * Custom client data to pass to the SSH keyfunc callback
- */
- data->set.ssh_keyfunc_userp = va_arg(param, void *);
- break;
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
-
-#endif /* USE_LIBSSH2 */
-
- case CURLOPT_HTTP_TRANSFER_DECODING:
- /*
- * disable libcurl transfer encoding is used
- */
- data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_HTTP_CONTENT_DECODING:
- /*
- * raw data passed to the application when content encoding is used
- */
- data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_NEW_FILE_PERMS:
- /*
- * Uses these permissions instead of 0644
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 0777))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.new_file_perms = arg;
- break;
-
- case CURLOPT_NEW_DIRECTORY_PERMS:
- /*
- * Uses these permissions instead of 0755
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 0777))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.new_directory_perms = arg;
- break;
-
- case CURLOPT_ADDRESS_SCOPE:
- /*
- * We always get longs when passed plain numericals, but for this value we
- * know that an unsigned int will always hold the value so we blindly
- * typecast to this type
- */
- arg = va_arg(param, long);
- if((arg < 0) || (arg > 0xf))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.scope_id = curlx_sltoui(arg);
- break;
-
- case CURLOPT_PROTOCOLS:
- /* set the bitmask for the protocols that are allowed to be used for the
- transfer, which thus helps the app which takes URLs from users or other
- external inputs and want to restrict what protocol(s) to deal
- with. Defaults to CURLPROTO_ALL. */
- data->set.allowed_protocols = va_arg(param, long);
- break;
-
- case CURLOPT_REDIR_PROTOCOLS:
- /* set the bitmask for the protocols that libcurl is allowed to follow to,
- as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
- to be set in both bitmasks to be allowed to get redirected to. Defaults
- to all protocols except FILE and SCP. */
- data->set.redir_protocols = va_arg(param, long);
- break;
-
- case CURLOPT_DEFAULT_PROTOCOL:
- /* Set the protocol to use when the URL doesn't include any protocol */
- result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
- va_arg(param, char *));
- break;
-
- case CURLOPT_MAIL_FROM:
- /* Set the SMTP mail originator */
- result = setstropt(&data->set.str[STRING_MAIL_FROM],
- va_arg(param, char *));
- break;
-
- case CURLOPT_MAIL_AUTH:
- /* Set the SMTP auth originator */
- result = setstropt(&data->set.str[STRING_MAIL_AUTH],
- va_arg(param, char *));
- break;
-
- case CURLOPT_MAIL_RCPT:
- /* Set the list of mail recipients */
- data->set.mail_rcpt = va_arg(param, struct curl_slist *);
- break;
-
- case CURLOPT_SASL_IR:
- /* Enable/disable SASL initial response */
- data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_RTSP_REQUEST:
- {
- /*
- * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
- * Would this be better if the RTSPREQ_* were just moved into here?
- */
- long curl_rtspreq = va_arg(param, long);
- Curl_RtspReq rtspreq = RTSPREQ_NONE;
- switch(curl_rtspreq) {
- case CURL_RTSPREQ_OPTIONS:
- rtspreq = RTSPREQ_OPTIONS;
- break;
-
- case CURL_RTSPREQ_DESCRIBE:
- rtspreq = RTSPREQ_DESCRIBE;
- break;
-
- case CURL_RTSPREQ_ANNOUNCE:
- rtspreq = RTSPREQ_ANNOUNCE;
- break;
-
- case CURL_RTSPREQ_SETUP:
- rtspreq = RTSPREQ_SETUP;
- break;
-
- case CURL_RTSPREQ_PLAY:
- rtspreq = RTSPREQ_PLAY;
- break;
-
- case CURL_RTSPREQ_PAUSE:
- rtspreq = RTSPREQ_PAUSE;
- break;
-
- case CURL_RTSPREQ_TEARDOWN:
- rtspreq = RTSPREQ_TEARDOWN;
- break;
-
- case CURL_RTSPREQ_GET_PARAMETER:
- rtspreq = RTSPREQ_GET_PARAMETER;
- break;
-
- case CURL_RTSPREQ_SET_PARAMETER:
- rtspreq = RTSPREQ_SET_PARAMETER;
- break;
-
- case CURL_RTSPREQ_RECORD:
- rtspreq = RTSPREQ_RECORD;
- break;
-
- case CURL_RTSPREQ_RECEIVE:
- rtspreq = RTSPREQ_RECEIVE;
- break;
- default:
- rtspreq = RTSPREQ_NONE;
- }
-
- data->set.rtspreq = rtspreq;
- break;
- }
-
-
- case CURLOPT_RTSP_SESSION_ID:
- /*
- * Set the RTSP Session ID manually. Useful if the application is
- * resuming a previously established RTSP session
- */
- result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
- va_arg(param, char *));
- break;
-
- case CURLOPT_RTSP_STREAM_URI:
- /*
- * Set the Stream URI for the RTSP request. Unless the request is
- * for generic server options, the application will need to set this.
- */
- result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
- va_arg(param, char *));
- break;
-
- case CURLOPT_RTSP_TRANSPORT:
- /*
- * The content of the Transport: header for the RTSP request
- */
- result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
- va_arg(param, char *));
- break;
-
- case CURLOPT_RTSP_CLIENT_CSEQ:
- /*
- * Set the CSEQ number to issue for the next RTSP request. Useful if the
- * application is resuming a previously broken connection. The CSEQ
- * will increment from this new number henceforth.
- */
- data->state.rtsp_next_client_CSeq = va_arg(param, long);
- break;
-
- case CURLOPT_RTSP_SERVER_CSEQ:
- /* Same as the above, but for server-initiated requests */
- data->state.rtsp_next_client_CSeq = va_arg(param, long);
- break;
-
- case CURLOPT_INTERLEAVEDATA:
- data->set.rtp_out = va_arg(param, void *);
- break;
- case CURLOPT_INTERLEAVEFUNCTION:
- /* Set the user defined RTP write function */
- data->set.fwrite_rtp = va_arg(param, curl_write_callback);
- break;
-
- case CURLOPT_WILDCARDMATCH:
- data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_CHUNK_BGN_FUNCTION:
- data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
- break;
- case CURLOPT_CHUNK_END_FUNCTION:
- data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
- break;
- case CURLOPT_FNMATCH_FUNCTION:
- data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
- break;
- case CURLOPT_CHUNK_DATA:
- data->wildcard.customptr = va_arg(param, void *);
- break;
- case CURLOPT_FNMATCH_DATA:
- data->set.fnmatch_data = va_arg(param, void *);
- break;
-#ifdef USE_TLS_SRP
- case CURLOPT_TLSAUTH_USERNAME:
- result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
- va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
- break;
- case CURLOPT_PROXY_TLSAUTH_USERNAME:
- result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
- va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.authtype)
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
- break;
- case CURLOPT_TLSAUTH_PASSWORD:
- result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
- va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
- break;
- case CURLOPT_PROXY_TLSAUTH_PASSWORD:
- result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
- va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.authtype)
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
- break;
- case CURLOPT_TLSAUTH_TYPE:
- argptr = va_arg(param, char *);
- if(!argptr ||
- strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.ssl.authtype = CURL_TLSAUTH_SRP;
- else
- data->set.ssl.authtype = CURL_TLSAUTH_NONE;
- break;
- case CURLOPT_PROXY_TLSAUTH_TYPE:
- argptr = va_arg(param, char *);
- if(!argptr ||
- strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
- else
- data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
- break;
-#endif
- case CURLOPT_DNS_SERVERS:
- result = Curl_set_dns_servers(data, va_arg(param, char *));
- break;
- case CURLOPT_DNS_INTERFACE:
- result = Curl_set_dns_interface(data, va_arg(param, char *));
- break;
- case CURLOPT_DNS_LOCAL_IP4:
- result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
- break;
- case CURLOPT_DNS_LOCAL_IP6:
- result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
- break;
-
- case CURLOPT_TCP_KEEPALIVE:
- data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_TCP_KEEPIDLE:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.tcp_keepidle = arg;
- break;
- case CURLOPT_TCP_KEEPINTVL:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.tcp_keepintvl = arg;
- break;
- case CURLOPT_TCP_FASTOPEN:
-#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
- data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
-#else
- result = CURLE_NOT_BUILT_IN;
-#endif
- break;
- case CURLOPT_SSL_ENABLE_NPN:
- data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_SSL_ENABLE_ALPN:
- data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
-#ifdef USE_UNIX_SOCKETS
- case CURLOPT_UNIX_SOCKET_PATH:
- data->set.abstract_unix_socket = FALSE;
- result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
- va_arg(param, char *));
- break;
- case CURLOPT_ABSTRACT_UNIX_SOCKET:
- data->set.abstract_unix_socket = TRUE;
- result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
- va_arg(param, char *));
- break;
-#endif
-
- case CURLOPT_PATH_AS_IS:
- data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_PIPEWAIT:
- data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
- case CURLOPT_STREAM_WEIGHT:
-#ifndef USE_NGHTTP2
- return CURLE_NOT_BUILT_IN;
-#else
- arg = va_arg(param, long);
- if((arg >= 1) && (arg <= 256))
- data->set.stream_weight = (int)arg;
- break;
-#endif
- case CURLOPT_STREAM_DEPENDS:
- case CURLOPT_STREAM_DEPENDS_E:
- {
-#ifndef USE_NGHTTP2
- return CURLE_NOT_BUILT_IN;
-#else
- struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
- if(!dep || GOOD_EASY_HANDLE(dep)) {
- if(data->set.stream_depends_on) {
- Curl_http2_remove_child(data->set.stream_depends_on, data);
- }
- Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
- }
- break;
-#endif
- }
- case CURLOPT_CONNECT_TO:
- data->set.connect_to = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_SUPPRESS_CONNECT_HEADERS:
- data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
- break;
- case CURLOPT_SSH_COMPRESSION:
- data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
- break;
- default:
- /* unknown tag and its companion, just ignore: */
- result = CURLE_UNKNOWN_OPTION;
- break;
- }
-
- return result;
-}
-
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
static void conn_reset_postponed_data(struct connectdata *conn, int num)
{
@@ -5249,8 +2726,8 @@ static CURLcode parse_proxy(struct Curl_easy *data,
atsign = strchr(proxyptr, '@');
if(atsign) {
CURLcode result =
- parse_login_details(proxyptr, atsign - proxyptr,
- &proxyuser, &proxypasswd, NULL);
+ Curl_parse_login_details(proxyptr, atsign - proxyptr,
+ &proxyuser, &proxypasswd, NULL);
if(result)
return result;
proxyptr = atsign + 1;
@@ -5641,10 +3118,11 @@ static CURLcode parse_url_login(struct Curl_easy *data,
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. */
- result = parse_login_details(login, ptr - login - 1,
- &userp, &passwdp,
- (conn->handler->flags & PROTOPT_URLOPTIONS)?
- &optionsp:NULL);
+ result =
+ Curl_parse_login_details(login, ptr - login - 1,
+ &userp, &passwdp,
+ (conn->handler->flags & PROTOPT_URLOPTIONS)?
+ &optionsp:NULL);
if(result)
goto out;
@@ -5700,7 +3178,7 @@ static CURLcode parse_url_login(struct Curl_easy *data,
}
/*
- * parse_login_details()
+ * Curl_parse_login_details()
*
* This is used to parse a login string for user name, password and options in
* the following formats:
@@ -5728,9 +3206,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
*
* Returns CURLE_OK on success.
*/
-static CURLcode parse_login_details(const char *login, const size_t len,
- char **userp, char **passwdp,
- char **optionsp)
+CURLcode Curl_parse_login_details(const char *login, const size_t len,
+ char **userp, char **passwdp,
+ char **optionsp)
{
CURLcode result = CURLE_OK;
char *ubuf = NULL;
diff --git a/lib/url.h b/lib/url.h
index 41c740379..5dd04fdff 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -23,6 +23,10 @@
***************************************************************************/
#include "curl_setup.h"
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX CURL_MAX_READ_SIZE
+#define READBUFFER_MIN 1024
+
/*
* Prototypes for library-wide functions provided by url.c
*/
@@ -51,7 +55,9 @@ int Curl_protocol_getsock(struct connectdata *conn,
int Curl_doing_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
-
+CURLcode Curl_parse_login_details(const char *login, const size_t len,
+ char **userptr, char **passwdptr,
+ char **optionsptr);
bool Curl_isPipeliningEnabled(const struct Curl_easy *handle);
CURLcode Curl_addHandleToPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline);