14f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta/***************************************************************************
2e83b0cadc67882c1ba7f430d16dab80c9b3a0228Dan Handley *                                  _   _ ____  _
34f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *  Project                     ___| | | |  _ \| |
44f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *                             / __| | | | |_) | |
54f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *                            | (__| |_| |  _ <| |___
64f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *                             \___|\___/|_| \_\_____|
74f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *
84f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
94f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *
104f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * This software is licensed as described in the file COPYING, which
114f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * you should have received as part of this distribution. The terms
124f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * are also available at https://curl.haxx.se/docs/copyright.html.
134f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *
144f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * You may opt to use, copy, modify, merge, publish, distribute and/or sell
154f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * copies of the Software, and permit persons to whom the Software is
164f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * furnished to do so, under the terms of the COPYING file.
174f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *
184f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
194f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta * KIND, either express or implied.
204f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta *
214f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta ***************************************************************************/
224f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
234f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "curl_setup.h"
244f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
254f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include <limits.h>
264f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
274f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#ifdef HAVE_NETINET_IN_H
284f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include <netinet/in.h>
294f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#endif
304f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
3197043ac98e13a726dbf8b3b41654dca759e3da2cDan Handley#ifdef HAVE_LINUX_TCP_H
3297043ac98e13a726dbf8b3b41654dca759e3da2cDan Handley#include <linux/tcp.h>
3397043ac98e13a726dbf8b3b41654dca759e3da2cDan Handley#endif
344f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
354f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "urldata.h"
364f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "url.h"
374f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "progress.h"
384f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "content_encoding.h"
394f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "strcase.h"
404f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "share.h"
414f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "vtls/vtls.h"
424f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "warnless.h"
434f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "sendf.h"
444f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "http2.h"
4507f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta#include "setopt.h"
464f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
4707f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta/* The last 3 #include files should be in this order */
4807f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta#include "curl_printf.h"
494f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "curl_memory.h"
504f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta#include "memdebug.h"
514f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
524f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin GuptaCURLcode Curl_setstropt(char **charp, const char *s)
5307f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta{
5407f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta  /* Release the previous storage at `charp' and replace by a dynamic storage
5507f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta     copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
5607f4e078b6871e5c74f6cb38f2726a2cfcb2b746Achin Gupta
574f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta  Curl_safefree(*charp);
584f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
594f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta  if(s) {
604f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta    char *str = strdup(s);
617935d0a59d439c993b79814ab414d37e4a90d9a6Andrew Thoelke
624f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta    if(!str)
634f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta      return CURLE_OUT_OF_MEMORY;
644f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
654f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta    *charp = str;
664f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta  }
674f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
684f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta  return CURLE_OK;
694f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta}
704f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta
714f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Guptastatic CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
724f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta{
734f6ad66ae9fcc8bcb3b0fcee10b7ab1ffcaf1a5Achin Gupta  CURLcode result = CURLE_OK;
74a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan  char *user = NULL;
75a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan  char *passwd = NULL;
76a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan
77a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan  /* Parse the login details if specified. It not then we treat NULL as a hint
78a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan     to clear the existing data */
79a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan  if(option) {
80a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan    result = Curl_parse_login_details(option, strlen(option),
81a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan                                      (userp ? &user : NULL),
82a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan                                      (passwdp ? &passwd : NULL),
83a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan                                      NULL);
84a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan  }
85a7934d69508872919787742c7680b68807c24361Jeenu Viswambharan
860a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke  if(!result) {
870a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke    /* Store the username part of option if required */
880a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke    if(userp) {
890a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke      if(!user && option && option[0] == ':') {
900a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke        /* Allocate an empty string instead of returning NULL as user name */
910a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke        user = strdup("");
920a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke        if(!user)
930a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke          result = CURLE_OUT_OF_MEMORY;
940a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke      }
950a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke
960a30cf54af7bb1f77b405062b1d5b44e809d0290Andrew Thoelke      Curl_safefree(*userp);
972bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke      *userp = user;
982bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    }
992bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke
1002bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    /* Store the password part of option if required */
1012bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    if(passwdp) {
1022bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke      Curl_safefree(*passwdp);
1032bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke      *passwdp = passwd;
1042bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    }
1052bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  }
1062bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke
1072bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  return result;
1082bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke}
1092bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke
1102bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke#define C_SSLVERSION_VALUE(x) (x & 0xffff)
1112bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
1122bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke
1132bf28e620a6f05700753a2b45a888c6623e20723Andrew ThoelkeCURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
1142bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke                      va_list param)
1152bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke{
1162bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  char *argptr;
1172bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  CURLcode result = CURLE_OK;
1182bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  long arg;
1192bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  curl_off_t bigsize;
1202bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke
1212bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  switch(option) {
1222bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  case CURLOPT_DNS_CACHE_TIMEOUT:
1232bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    arg = va_arg(param, long);
1242bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    if(arg < -1)
1252bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke      return CURLE_BAD_FUNCTION_ARGUMENT;
1262bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    data->set.dns_cache_timeout = arg;
1272bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    break;
1282bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  case CURLOPT_DNS_USE_GLOBAL_CACHE:
1292bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    /* remember we want this enabled */
1302bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    arg = va_arg(param, long);
1312bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
1322bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    break;
1332bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke  case CURLOPT_SSL_CIPHER_LIST:
1342bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    /* set a list of cipher we want to use in the SSL connection */
1352bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke    result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
1362bf28e620a6f05700753a2b45a888c6623e20723Andrew Thoelke                            va_arg(param, char *));
137    break;
138  case CURLOPT_PROXY_SSL_CIPHER_LIST:
139    /* set a list of cipher we want to use in the SSL connection for proxy */
140    result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
141                            va_arg(param, char *));
142    break;
143
144  case CURLOPT_RANDOM_FILE:
145    /*
146     * This is the path name to a file that contains random data to seed
147     * the random SSL stuff with. The file is only used for reading.
148     */
149    result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
150                            va_arg(param, char *));
151    break;
152  case CURLOPT_EGDSOCKET:
153    /*
154     * The Entropy Gathering Daemon socket pathname
155     */
156    result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
157                            va_arg(param, char *));
158    break;
159  case CURLOPT_MAXCONNECTS:
160    /*
161     * Set the absolute number of maximum simultaneous alive connection that
162     * libcurl is allowed to have.
163     */
164    arg = va_arg(param, long);
165    if(arg < 0)
166      return CURLE_BAD_FUNCTION_ARGUMENT;
167    data->set.maxconnects = arg;
168    break;
169  case CURLOPT_FORBID_REUSE:
170    /*
171     * When this transfer is done, it must not be left to be reused by a
172     * subsequent transfer but shall be closed immediately.
173     */
174    data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
175    break;
176  case CURLOPT_FRESH_CONNECT:
177    /*
178     * This transfer shall not use a previously cached connection but
179     * should be made with a fresh new connect!
180     */
181    data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
182    break;
183  case CURLOPT_VERBOSE:
184    /*
185     * Verbose means infof() calls that give a lot of information about
186     * the connection and transfer procedures as well as internal choices.
187     */
188    data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
189    break;
190  case CURLOPT_HEADER:
191    /*
192     * Set to include the header in the general data output stream.
193     */
194    data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
195    break;
196  case CURLOPT_NOPROGRESS:
197    /*
198     * Shut off the internal supported progress meter
199     */
200    data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
201    if(data->set.hide_progress)
202      data->progress.flags |= PGRS_HIDE;
203    else
204      data->progress.flags &= ~PGRS_HIDE;
205    break;
206  case CURLOPT_NOBODY:
207    /*
208     * Do not include the body part in the output data stream.
209     */
210    data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
211    break;
212  case CURLOPT_FAILONERROR:
213    /*
214     * Don't output the >=400 error code HTML-page, but instead only
215     * return error.
216     */
217    data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
218    break;
219  case CURLOPT_KEEP_SENDING_ON_ERROR:
220    data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
221      TRUE : FALSE;
222    break;
223  case CURLOPT_UPLOAD:
224  case CURLOPT_PUT:
225    /*
226     * We want to sent data to the remote host. If this is HTTP, that equals
227     * using the PUT request.
228     */
229    data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
230    if(data->set.upload) {
231      /* If this is HTTP, PUT is what's needed to "upload" */
232      data->set.httpreq = HTTPREQ_PUT;
233      data->set.opt_no_body = FALSE; /* this is implied */
234    }
235    else
236      /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
237         then this can be changed to HEAD later on) */
238      data->set.httpreq = HTTPREQ_GET;
239    break;
240  case CURLOPT_REQUEST_TARGET:
241    result = Curl_setstropt(&data->set.str[STRING_TARGET],
242                            va_arg(param, char *));
243    break;
244  case CURLOPT_FILETIME:
245    /*
246     * Try to get the file time of the remote document. The time will
247     * later (possibly) become available using curl_easy_getinfo().
248     */
249    data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
250    break;
251  case CURLOPT_FTP_CREATE_MISSING_DIRS:
252    /*
253     * An FTP option that modifies an upload to create missing directories on
254     * the server.
255     */
256    switch(va_arg(param, long)) {
257    case 0:
258      data->set.ftp_create_missing_dirs = 0;
259      break;
260    case 1:
261      data->set.ftp_create_missing_dirs = 1;
262      break;
263    case 2:
264      data->set.ftp_create_missing_dirs = 2;
265      break;
266    default:
267      /* reserve other values for future use */
268      result = CURLE_UNKNOWN_OPTION;
269      break;
270    }
271    break;
272  case CURLOPT_SERVER_RESPONSE_TIMEOUT:
273    /*
274     * Option that specifies how quickly an server response must be obtained
275     * before it is considered failure. For pingpong protocols.
276     */
277    arg = va_arg(param, long);
278    if((arg >= 0) && (arg <= (INT_MAX/1000)))
279      data->set.server_response_timeout = arg * 1000;
280    else
281      return CURLE_BAD_FUNCTION_ARGUMENT;
282    break;
283  case CURLOPT_TFTP_NO_OPTIONS:
284    /*
285     * Option that prevents libcurl from sending TFTP option requests to the
286     * server.
287     */
288    data->set.tftp_no_options = va_arg(param, long) != 0;
289    break;
290  case CURLOPT_TFTP_BLKSIZE:
291    /*
292     * TFTP option that specifies the block size to use for data transmission.
293     */
294    arg = va_arg(param, long);
295    if(arg < 0)
296      return CURLE_BAD_FUNCTION_ARGUMENT;
297    data->set.tftp_blksize = arg;
298    break;
299  case CURLOPT_DIRLISTONLY:
300    /*
301     * An option that changes the command to one that asks for a list
302     * only, no file info details.
303     */
304    data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
305    break;
306  case CURLOPT_APPEND:
307    /*
308     * We want to upload and append to an existing file.
309     */
310    data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
311    break;
312  case CURLOPT_FTP_FILEMETHOD:
313    /*
314     * How do access files over FTP.
315     */
316    arg = va_arg(param, long);
317    if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
318      return CURLE_BAD_FUNCTION_ARGUMENT;
319    data->set.ftp_filemethod = (curl_ftpfile)arg;
320    break;
321  case CURLOPT_NETRC:
322    /*
323     * Parse the $HOME/.netrc file
324     */
325    arg = va_arg(param, long);
326    if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED))
327      return CURLE_BAD_FUNCTION_ARGUMENT;
328    data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
329    break;
330  case CURLOPT_NETRC_FILE:
331    /*
332     * Use this file instead of the $HOME/.netrc file
333     */
334    result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
335                            va_arg(param, char *));
336    break;
337  case CURLOPT_TRANSFERTEXT:
338    /*
339     * This option was previously named 'FTPASCII'. Renamed to work with
340     * more protocols than merely FTP.
341     *
342     * Transfer using ASCII (instead of BINARY).
343     */
344    data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
345    break;
346  case CURLOPT_TIMECONDITION:
347    /*
348     * Set HTTP time condition. This must be one of the defines in the
349     * curl/curl.h header file.
350     */
351    arg = va_arg(param, long);
352    if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD))
353      return CURLE_BAD_FUNCTION_ARGUMENT;
354    data->set.timecondition = (curl_TimeCond)arg;
355    break;
356  case CURLOPT_TIMEVALUE:
357    /*
358     * This is the value to compare with the remote document with the
359     * method set with CURLOPT_TIMECONDITION
360     */
361    data->set.timevalue = (time_t)va_arg(param, long);
362    break;
363
364  case CURLOPT_SSLVERSION:
365  case CURLOPT_PROXY_SSLVERSION:
366    /*
367     * Set explicit SSL version to try to connect with, as some SSL
368     * implementations are lame.
369     */
370#ifdef USE_SSL
371    {
372      long version, version_max;
373      struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ?
374                                            &data->set.ssl.primary :
375                                            &data->set.proxy_ssl.primary);
376
377      arg = va_arg(param, long);
378
379      version = C_SSLVERSION_VALUE(arg);
380      version_max = C_SSLVERSION_MAX_VALUE(arg);
381
382      if(version < CURL_SSLVERSION_DEFAULT ||
383         version >= CURL_SSLVERSION_LAST ||
384         version_max < CURL_SSLVERSION_MAX_NONE ||
385         version_max >= CURL_SSLVERSION_MAX_LAST)
386        return CURLE_BAD_FUNCTION_ARGUMENT;
387
388      primary->version = version;
389      primary->version_max = version_max;
390    }
391#else
392    result = CURLE_UNKNOWN_OPTION;
393#endif
394    break;
395
396#ifndef CURL_DISABLE_HTTP
397  case CURLOPT_AUTOREFERER:
398    /*
399     * Switch on automatic referer that gets set if curl follows locations.
400     */
401    data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
402    break;
403
404  case CURLOPT_ACCEPT_ENCODING:
405    /*
406     * String to use at the value of Accept-Encoding header.
407     *
408     * If the encoding is set to "" we use an Accept-Encoding header that
409     * encompasses all the encodings we support.
410     * If the encoding is set to NULL we don't send an Accept-Encoding header
411     * and ignore an received Content-Encoding header.
412     *
413     */
414    argptr = va_arg(param, char *);
415    if(argptr && !*argptr) {
416      argptr = Curl_all_content_encodings();
417      if(!argptr)
418        result = CURLE_OUT_OF_MEMORY;
419      else {
420        result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
421        free(argptr);
422      }
423    }
424    else
425      result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
426    break;
427
428  case CURLOPT_TRANSFER_ENCODING:
429    data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
430      TRUE : FALSE;
431    break;
432
433  case CURLOPT_FOLLOWLOCATION:
434    /*
435     * Follow Location: header hints on a HTTP-server.
436     */
437    data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
438    break;
439
440  case CURLOPT_UNRESTRICTED_AUTH:
441    /*
442     * Send authentication (user+password) when following locations, even when
443     * hostname changed.
444     */
445    data->set.allow_auth_to_other_hosts =
446      (0 != va_arg(param, long)) ? TRUE : FALSE;
447    break;
448
449  case CURLOPT_MAXREDIRS:
450    /*
451     * The maximum amount of hops you allow curl to follow Location:
452     * headers. This should mostly be used to detect never-ending loops.
453     */
454    arg = va_arg(param, long);
455    if(arg < -1)
456      return CURLE_BAD_FUNCTION_ARGUMENT;
457    data->set.maxredirs = arg;
458    break;
459
460  case CURLOPT_POSTREDIR:
461    /*
462     * Set the behaviour of POST when redirecting
463     * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
464     * CURL_REDIR_POST_301 - POST is kept as POST after 301
465     * CURL_REDIR_POST_302 - POST is kept as POST after 302
466     * CURL_REDIR_POST_303 - POST is kept as POST after 303
467     * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
468     * other - POST is kept as POST after 301 and 302
469     */
470    arg = va_arg(param, long);
471    if(arg < CURL_REDIR_GET_ALL)
472      /* no return error on too high numbers since the bitmask could be
473         extended in a future */
474      return CURLE_BAD_FUNCTION_ARGUMENT;
475    data->set.keep_post = arg & CURL_REDIR_POST_ALL;
476    break;
477
478  case CURLOPT_POST:
479    /* Does this option serve a purpose anymore? Yes it does, when
480       CURLOPT_POSTFIELDS isn't used and the POST data is read off the
481       callback! */
482    if(va_arg(param, long)) {
483      data->set.httpreq = HTTPREQ_POST;
484      data->set.opt_no_body = FALSE; /* this is implied */
485    }
486    else
487      data->set.httpreq = HTTPREQ_GET;
488    break;
489
490  case CURLOPT_COPYPOSTFIELDS:
491    /*
492     * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
493     * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
494     *  CURLOPT_COPYPOSTFIELDS and not altered later.
495     */
496    argptr = va_arg(param, char *);
497
498    if(!argptr || data->set.postfieldsize == -1)
499      result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
500    else {
501      /*
502       *  Check that requested length does not overflow the size_t type.
503       */
504
505      if((data->set.postfieldsize < 0) ||
506         ((sizeof(curl_off_t) != sizeof(size_t)) &&
507          (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
508        result = CURLE_OUT_OF_MEMORY;
509      else {
510        char *p;
511
512        (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
513
514        /* Allocate even when size == 0. This satisfies the need of possible
515           later address compare to detect the COPYPOSTFIELDS mode, and
516           to mark that postfields is used rather than read function or
517           form data.
518        */
519        p = malloc((size_t)(data->set.postfieldsize?
520                            data->set.postfieldsize:1));
521
522        if(!p)
523          result = CURLE_OUT_OF_MEMORY;
524        else {
525          if(data->set.postfieldsize)
526            memcpy(p, argptr, (size_t)data->set.postfieldsize);
527
528          data->set.str[STRING_COPYPOSTFIELDS] = p;
529        }
530      }
531    }
532
533    data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
534    data->set.httpreq = HTTPREQ_POST;
535    break;
536
537  case CURLOPT_POSTFIELDS:
538    /*
539     * Like above, but use static data instead of copying it.
540     */
541    data->set.postfields = va_arg(param, void *);
542    /* Release old copied data. */
543    (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
544    data->set.httpreq = HTTPREQ_POST;
545    break;
546
547  case CURLOPT_POSTFIELDSIZE:
548    /*
549     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
550     * figure it out. Enables binary posts.
551     */
552    bigsize = va_arg(param, long);
553    if(bigsize < -1)
554      return CURLE_BAD_FUNCTION_ARGUMENT;
555
556    if(data->set.postfieldsize < bigsize &&
557       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
558      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
559      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
560      data->set.postfields = NULL;
561    }
562
563    data->set.postfieldsize = bigsize;
564    break;
565
566  case CURLOPT_POSTFIELDSIZE_LARGE:
567    /*
568     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
569     * figure it out. Enables binary posts.
570     */
571    bigsize = va_arg(param, curl_off_t);
572    if(bigsize < -1)
573      return CURLE_BAD_FUNCTION_ARGUMENT;
574
575    if(data->set.postfieldsize < bigsize &&
576       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
577      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
578      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
579      data->set.postfields = NULL;
580    }
581
582    data->set.postfieldsize = bigsize;
583    break;
584
585  case CURLOPT_HTTPPOST:
586    /*
587     * Set to make us do HTTP POST
588     */
589    data->set.httppost = va_arg(param, struct curl_httppost *);
590    data->set.httpreq = HTTPREQ_POST_FORM;
591    data->set.opt_no_body = FALSE; /* this is implied */
592    break;
593#endif   /* CURL_DISABLE_HTTP */
594
595  case CURLOPT_MIMEPOST:
596    /*
597     * Set to make us do MIME/form POST
598     */
599    result = Curl_mime_set_subparts(&data->set.mimepost,
600                                    va_arg(param, curl_mime *), FALSE);
601    if(!result) {
602      data->set.httpreq = HTTPREQ_POST_MIME;
603      data->set.opt_no_body = FALSE; /* this is implied */
604    }
605    break;
606
607  case CURLOPT_REFERER:
608    /*
609     * String to set in the HTTP Referer: field.
610     */
611    if(data->change.referer_alloc) {
612      Curl_safefree(data->change.referer);
613      data->change.referer_alloc = FALSE;
614    }
615    result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
616                            va_arg(param, char *));
617    data->change.referer = data->set.str[STRING_SET_REFERER];
618    break;
619
620  case CURLOPT_USERAGENT:
621    /*
622     * String to use in the HTTP User-Agent field
623     */
624    result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
625                            va_arg(param, char *));
626    break;
627
628  case CURLOPT_HTTPHEADER:
629    /*
630     * Set a list with HTTP headers to use (or replace internals with)
631     */
632    data->set.headers = va_arg(param, struct curl_slist *);
633    break;
634
635#ifndef CURL_DISABLE_HTTP
636  case CURLOPT_PROXYHEADER:
637    /*
638     * Set a list with proxy headers to use (or replace internals with)
639     *
640     * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
641     * long time we remain doing it this way until CURLOPT_PROXYHEADER is
642     * used. As soon as this option has been used, if set to anything but
643     * NULL, custom headers for proxies are only picked from this list.
644     *
645     * Set this option to NULL to restore the previous behavior.
646     */
647    data->set.proxyheaders = va_arg(param, struct curl_slist *);
648    break;
649
650  case CURLOPT_HEADEROPT:
651    /*
652     * Set header option.
653     */
654    arg = va_arg(param, long);
655    data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
656    break;
657
658  case CURLOPT_HTTP200ALIASES:
659    /*
660     * Set a list of aliases for HTTP 200 in response header
661     */
662    data->set.http200aliases = va_arg(param, struct curl_slist *);
663    break;
664
665#if !defined(CURL_DISABLE_COOKIES)
666  case CURLOPT_COOKIE:
667    /*
668     * Cookie string to send to the remote server in the request.
669     */
670    result = Curl_setstropt(&data->set.str[STRING_COOKIE],
671                            va_arg(param, char *));
672    break;
673
674  case CURLOPT_COOKIEFILE:
675    /*
676     * Set cookie file to read and parse. Can be used multiple times.
677     */
678    argptr = (char *)va_arg(param, void *);
679    if(argptr) {
680      struct curl_slist *cl;
681      /* append the cookie file name to the list of file names, and deal with
682         them later */
683      cl = curl_slist_append(data->change.cookielist, argptr);
684      if(!cl) {
685        curl_slist_free_all(data->change.cookielist);
686        data->change.cookielist = NULL;
687        return CURLE_OUT_OF_MEMORY;
688      }
689      data->change.cookielist = cl; /* store the list for later use */
690    }
691    break;
692
693  case CURLOPT_COOKIEJAR:
694    /*
695     * Set cookie file name to dump all cookies to when we're done.
696     */
697  {
698    struct CookieInfo *newcookies;
699    result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
700                            va_arg(param, char *));
701
702    /*
703     * Activate the cookie parser. This may or may not already
704     * have been made.
705     */
706    newcookies = Curl_cookie_init(data, NULL, data->cookies,
707                                  data->set.cookiesession);
708    if(!newcookies)
709      result = CURLE_OUT_OF_MEMORY;
710    data->cookies = newcookies;
711  }
712  break;
713
714  case CURLOPT_COOKIESESSION:
715    /*
716     * Set this option to TRUE to start a new "cookie session". It will
717     * prevent the forthcoming read-cookies-from-file actions to accept
718     * cookies that are marked as being session cookies, as they belong to a
719     * previous session.
720     *
721     * In the original Netscape cookie spec, "session cookies" are cookies
722     * with no expire date set. RFC2109 describes the same action if no
723     * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
724     * a 'Discard' action that can enforce the discard even for cookies that
725     * have a Max-Age.
726     *
727     * We run mostly with the original cookie spec, as hardly anyone implements
728     * anything else.
729     */
730    data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
731    break;
732
733  case CURLOPT_COOKIELIST:
734    argptr = va_arg(param, char *);
735
736    if(argptr == NULL)
737      break;
738
739    if(strcasecompare(argptr, "ALL")) {
740      /* clear all cookies */
741      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
742      Curl_cookie_clearall(data->cookies);
743      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
744    }
745    else if(strcasecompare(argptr, "SESS")) {
746      /* clear session cookies */
747      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
748      Curl_cookie_clearsess(data->cookies);
749      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
750    }
751    else if(strcasecompare(argptr, "FLUSH")) {
752      /* flush cookies to file, takes care of the locking */
753      Curl_flush_cookies(data, 0);
754    }
755    else if(strcasecompare(argptr, "RELOAD")) {
756      /* reload cookies from file */
757      Curl_cookie_loadfiles(data);
758      break;
759    }
760    else {
761      if(!data->cookies)
762        /* if cookie engine was not running, activate it */
763        data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
764
765      argptr = strdup(argptr);
766      if(!argptr || !data->cookies) {
767        result = CURLE_OUT_OF_MEMORY;
768        free(argptr);
769      }
770      else {
771        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
772
773        if(checkprefix("Set-Cookie:", argptr))
774          /* HTTP Header format line */
775          Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
776
777        else
778          /* Netscape format line */
779          Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
780
781        Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
782        free(argptr);
783      }
784    }
785
786    break;
787#endif /* !CURL_DISABLE_COOKIES */
788
789  case CURLOPT_HTTPGET:
790    /*
791     * Set to force us do HTTP GET
792     */
793    if(va_arg(param, long)) {
794      data->set.httpreq = HTTPREQ_GET;
795      data->set.upload = FALSE; /* switch off upload */
796      data->set.opt_no_body = FALSE; /* this is implied */
797    }
798    break;
799
800  case CURLOPT_HTTP_VERSION:
801    /*
802     * This sets a requested HTTP version to be used. The value is one of
803     * the listed enums in curl/curl.h.
804     */
805    arg = va_arg(param, long);
806    if(arg < CURL_HTTP_VERSION_NONE)
807      return CURLE_BAD_FUNCTION_ARGUMENT;
808#ifndef USE_NGHTTP2
809    if(arg >= CURL_HTTP_VERSION_2)
810      return CURLE_UNSUPPORTED_PROTOCOL;
811#else
812    if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
813      return CURLE_UNSUPPORTED_PROTOCOL;
814#endif
815    data->set.httpversion = arg;
816    break;
817
818  case CURLOPT_EXPECT_100_TIMEOUT_MS:
819    /*
820     * Time to wait for a response to a HTTP request containing an
821     * Expect: 100-continue header before sending the data anyway.
822     */
823    arg = va_arg(param, long);
824    if(arg < 0)
825      return CURLE_BAD_FUNCTION_ARGUMENT;
826    data->set.expect_100_timeout = arg;
827    break;
828
829#endif   /* CURL_DISABLE_HTTP */
830
831  case CURLOPT_HTTPAUTH:
832    /*
833     * Set HTTP Authentication type BITMASK.
834     */
835  {
836    int bitcheck;
837    bool authbits;
838    unsigned long auth = va_arg(param, unsigned long);
839
840    if(auth == CURLAUTH_NONE) {
841      data->set.httpauth = auth;
842      break;
843    }
844
845    /* the DIGEST_IE bit is only used to set a special marker, for all the
846       rest we need to handle it as normal DIGEST */
847    data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
848
849    if(auth & CURLAUTH_DIGEST_IE) {
850      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
851      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
852    }
853
854    /* switch off bits we can't support */
855#ifndef USE_NTLM
856    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
857    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
858#elif !defined(NTLM_WB_ENABLED)
859    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
860#endif
861#ifndef USE_SPNEGO
862    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
863                                    GSS-API or SSPI */
864#endif
865
866    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
867    bitcheck = 0;
868    authbits = FALSE;
869    while(bitcheck < 31) {
870      if(auth & (1UL << bitcheck++)) {
871        authbits = TRUE;
872        break;
873      }
874    }
875    if(!authbits)
876      return CURLE_NOT_BUILT_IN; /* no supported types left! */
877
878    data->set.httpauth = auth;
879  }
880  break;
881
882  case CURLOPT_CUSTOMREQUEST:
883    /*
884     * Set a custom string to use as request
885     */
886    result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
887                            va_arg(param, char *));
888
889    /* we don't set
890       data->set.httpreq = HTTPREQ_CUSTOM;
891       here, we continue as if we were using the already set type
892       and this just changes the actual request keyword */
893    break;
894
895#ifndef CURL_DISABLE_PROXY
896  case CURLOPT_HTTPPROXYTUNNEL:
897    /*
898     * Tunnel operations through the proxy instead of normal proxy use
899     */
900    data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
901      TRUE : FALSE;
902    break;
903
904  case CURLOPT_PROXYPORT:
905    /*
906     * Explicitly set HTTP proxy port number.
907     */
908    arg = va_arg(param, long);
909    if((arg < 0) || (arg > 65535))
910      return CURLE_BAD_FUNCTION_ARGUMENT;
911    data->set.proxyport = arg;
912    break;
913
914  case CURLOPT_PROXYAUTH:
915    /*
916     * Set HTTP Authentication type BITMASK.
917     */
918  {
919    int bitcheck;
920    bool authbits;
921    unsigned long auth = va_arg(param, unsigned long);
922
923    if(auth == CURLAUTH_NONE) {
924      data->set.proxyauth = auth;
925      break;
926    }
927
928    /* the DIGEST_IE bit is only used to set a special marker, for all the
929       rest we need to handle it as normal DIGEST */
930    data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
931
932    if(auth & CURLAUTH_DIGEST_IE) {
933      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
934      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
935    }
936    /* switch off bits we can't support */
937#ifndef USE_NTLM
938    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
939    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
940#elif !defined(NTLM_WB_ENABLED)
941    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
942#endif
943#ifndef USE_SPNEGO
944    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
945                                    GSS-API or SSPI */
946#endif
947
948    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
949    bitcheck = 0;
950    authbits = FALSE;
951    while(bitcheck < 31) {
952      if(auth & (1UL << bitcheck++)) {
953        authbits = TRUE;
954        break;
955      }
956    }
957    if(!authbits)
958      return CURLE_NOT_BUILT_IN; /* no supported types left! */
959
960    data->set.proxyauth = auth;
961  }
962  break;
963
964  case CURLOPT_PROXY:
965    /*
966     * Set proxy server:port to use as proxy.
967     *
968     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
969     * we explicitly say that we don't want to use a proxy
970     * (even though there might be environment variables saying so).
971     *
972     * Setting it to NULL, means no proxy but allows the environment variables
973     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
974     */
975    result = Curl_setstropt(&data->set.str[STRING_PROXY],
976                            va_arg(param, char *));
977    break;
978
979  case CURLOPT_PRE_PROXY:
980    /*
981     * Set proxy server:port to use as SOCKS proxy.
982     *
983     * If the proxy is set to "" or NULL we explicitly say that we don't want
984     * to use the socks proxy.
985     */
986    result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY],
987                            va_arg(param, char *));
988    break;
989
990  case CURLOPT_PROXYTYPE:
991    /*
992     * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
993     */
994    arg = va_arg(param, long);
995    if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
996      return CURLE_BAD_FUNCTION_ARGUMENT;
997    data->set.proxytype = (curl_proxytype)arg;
998    break;
999
1000  case CURLOPT_PROXY_TRANSFER_MODE:
1001    /*
1002     * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
1003     */
1004    switch(va_arg(param, long)) {
1005    case 0:
1006      data->set.proxy_transfer_mode = FALSE;
1007      break;
1008    case 1:
1009      data->set.proxy_transfer_mode = TRUE;
1010      break;
1011    default:
1012      /* reserve other values for future use */
1013      result = CURLE_UNKNOWN_OPTION;
1014      break;
1015    }
1016    break;
1017#endif   /* CURL_DISABLE_PROXY */
1018
1019  case CURLOPT_SOCKS5_AUTH:
1020    data->set.socks5auth = va_arg(param, unsigned long);
1021    if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
1022      result = CURLE_NOT_BUILT_IN;
1023    break;
1024#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
1025  case CURLOPT_SOCKS5_GSSAPI_NEC:
1026    /*
1027     * Set flag for NEC SOCK5 support
1028     */
1029    data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
1030    break;
1031
1032  case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1033  case CURLOPT_PROXY_SERVICE_NAME:
1034    /*
1035     * Set proxy authentication service name for Kerberos 5 and SPNEGO
1036     */
1037    result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
1038                            va_arg(param, char *));
1039    break;
1040#endif
1041
1042#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) ||     \
1043  defined(USE_SPNEGO)
1044  case CURLOPT_SERVICE_NAME:
1045    /*
1046     * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
1047     */
1048    result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME],
1049                            va_arg(param, char *));
1050    break;
1051
1052#endif
1053
1054  case CURLOPT_HEADERDATA:
1055    /*
1056     * Custom pointer to pass the header write callback function
1057     */
1058    data->set.writeheader = (void *)va_arg(param, void *);
1059    break;
1060  case CURLOPT_ERRORBUFFER:
1061    /*
1062     * Error buffer provided by the caller to get the human readable
1063     * error string in.
1064     */
1065    data->set.errorbuffer = va_arg(param, char *);
1066    break;
1067  case CURLOPT_WRITEDATA:
1068    /*
1069     * FILE pointer to write to. Or possibly
1070     * used as argument to the write callback.
1071     */
1072    data->set.out = va_arg(param, void *);
1073    break;
1074  case CURLOPT_FTPPORT:
1075    /*
1076     * Use FTP PORT, this also specifies which IP address to use
1077     */
1078    result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
1079                            va_arg(param, char *));
1080    data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
1081    break;
1082
1083  case CURLOPT_FTP_USE_EPRT:
1084    data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
1085    break;
1086
1087  case CURLOPT_FTP_USE_EPSV:
1088    data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
1089    break;
1090
1091  case CURLOPT_FTP_USE_PRET:
1092    data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
1093    break;
1094
1095  case CURLOPT_FTP_SSL_CCC:
1096    arg = va_arg(param, long);
1097    if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE))
1098      return CURLE_BAD_FUNCTION_ARGUMENT;
1099    data->set.ftp_ccc = (curl_ftpccc)arg;
1100    break;
1101
1102  case CURLOPT_FTP_SKIP_PASV_IP:
1103    /*
1104     * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
1105     * bypass of the IP address in PASV responses.
1106     */
1107    data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
1108    break;
1109
1110  case CURLOPT_READDATA:
1111    /*
1112     * FILE pointer to read the file to be uploaded from. Or possibly
1113     * used as argument to the read callback.
1114     */
1115    data->set.in_set = va_arg(param, void *);
1116    break;
1117  case CURLOPT_INFILESIZE:
1118    /*
1119     * If known, this should inform curl about the file size of the
1120     * to-be-uploaded file.
1121     */
1122    arg = va_arg(param, long);
1123    if(arg < -1)
1124      return CURLE_BAD_FUNCTION_ARGUMENT;
1125    data->set.filesize = arg;
1126    break;
1127  case CURLOPT_INFILESIZE_LARGE:
1128    /*
1129     * If known, this should inform curl about the file size of the
1130     * to-be-uploaded file.
1131     */
1132    bigsize = va_arg(param, curl_off_t);
1133    if(bigsize < -1)
1134      return CURLE_BAD_FUNCTION_ARGUMENT;
1135    data->set.filesize = bigsize;
1136    break;
1137  case CURLOPT_LOW_SPEED_LIMIT:
1138    /*
1139     * The low speed limit that if transfers are below this for
1140     * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
1141     */
1142    arg = va_arg(param, long);
1143    if(arg < 0)
1144      return CURLE_BAD_FUNCTION_ARGUMENT;
1145    data->set.low_speed_limit = arg;
1146    break;
1147  case CURLOPT_MAX_SEND_SPEED_LARGE:
1148    /*
1149     * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
1150     * bytes per second the transfer is throttled..
1151     */
1152    bigsize = va_arg(param, curl_off_t);
1153    if(bigsize < 0)
1154      return CURLE_BAD_FUNCTION_ARGUMENT;
1155    data->set.max_send_speed = bigsize;
1156    break;
1157  case CURLOPT_MAX_RECV_SPEED_LARGE:
1158    /*
1159     * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
1160     * second the transfer is throttled..
1161     */
1162    bigsize = va_arg(param, curl_off_t);
1163    if(bigsize < 0)
1164      return CURLE_BAD_FUNCTION_ARGUMENT;
1165    data->set.max_recv_speed = bigsize;
1166    break;
1167  case CURLOPT_LOW_SPEED_TIME:
1168    /*
1169     * The low speed time that if transfers are below the set
1170     * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
1171     */
1172    arg = va_arg(param, long);
1173    if(arg < 0)
1174      return CURLE_BAD_FUNCTION_ARGUMENT;
1175    data->set.low_speed_time = arg;
1176    break;
1177  case CURLOPT_URL:
1178    /*
1179     * The URL to fetch.
1180     */
1181    if(data->change.url_alloc) {
1182      /* the already set URL is allocated, free it first! */
1183      Curl_safefree(data->change.url);
1184      data->change.url_alloc = FALSE;
1185    }
1186    result = Curl_setstropt(&data->set.str[STRING_SET_URL],
1187                            va_arg(param, char *));
1188    data->change.url = data->set.str[STRING_SET_URL];
1189    break;
1190  case CURLOPT_PORT:
1191    /*
1192     * The port number to use when getting the URL
1193     */
1194    arg = va_arg(param, long);
1195    if((arg < 0) || (arg > 65535))
1196      return CURLE_BAD_FUNCTION_ARGUMENT;
1197    data->set.use_port = arg;
1198    break;
1199  case CURLOPT_TIMEOUT:
1200    /*
1201     * The maximum time you allow curl to use for a single transfer
1202     * operation.
1203     */
1204    arg = va_arg(param, long);
1205    if((arg >= 0) && (arg <= (INT_MAX/1000)))
1206      data->set.timeout = arg * 1000;
1207    else
1208      return CURLE_BAD_FUNCTION_ARGUMENT;
1209    break;
1210
1211  case CURLOPT_TIMEOUT_MS:
1212    arg = va_arg(param, long);
1213    if(arg < 0)
1214      return CURLE_BAD_FUNCTION_ARGUMENT;
1215    data->set.timeout = arg;
1216    break;
1217
1218  case CURLOPT_CONNECTTIMEOUT:
1219    /*
1220     * The maximum time you allow curl to use to connect.
1221     */
1222    arg = va_arg(param, long);
1223    if((arg >= 0) && (arg <= (INT_MAX/1000)))
1224      data->set.connecttimeout = arg * 1000;
1225    else
1226      return CURLE_BAD_FUNCTION_ARGUMENT;
1227    break;
1228
1229  case CURLOPT_CONNECTTIMEOUT_MS:
1230    arg = va_arg(param, long);
1231    if(arg < 0)
1232      return CURLE_BAD_FUNCTION_ARGUMENT;
1233    data->set.connecttimeout = arg;
1234    break;
1235
1236  case CURLOPT_ACCEPTTIMEOUT_MS:
1237    /*
1238     * The maximum time you allow curl to wait for server connect
1239     */
1240    arg = va_arg(param, long);
1241    if(arg < 0)
1242      return CURLE_BAD_FUNCTION_ARGUMENT;
1243    data->set.accepttimeout = arg;
1244    break;
1245
1246  case CURLOPT_USERPWD:
1247    /*
1248     * user:password to use in the operation
1249     */
1250    result = setstropt_userpwd(va_arg(param, char *),
1251                               &data->set.str[STRING_USERNAME],
1252                               &data->set.str[STRING_PASSWORD]);
1253    break;
1254
1255  case CURLOPT_USERNAME:
1256    /*
1257     * authentication user name to use in the operation
1258     */
1259    result = Curl_setstropt(&data->set.str[STRING_USERNAME],
1260                            va_arg(param, char *));
1261    break;
1262
1263  case CURLOPT_PASSWORD:
1264    /*
1265     * authentication password to use in the operation
1266     */
1267    result = Curl_setstropt(&data->set.str[STRING_PASSWORD],
1268                            va_arg(param, char *));
1269    break;
1270
1271  case CURLOPT_LOGIN_OPTIONS:
1272    /*
1273     * authentication options to use in the operation
1274     */
1275    result = Curl_setstropt(&data->set.str[STRING_OPTIONS],
1276                            va_arg(param, char *));
1277    break;
1278
1279  case CURLOPT_XOAUTH2_BEARER:
1280    /*
1281     * OAuth 2.0 bearer token to use in the operation
1282     */
1283    result = Curl_setstropt(&data->set.str[STRING_BEARER],
1284                            va_arg(param, char *));
1285    break;
1286
1287  case CURLOPT_POSTQUOTE:
1288    /*
1289     * List of RAW FTP commands to use after a transfer
1290     */
1291    data->set.postquote = va_arg(param, struct curl_slist *);
1292    break;
1293  case CURLOPT_PREQUOTE:
1294    /*
1295     * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
1296     */
1297    data->set.prequote = va_arg(param, struct curl_slist *);
1298    break;
1299  case CURLOPT_QUOTE:
1300    /*
1301     * List of RAW FTP commands to use before a transfer
1302     */
1303    data->set.quote = va_arg(param, struct curl_slist *);
1304    break;
1305  case CURLOPT_RESOLVE:
1306    /*
1307     * List of NAME:[address] names to populate the DNS cache with
1308     * Prefix the NAME with dash (-) to _remove_ the name from the cache.
1309     *
1310     * Names added with this API will remain in the cache until explicitly
1311     * removed or the handle is cleaned up.
1312     *
1313     * This API can remove any name from the DNS cache, but only entries
1314     * that aren't actually in use right now will be pruned immediately.
1315     */
1316    data->set.resolve = va_arg(param, struct curl_slist *);
1317    data->change.resolve = data->set.resolve;
1318    break;
1319  case CURLOPT_PROGRESSFUNCTION:
1320    /*
1321     * Progress callback function
1322     */
1323    data->set.fprogress = va_arg(param, curl_progress_callback);
1324    if(data->set.fprogress)
1325      data->progress.callback = TRUE; /* no longer internal */
1326    else
1327      data->progress.callback = FALSE; /* NULL enforces internal */
1328    break;
1329
1330  case CURLOPT_XFERINFOFUNCTION:
1331    /*
1332     * Transfer info callback function
1333     */
1334    data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
1335    if(data->set.fxferinfo)
1336      data->progress.callback = TRUE; /* no longer internal */
1337    else
1338      data->progress.callback = FALSE; /* NULL enforces internal */
1339
1340    break;
1341
1342  case CURLOPT_PROGRESSDATA:
1343    /*
1344     * Custom client data to pass to the progress callback
1345     */
1346    data->set.progress_client = va_arg(param, void *);
1347    break;
1348
1349#ifndef CURL_DISABLE_PROXY
1350  case CURLOPT_PROXYUSERPWD:
1351    /*
1352     * user:password needed to use the proxy
1353     */
1354    result = setstropt_userpwd(va_arg(param, char *),
1355                               &data->set.str[STRING_PROXYUSERNAME],
1356                               &data->set.str[STRING_PROXYPASSWORD]);
1357    break;
1358  case CURLOPT_PROXYUSERNAME:
1359    /*
1360     * authentication user name to use in the operation
1361     */
1362    result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME],
1363                            va_arg(param, char *));
1364    break;
1365  case CURLOPT_PROXYPASSWORD:
1366    /*
1367     * authentication password to use in the operation
1368     */
1369    result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD],
1370                            va_arg(param, char *));
1371    break;
1372  case CURLOPT_NOPROXY:
1373    /*
1374     * proxy exception list
1375     */
1376    result = Curl_setstropt(&data->set.str[STRING_NOPROXY],
1377                            va_arg(param, char *));
1378    break;
1379#endif
1380
1381  case CURLOPT_RANGE:
1382    /*
1383     * What range of the file you want to transfer
1384     */
1385    result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
1386                            va_arg(param, char *));
1387    break;
1388  case CURLOPT_RESUME_FROM:
1389    /*
1390     * Resume transfer at the given file position
1391     */
1392    arg = va_arg(param, long);
1393    if(arg < -1)
1394      return CURLE_BAD_FUNCTION_ARGUMENT;
1395    data->set.set_resume_from = arg;
1396    break;
1397  case CURLOPT_RESUME_FROM_LARGE:
1398    /*
1399     * Resume transfer at the given file position
1400     */
1401    bigsize = va_arg(param, curl_off_t);
1402    if(bigsize < -1)
1403      return CURLE_BAD_FUNCTION_ARGUMENT;
1404    data->set.set_resume_from = bigsize;
1405    break;
1406  case CURLOPT_DEBUGFUNCTION:
1407    /*
1408     * stderr write callback.
1409     */
1410    data->set.fdebug = va_arg(param, curl_debug_callback);
1411    /*
1412     * if the callback provided is NULL, it'll use the default callback
1413     */
1414    break;
1415  case CURLOPT_DEBUGDATA:
1416    /*
1417     * Set to a void * that should receive all error writes. This
1418     * defaults to CURLOPT_STDERR for normal operations.
1419     */
1420    data->set.debugdata = va_arg(param, void *);
1421    break;
1422  case CURLOPT_STDERR:
1423    /*
1424     * Set to a FILE * that should receive all error writes. This
1425     * defaults to stderr for normal operations.
1426     */
1427    data->set.err = va_arg(param, FILE *);
1428    if(!data->set.err)
1429      data->set.err = stderr;
1430    break;
1431  case CURLOPT_HEADERFUNCTION:
1432    /*
1433     * Set header write callback
1434     */
1435    data->set.fwrite_header = va_arg(param, curl_write_callback);
1436    break;
1437  case CURLOPT_WRITEFUNCTION:
1438    /*
1439     * Set data write callback
1440     */
1441    data->set.fwrite_func = va_arg(param, curl_write_callback);
1442    if(!data->set.fwrite_func) {
1443      data->set.is_fwrite_set = 0;
1444      /* When set to NULL, reset to our internal default function */
1445      data->set.fwrite_func = (curl_write_callback)fwrite;
1446    }
1447    else
1448      data->set.is_fwrite_set = 1;
1449    break;
1450  case CURLOPT_READFUNCTION:
1451    /*
1452     * Read data callback
1453     */
1454    data->set.fread_func_set = va_arg(param, curl_read_callback);
1455    if(!data->set.fread_func_set) {
1456      data->set.is_fread_set = 0;
1457      /* When set to NULL, reset to our internal default function */
1458      data->set.fread_func_set = (curl_read_callback)fread;
1459    }
1460    else
1461      data->set.is_fread_set = 1;
1462    break;
1463  case CURLOPT_SEEKFUNCTION:
1464    /*
1465     * Seek callback. Might be NULL.
1466     */
1467    data->set.seek_func = va_arg(param, curl_seek_callback);
1468    break;
1469  case CURLOPT_SEEKDATA:
1470    /*
1471     * Seek control callback. Might be NULL.
1472     */
1473    data->set.seek_client = va_arg(param, void *);
1474    break;
1475  case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
1476    /*
1477     * "Convert from network encoding" callback
1478     */
1479    data->set.convfromnetwork = va_arg(param, curl_conv_callback);
1480    break;
1481  case CURLOPT_CONV_TO_NETWORK_FUNCTION:
1482    /*
1483     * "Convert to network encoding" callback
1484     */
1485    data->set.convtonetwork = va_arg(param, curl_conv_callback);
1486    break;
1487  case CURLOPT_CONV_FROM_UTF8_FUNCTION:
1488    /*
1489     * "Convert from UTF-8 encoding" callback
1490     */
1491    data->set.convfromutf8 = va_arg(param, curl_conv_callback);
1492    break;
1493  case CURLOPT_IOCTLFUNCTION:
1494    /*
1495     * I/O control callback. Might be NULL.
1496     */
1497    data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
1498    break;
1499  case CURLOPT_IOCTLDATA:
1500    /*
1501     * I/O control data pointer. Might be NULL.
1502     */
1503    data->set.ioctl_client = va_arg(param, void *);
1504    break;
1505  case CURLOPT_SSLCERT:
1506    /*
1507     * String that holds file name of the SSL certificate to use
1508     */
1509    result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
1510                            va_arg(param, char *));
1511    break;
1512  case CURLOPT_PROXY_SSLCERT:
1513    /*
1514     * String that holds file name of the SSL certificate to use for proxy
1515     */
1516    result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
1517                            va_arg(param, char *));
1518    break;
1519  case CURLOPT_SSLCERTTYPE:
1520    /*
1521     * String that holds file type of the SSL certificate to use
1522     */
1523    result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
1524                            va_arg(param, char *));
1525    break;
1526  case CURLOPT_PROXY_SSLCERTTYPE:
1527    /*
1528     * String that holds file type of the SSL certificate to use for proxy
1529     */
1530    result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
1531                            va_arg(param, char *));
1532    break;
1533  case CURLOPT_SSLKEY:
1534    /*
1535     * String that holds file name of the SSL key to use
1536     */
1537    result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
1538                            va_arg(param, char *));
1539    break;
1540  case CURLOPT_PROXY_SSLKEY:
1541    /*
1542     * String that holds file name of the SSL key to use for proxy
1543     */
1544    result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
1545                            va_arg(param, char *));
1546    break;
1547  case CURLOPT_SSLKEYTYPE:
1548    /*
1549     * String that holds file type of the SSL key to use
1550     */
1551    result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
1552                            va_arg(param, char *));
1553    break;
1554  case CURLOPT_PROXY_SSLKEYTYPE:
1555    /*
1556     * String that holds file type of the SSL key to use for proxy
1557     */
1558    result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
1559                            va_arg(param, char *));
1560    break;
1561  case CURLOPT_KEYPASSWD:
1562    /*
1563     * String that holds the SSL or SSH private key password.
1564     */
1565    result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
1566                            va_arg(param, char *));
1567    break;
1568  case CURLOPT_PROXY_KEYPASSWD:
1569    /*
1570     * String that holds the SSL private key password for proxy.
1571     */
1572    result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
1573                            va_arg(param, char *));
1574    break;
1575  case CURLOPT_SSLENGINE:
1576    /*
1577     * String that holds the SSL crypto engine.
1578     */
1579    argptr = va_arg(param, char *);
1580    if(argptr && argptr[0])
1581      result = Curl_ssl_set_engine(data, argptr);
1582    break;
1583
1584  case CURLOPT_SSLENGINE_DEFAULT:
1585    /*
1586     * flag to set engine as default.
1587     */
1588    result = Curl_ssl_set_engine_default(data);
1589    break;
1590  case CURLOPT_CRLF:
1591    /*
1592     * Kludgy option to enable CRLF conversions. Subject for removal.
1593     */
1594    data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
1595    break;
1596
1597  case CURLOPT_INTERFACE:
1598    /*
1599     * Set what interface or address/hostname to bind the socket to when
1600     * performing an operation and thus what from-IP your connection will use.
1601     */
1602    result = Curl_setstropt(&data->set.str[STRING_DEVICE],
1603                            va_arg(param, char *));
1604    break;
1605  case CURLOPT_LOCALPORT:
1606    /*
1607     * Set what local port to bind the socket to when performing an operation.
1608     */
1609    arg = va_arg(param, long);
1610    if((arg < 0) || (arg > 65535))
1611      return CURLE_BAD_FUNCTION_ARGUMENT;
1612    data->set.localport = curlx_sltous(arg);
1613    break;
1614  case CURLOPT_LOCALPORTRANGE:
1615    /*
1616     * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
1617     */
1618    arg = va_arg(param, long);
1619    if((arg < 0) || (arg > 65535))
1620      return CURLE_BAD_FUNCTION_ARGUMENT;
1621    data->set.localportrange = curlx_sltosi(arg);
1622    break;
1623  case CURLOPT_KRBLEVEL:
1624    /*
1625     * A string that defines the kerberos security level.
1626     */
1627    result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
1628                            va_arg(param, char *));
1629    data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
1630    break;
1631  case CURLOPT_GSSAPI_DELEGATION:
1632    /*
1633     * GSS-API credential delegation bitmask
1634     */
1635    arg = va_arg(param, long);
1636    if(arg < CURLGSSAPI_DELEGATION_NONE)
1637      return CURLE_BAD_FUNCTION_ARGUMENT;
1638    data->set.gssapi_delegation = arg;
1639    break;
1640  case CURLOPT_SSL_VERIFYPEER:
1641    /*
1642     * Enable peer SSL verifying.
1643     */
1644    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
1645      TRUE : FALSE;
1646
1647    /* Update the current connection ssl_config. */
1648    if(data->easy_conn) {
1649      data->easy_conn->ssl_config.verifypeer =
1650        data->set.ssl.primary.verifypeer;
1651    }
1652    break;
1653  case CURLOPT_PROXY_SSL_VERIFYPEER:
1654    /*
1655     * Enable peer SSL verifying for proxy.
1656     */
1657    data->set.proxy_ssl.primary.verifypeer =
1658      (0 != va_arg(param, long))?TRUE:FALSE;
1659
1660    /* Update the current connection proxy_ssl_config. */
1661    if(data->easy_conn) {
1662      data->easy_conn->proxy_ssl_config.verifypeer =
1663        data->set.proxy_ssl.primary.verifypeer;
1664    }
1665    break;
1666  case CURLOPT_SSL_VERIFYHOST:
1667    /*
1668     * Enable verification of the host name in the peer certificate
1669     */
1670    arg = va_arg(param, long);
1671
1672    /* Obviously people are not reading documentation and too many thought
1673       this argument took a boolean when it wasn't and misused it. We thus ban
1674       1 as a sensible input and we warn about its use. Then we only have the
1675       2 action internally stored as TRUE. */
1676
1677    if(1 == arg) {
1678      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
1679      return CURLE_BAD_FUNCTION_ARGUMENT;
1680    }
1681
1682    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
1683
1684    /* Update the current connection ssl_config. */
1685    if(data->easy_conn) {
1686      data->easy_conn->ssl_config.verifyhost =
1687        data->set.ssl.primary.verifyhost;
1688    }
1689    break;
1690  case CURLOPT_PROXY_SSL_VERIFYHOST:
1691    /*
1692     * Enable verification of the host name in the peer certificate for proxy
1693     */
1694    arg = va_arg(param, long);
1695
1696    /* Obviously people are not reading documentation and too many thought
1697       this argument took a boolean when it wasn't and misused it. We thus ban
1698       1 as a sensible input and we warn about its use. Then we only have the
1699       2 action internally stored as TRUE. */
1700
1701    if(1 == arg) {
1702      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
1703      return CURLE_BAD_FUNCTION_ARGUMENT;
1704    }
1705
1706    data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
1707
1708    /* Update the current connection proxy_ssl_config. */
1709    if(data->easy_conn) {
1710      data->easy_conn->proxy_ssl_config.verifyhost =
1711        data->set.proxy_ssl.primary.verifyhost;
1712    }
1713    break;
1714  case CURLOPT_SSL_VERIFYSTATUS:
1715    /*
1716     * Enable certificate status verifying.
1717     */
1718    if(!Curl_ssl_cert_status_request()) {
1719      result = CURLE_NOT_BUILT_IN;
1720      break;
1721    }
1722
1723    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
1724      TRUE : FALSE;
1725
1726    /* Update the current connection ssl_config. */
1727    if(data->easy_conn) {
1728      data->easy_conn->ssl_config.verifystatus =
1729        data->set.ssl.primary.verifystatus;
1730    }
1731    break;
1732  case CURLOPT_SSL_CTX_FUNCTION:
1733    /*
1734     * Set a SSL_CTX callback
1735     */
1736#ifdef USE_SSL
1737    if(Curl_ssl->have_ssl_ctx)
1738      data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
1739    else
1740#endif
1741      result = CURLE_NOT_BUILT_IN;
1742    break;
1743  case CURLOPT_SSL_CTX_DATA:
1744    /*
1745     * Set a SSL_CTX callback parameter pointer
1746     */
1747#ifdef USE_SSL
1748    if(Curl_ssl->have_ssl_ctx)
1749      data->set.ssl.fsslctxp = va_arg(param, void *);
1750    else
1751#endif
1752      result = CURLE_NOT_BUILT_IN;
1753    break;
1754  case CURLOPT_SSL_FALSESTART:
1755    /*
1756     * Enable TLS false start.
1757     */
1758    if(!Curl_ssl_false_start()) {
1759      result = CURLE_NOT_BUILT_IN;
1760      break;
1761    }
1762
1763    data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
1764    break;
1765  case CURLOPT_CERTINFO:
1766#ifdef USE_SSL
1767    if(Curl_ssl->have_certinfo)
1768      data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
1769    else
1770#endif
1771      result = CURLE_NOT_BUILT_IN;
1772        break;
1773  case CURLOPT_PINNEDPUBLICKEY:
1774    /*
1775     * Set pinned public key for SSL connection.
1776     * Specify file name of the public key in DER format.
1777     */
1778#ifdef USE_SSL
1779    if(Curl_ssl->have_pinnedpubkey)
1780      result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
1781                              va_arg(param, char *));
1782    else
1783#endif
1784      result = CURLE_NOT_BUILT_IN;
1785    break;
1786  case CURLOPT_PROXY_PINNEDPUBLICKEY:
1787    /*
1788     * Set pinned public key for SSL connection.
1789     * Specify file name of the public key in DER format.
1790     */
1791#ifdef USE_SSL
1792    if(Curl_ssl->have_pinnedpubkey)
1793      result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
1794                              va_arg(param, char *));
1795    else
1796#endif
1797      result = CURLE_NOT_BUILT_IN;
1798    break;
1799  case CURLOPT_CAINFO:
1800    /*
1801     * Set CA info for SSL connection. Specify file name of the CA certificate
1802     */
1803    result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
1804                            va_arg(param, char *));
1805    break;
1806  case CURLOPT_PROXY_CAINFO:
1807    /*
1808     * Set CA info SSL connection for proxy. Specify file name of the
1809     * CA certificate
1810     */
1811    result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
1812                            va_arg(param, char *));
1813    break;
1814  case CURLOPT_CAPATH:
1815    /*
1816     * Set CA path info for SSL connection. Specify directory name of the CA
1817     * certificates which have been prepared using openssl c_rehash utility.
1818     */
1819#ifdef USE_SSL
1820    if(Curl_ssl->have_ca_path)
1821      /* This does not work on windows. */
1822      result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
1823                              va_arg(param, char *));
1824    else
1825#endif
1826      result = CURLE_NOT_BUILT_IN;
1827    break;
1828  case CURLOPT_PROXY_CAPATH:
1829    /*
1830     * Set CA path info for SSL connection proxy. Specify directory name of the
1831     * CA certificates which have been prepared using openssl c_rehash utility.
1832     */
1833#ifdef USE_SSL
1834    if(Curl_ssl->have_ca_path)
1835      /* This does not work on windows. */
1836      result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
1837                              va_arg(param, char *));
1838    else
1839#endif
1840      result = CURLE_NOT_BUILT_IN;
1841    break;
1842  case CURLOPT_CRLFILE:
1843    /*
1844     * Set CRL file info for SSL connection. Specify file name of the CRL
1845     * to check certificates revocation
1846     */
1847    result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
1848                            va_arg(param, char *));
1849    break;
1850  case CURLOPT_PROXY_CRLFILE:
1851    /*
1852     * Set CRL file info for SSL connection for proxy. Specify file name of the
1853     * CRL to check certificates revocation
1854     */
1855    result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
1856                            va_arg(param, char *));
1857    break;
1858  case CURLOPT_ISSUERCERT:
1859    /*
1860     * Set Issuer certificate file
1861     * to check certificates issuer
1862     */
1863    result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
1864                            va_arg(param, char *));
1865    break;
1866  case CURLOPT_TELNETOPTIONS:
1867    /*
1868     * Set a linked list of telnet options
1869     */
1870    data->set.telnet_options = va_arg(param, struct curl_slist *);
1871    break;
1872
1873  case CURLOPT_BUFFERSIZE:
1874    /*
1875     * The application kindly asks for a differently sized receive buffer.
1876     * If it seems reasonable, we'll use it.
1877     */
1878    arg = va_arg(param, long);
1879
1880    if(arg > READBUFFER_MAX)
1881      arg = READBUFFER_MAX;
1882    else if(arg < 1)
1883      arg = READBUFFER_SIZE;
1884    else if(arg < READBUFFER_MIN)
1885      arg = READBUFFER_MIN;
1886
1887    /* Resize if new size */
1888    if(arg != data->set.buffer_size) {
1889      char *newbuff = realloc(data->state.buffer, arg + 1);
1890      if(!newbuff) {
1891        DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
1892        result = CURLE_OUT_OF_MEMORY;
1893      }
1894      else
1895        data->state.buffer = newbuff;
1896    }
1897    data->set.buffer_size = arg;
1898
1899    break;
1900
1901  case CURLOPT_NOSIGNAL:
1902    /*
1903     * The application asks not to set any signal() or alarm() handlers,
1904     * even when using a timeout.
1905     */
1906    data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
1907    break;
1908
1909  case CURLOPT_SHARE:
1910  {
1911    struct Curl_share *set;
1912    set = va_arg(param, struct Curl_share *);
1913
1914    /* disconnect from old share, if any */
1915    if(data->share) {
1916      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1917
1918      if(data->dns.hostcachetype == HCACHE_SHARED) {
1919        data->dns.hostcache = NULL;
1920        data->dns.hostcachetype = HCACHE_NONE;
1921      }
1922
1923#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
1924      if(data->share->cookies == data->cookies)
1925        data->cookies = NULL;
1926#endif
1927
1928      if(data->share->sslsession == data->state.session)
1929        data->state.session = NULL;
1930
1931      data->share->dirty--;
1932
1933      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1934      data->share = NULL;
1935    }
1936
1937    /* use new share if it set */
1938    data->share = set;
1939    if(data->share) {
1940
1941      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1942
1943      data->share->dirty++;
1944
1945      if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
1946        /* use shared host cache */
1947        data->dns.hostcache = &data->share->hostcache;
1948        data->dns.hostcachetype = HCACHE_SHARED;
1949      }
1950#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
1951      if(data->share->cookies) {
1952        /* use shared cookie list, first free own one if any */
1953        Curl_cookie_cleanup(data->cookies);
1954        /* enable cookies since we now use a share that uses cookies! */
1955        data->cookies = data->share->cookies;
1956      }
1957#endif   /* CURL_DISABLE_HTTP */
1958      if(data->share->sslsession) {
1959        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
1960        data->state.session = data->share->sslsession;
1961      }
1962      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1963
1964    }
1965    /* check for host cache not needed,
1966     * it will be done by curl_easy_perform */
1967  }
1968  break;
1969
1970  case CURLOPT_PRIVATE:
1971    /*
1972     * Set private data pointer.
1973     */
1974    data->set.private_data = va_arg(param, void *);
1975    break;
1976
1977  case CURLOPT_MAXFILESIZE:
1978    /*
1979     * Set the maximum size of a file to download.
1980     */
1981    arg = va_arg(param, long);
1982    if(arg < 0)
1983      return CURLE_BAD_FUNCTION_ARGUMENT;
1984    data->set.max_filesize = arg;
1985    break;
1986
1987#ifdef USE_SSL
1988  case CURLOPT_USE_SSL:
1989    /*
1990     * Make transfers attempt to use SSL/TLS.
1991     */
1992    arg = va_arg(param, long);
1993    if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL))
1994      return CURLE_BAD_FUNCTION_ARGUMENT;
1995    data->set.use_ssl = (curl_usessl)arg;
1996    break;
1997
1998  case CURLOPT_SSL_OPTIONS:
1999    arg = va_arg(param, long);
2000    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
2001    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2002    break;
2003
2004  case CURLOPT_PROXY_SSL_OPTIONS:
2005    arg = va_arg(param, long);
2006    data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
2007    data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2008    break;
2009
2010#endif
2011  case CURLOPT_FTPSSLAUTH:
2012    /*
2013     * Set a specific auth for FTP-SSL transfers.
2014     */
2015    arg = va_arg(param, long);
2016    if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
2017      return CURLE_BAD_FUNCTION_ARGUMENT;
2018    data->set.ftpsslauth = (curl_ftpauth)arg;
2019    break;
2020
2021  case CURLOPT_IPRESOLVE:
2022    arg = va_arg(param, long);
2023    if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
2024      return CURLE_BAD_FUNCTION_ARGUMENT;
2025    data->set.ipver = arg;
2026    break;
2027
2028  case CURLOPT_MAXFILESIZE_LARGE:
2029    /*
2030     * Set the maximum size of a file to download.
2031     */
2032    bigsize = va_arg(param, curl_off_t);
2033    if(bigsize < 0)
2034      return CURLE_BAD_FUNCTION_ARGUMENT;
2035    data->set.max_filesize = bigsize;
2036    break;
2037
2038  case CURLOPT_TCP_NODELAY:
2039    /*
2040     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
2041     * algorithm
2042     */
2043    data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
2044    break;
2045
2046  case CURLOPT_FTP_ACCOUNT:
2047    result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
2048                            va_arg(param, char *));
2049    break;
2050
2051  case CURLOPT_IGNORE_CONTENT_LENGTH:
2052    data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
2053    break;
2054
2055  case CURLOPT_CONNECT_ONLY:
2056    /*
2057     * No data transfer, set up connection and let application use the socket
2058     */
2059    data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
2060    break;
2061
2062  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2063    result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
2064                            va_arg(param, char *));
2065    break;
2066
2067  case CURLOPT_SOCKOPTFUNCTION:
2068    /*
2069     * socket callback function: called after socket() but before connect()
2070     */
2071    data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2072    break;
2073
2074  case CURLOPT_SOCKOPTDATA:
2075    /*
2076     * socket callback data pointer. Might be NULL.
2077     */
2078    data->set.sockopt_client = va_arg(param, void *);
2079    break;
2080
2081  case CURLOPT_OPENSOCKETFUNCTION:
2082    /*
2083     * open/create socket callback function: called instead of socket(),
2084     * before connect()
2085     */
2086    data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2087    break;
2088
2089  case CURLOPT_OPENSOCKETDATA:
2090    /*
2091     * socket callback data pointer. Might be NULL.
2092     */
2093    data->set.opensocket_client = va_arg(param, void *);
2094    break;
2095
2096  case CURLOPT_CLOSESOCKETFUNCTION:
2097    /*
2098     * close socket callback function: called instead of close()
2099     * when shutting down a connection
2100     */
2101    data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2102    break;
2103
2104  case CURLOPT_CLOSESOCKETDATA:
2105    /*
2106     * socket callback data pointer. Might be NULL.
2107     */
2108    data->set.closesocket_client = va_arg(param, void *);
2109    break;
2110
2111  case CURLOPT_SSL_SESSIONID_CACHE:
2112    data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
2113      TRUE : FALSE;
2114    data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
2115    break;
2116
2117#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
2118    /* we only include SSH options if explicitly built to support SSH */
2119  case CURLOPT_SSH_AUTH_TYPES:
2120    data->set.ssh_auth_types = va_arg(param, long);
2121    break;
2122
2123  case CURLOPT_SSH_PUBLIC_KEYFILE:
2124    /*
2125     * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2126     */
2127    result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
2128                            va_arg(param, char *));
2129    break;
2130
2131  case CURLOPT_SSH_PRIVATE_KEYFILE:
2132    /*
2133     * Use this file instead of the $HOME/.ssh/id_dsa file
2134     */
2135    result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
2136                            va_arg(param, char *));
2137    break;
2138  case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2139    /*
2140     * Option to allow for the MD5 of the host public key to be checked
2141     * for validation purposes.
2142     */
2143    result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
2144                            va_arg(param, char *));
2145    break;
2146#ifdef HAVE_LIBSSH2_KNOWNHOST_API
2147  case CURLOPT_SSH_KNOWNHOSTS:
2148    /*
2149     * Store the file name to read known hosts from.
2150     */
2151    result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
2152                            va_arg(param, char *));
2153    break;
2154
2155  case CURLOPT_SSH_KEYFUNCTION:
2156    /* setting to NULL is fine since the ssh.c functions themselves will
2157       then rever to use the internal default */
2158    data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2159    break;
2160
2161  case CURLOPT_SSH_KEYDATA:
2162    /*
2163     * Custom client data to pass to the SSH keyfunc callback
2164     */
2165    data->set.ssh_keyfunc_userp = va_arg(param, void *);
2166    break;
2167#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2168#endif /* USE_LIBSSH2 */
2169
2170  case CURLOPT_HTTP_TRANSFER_DECODING:
2171    /*
2172     * disable libcurl transfer encoding is used
2173     */
2174    data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2175    break;
2176
2177  case CURLOPT_HTTP_CONTENT_DECODING:
2178    /*
2179     * raw data passed to the application when content encoding is used
2180     */
2181    data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2182    break;
2183
2184  case CURLOPT_NEW_FILE_PERMS:
2185    /*
2186     * Uses these permissions instead of 0644
2187     */
2188    arg = va_arg(param, long);
2189    if((arg < 0) || (arg > 0777))
2190      return CURLE_BAD_FUNCTION_ARGUMENT;
2191    data->set.new_file_perms = arg;
2192    break;
2193
2194  case CURLOPT_NEW_DIRECTORY_PERMS:
2195    /*
2196     * Uses these permissions instead of 0755
2197     */
2198    arg = va_arg(param, long);
2199    if((arg < 0) || (arg > 0777))
2200      return CURLE_BAD_FUNCTION_ARGUMENT;
2201    data->set.new_directory_perms = arg;
2202    break;
2203
2204  case CURLOPT_ADDRESS_SCOPE:
2205    /*
2206     * We always get longs when passed plain numericals, but for this value we
2207     * know that an unsigned int will always hold the value so we blindly
2208     * typecast to this type
2209     */
2210    arg = va_arg(param, long);
2211    if((arg < 0) || (arg > 0xf))
2212      return CURLE_BAD_FUNCTION_ARGUMENT;
2213    data->set.scope_id = curlx_sltoui(arg);
2214    break;
2215
2216  case CURLOPT_PROTOCOLS:
2217    /* set the bitmask for the protocols that are allowed to be used for the
2218       transfer, which thus helps the app which takes URLs from users or other
2219       external inputs and want to restrict what protocol(s) to deal
2220       with. Defaults to CURLPROTO_ALL. */
2221    data->set.allowed_protocols = va_arg(param, long);
2222    break;
2223
2224  case CURLOPT_REDIR_PROTOCOLS:
2225    /* set the bitmask for the protocols that libcurl is allowed to follow to,
2226       as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
2227       to be set in both bitmasks to be allowed to get redirected to. Defaults
2228       to all protocols except FILE and SCP. */
2229    data->set.redir_protocols = va_arg(param, long);
2230    break;
2231
2232  case CURLOPT_DEFAULT_PROTOCOL:
2233    /* Set the protocol to use when the URL doesn't include any protocol */
2234    result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
2235                            va_arg(param, char *));
2236    break;
2237
2238  case CURLOPT_MAIL_FROM:
2239    /* Set the SMTP mail originator */
2240    result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
2241                            va_arg(param, char *));
2242    break;
2243
2244  case CURLOPT_MAIL_AUTH:
2245    /* Set the SMTP auth originator */
2246    result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
2247                            va_arg(param, char *));
2248    break;
2249
2250  case CURLOPT_MAIL_RCPT:
2251    /* Set the list of mail recipients */
2252    data->set.mail_rcpt = va_arg(param, struct curl_slist *);
2253    break;
2254
2255  case CURLOPT_SASL_IR:
2256    /* Enable/disable SASL initial response */
2257    data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
2258    break;
2259
2260  case CURLOPT_RTSP_REQUEST:
2261  {
2262    /*
2263     * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
2264     * Would this be better if the RTSPREQ_* were just moved into here?
2265     */
2266    long curl_rtspreq = va_arg(param, long);
2267    Curl_RtspReq rtspreq = RTSPREQ_NONE;
2268    switch(curl_rtspreq) {
2269    case CURL_RTSPREQ_OPTIONS:
2270      rtspreq = RTSPREQ_OPTIONS;
2271      break;
2272
2273    case CURL_RTSPREQ_DESCRIBE:
2274      rtspreq = RTSPREQ_DESCRIBE;
2275      break;
2276
2277    case CURL_RTSPREQ_ANNOUNCE:
2278      rtspreq = RTSPREQ_ANNOUNCE;
2279      break;
2280
2281    case CURL_RTSPREQ_SETUP:
2282      rtspreq = RTSPREQ_SETUP;
2283      break;
2284
2285    case CURL_RTSPREQ_PLAY:
2286      rtspreq = RTSPREQ_PLAY;
2287      break;
2288
2289    case CURL_RTSPREQ_PAUSE:
2290      rtspreq = RTSPREQ_PAUSE;
2291      break;
2292
2293    case CURL_RTSPREQ_TEARDOWN:
2294      rtspreq = RTSPREQ_TEARDOWN;
2295      break;
2296
2297    case CURL_RTSPREQ_GET_PARAMETER:
2298      rtspreq = RTSPREQ_GET_PARAMETER;
2299      break;
2300
2301    case CURL_RTSPREQ_SET_PARAMETER:
2302      rtspreq = RTSPREQ_SET_PARAMETER;
2303      break;
2304
2305    case CURL_RTSPREQ_RECORD:
2306      rtspreq = RTSPREQ_RECORD;
2307      break;
2308
2309    case CURL_RTSPREQ_RECEIVE:
2310      rtspreq = RTSPREQ_RECEIVE;
2311      break;
2312    default:
2313      rtspreq = RTSPREQ_NONE;
2314    }
2315
2316    data->set.rtspreq = rtspreq;
2317    break;
2318  }
2319
2320
2321  case CURLOPT_RTSP_SESSION_ID:
2322    /*
2323     * Set the RTSP Session ID manually. Useful if the application is
2324     * resuming a previously established RTSP session
2325     */
2326    result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
2327                            va_arg(param, char *));
2328    break;
2329
2330  case CURLOPT_RTSP_STREAM_URI:
2331    /*
2332     * Set the Stream URI for the RTSP request. Unless the request is
2333     * for generic server options, the application will need to set this.
2334     */
2335    result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
2336                            va_arg(param, char *));
2337    break;
2338
2339  case CURLOPT_RTSP_TRANSPORT:
2340    /*
2341     * The content of the Transport: header for the RTSP request
2342     */
2343    result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
2344                            va_arg(param, char *));
2345    break;
2346
2347  case CURLOPT_RTSP_CLIENT_CSEQ:
2348    /*
2349     * Set the CSEQ number to issue for the next RTSP request. Useful if the
2350     * application is resuming a previously broken connection. The CSEQ
2351     * will increment from this new number henceforth.
2352     */
2353    data->state.rtsp_next_client_CSeq = va_arg(param, long);
2354    break;
2355
2356  case CURLOPT_RTSP_SERVER_CSEQ:
2357    /* Same as the above, but for server-initiated requests */
2358    data->state.rtsp_next_client_CSeq = va_arg(param, long);
2359    break;
2360
2361  case CURLOPT_INTERLEAVEDATA:
2362    data->set.rtp_out = va_arg(param, void *);
2363    break;
2364  case CURLOPT_INTERLEAVEFUNCTION:
2365    /* Set the user defined RTP write function */
2366    data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2367    break;
2368
2369  case CURLOPT_WILDCARDMATCH:
2370    data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2371    break;
2372  case CURLOPT_CHUNK_BGN_FUNCTION:
2373    data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2374    break;
2375  case CURLOPT_CHUNK_END_FUNCTION:
2376    data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2377    break;
2378  case CURLOPT_FNMATCH_FUNCTION:
2379    data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2380    break;
2381  case CURLOPT_CHUNK_DATA:
2382    data->wildcard.customptr = va_arg(param, void *);
2383    break;
2384  case CURLOPT_FNMATCH_DATA:
2385    data->set.fnmatch_data = va_arg(param, void *);
2386    break;
2387#ifdef USE_TLS_SRP
2388  case CURLOPT_TLSAUTH_USERNAME:
2389    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
2390                            va_arg(param, char *));
2391    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
2392      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2393    break;
2394  case CURLOPT_PROXY_TLSAUTH_USERNAME:
2395    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
2396                            va_arg(param, char *));
2397    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
2398       !data->set.proxy_ssl.authtype)
2399      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2400    break;
2401  case CURLOPT_TLSAUTH_PASSWORD:
2402    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
2403                            va_arg(param, char *));
2404    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
2405      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2406    break;
2407  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2408    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
2409                            va_arg(param, char *));
2410    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
2411       !data->set.proxy_ssl.authtype)
2412      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2413    break;
2414  case CURLOPT_TLSAUTH_TYPE:
2415    argptr = va_arg(param, char *);
2416    if(!argptr ||
2417       strncasecompare(argptr, "SRP", strlen("SRP")))
2418      data->set.ssl.authtype = CURL_TLSAUTH_SRP;
2419    else
2420      data->set.ssl.authtype = CURL_TLSAUTH_NONE;
2421    break;
2422  case CURLOPT_PROXY_TLSAUTH_TYPE:
2423    argptr = va_arg(param, char *);
2424    if(!argptr ||
2425       strncasecompare(argptr, "SRP", strlen("SRP")))
2426      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
2427    else
2428      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
2429    break;
2430#endif
2431  case CURLOPT_DNS_SERVERS:
2432    result = Curl_set_dns_servers(data, va_arg(param, char *));
2433    break;
2434  case CURLOPT_DNS_INTERFACE:
2435    result = Curl_set_dns_interface(data, va_arg(param, char *));
2436    break;
2437  case CURLOPT_DNS_LOCAL_IP4:
2438    result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
2439    break;
2440  case CURLOPT_DNS_LOCAL_IP6:
2441    result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
2442    break;
2443
2444  case CURLOPT_TCP_KEEPALIVE:
2445    data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
2446    break;
2447  case CURLOPT_TCP_KEEPIDLE:
2448    arg = va_arg(param, long);
2449    if(arg < 0)
2450      return CURLE_BAD_FUNCTION_ARGUMENT;
2451    data->set.tcp_keepidle = arg;
2452    break;
2453  case CURLOPT_TCP_KEEPINTVL:
2454    arg = va_arg(param, long);
2455    if(arg < 0)
2456      return CURLE_BAD_FUNCTION_ARGUMENT;
2457    data->set.tcp_keepintvl = arg;
2458    break;
2459  case CURLOPT_TCP_FASTOPEN:
2460#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
2461   defined(TCP_FASTOPEN_CONNECT)
2462    data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
2463#else
2464    result = CURLE_NOT_BUILT_IN;
2465#endif
2466    break;
2467  case CURLOPT_SSL_ENABLE_NPN:
2468    data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2469    break;
2470  case CURLOPT_SSL_ENABLE_ALPN:
2471    data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2472    break;
2473
2474#ifdef USE_UNIX_SOCKETS
2475  case CURLOPT_UNIX_SOCKET_PATH:
2476    data->set.abstract_unix_socket = FALSE;
2477    result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2478                            va_arg(param, char *));
2479    break;
2480  case CURLOPT_ABSTRACT_UNIX_SOCKET:
2481    data->set.abstract_unix_socket = TRUE;
2482    result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2483                            va_arg(param, char *));
2484    break;
2485#endif
2486
2487  case CURLOPT_PATH_AS_IS:
2488    data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
2489    break;
2490  case CURLOPT_PIPEWAIT:
2491    data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
2492    break;
2493  case CURLOPT_STREAM_WEIGHT:
2494#ifndef USE_NGHTTP2
2495    return CURLE_NOT_BUILT_IN;
2496#else
2497    arg = va_arg(param, long);
2498    if((arg >= 1) && (arg <= 256))
2499      data->set.stream_weight = (int)arg;
2500    break;
2501#endif
2502  case CURLOPT_STREAM_DEPENDS:
2503  case CURLOPT_STREAM_DEPENDS_E:
2504  {
2505#ifndef USE_NGHTTP2
2506    return CURLE_NOT_BUILT_IN;
2507#else
2508    struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
2509    if(!dep || GOOD_EASY_HANDLE(dep)) {
2510      if(data->set.stream_depends_on) {
2511        Curl_http2_remove_child(data->set.stream_depends_on, data);
2512      }
2513      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
2514    }
2515    break;
2516#endif
2517  }
2518  case CURLOPT_CONNECT_TO:
2519    data->set.connect_to = va_arg(param, struct curl_slist *);
2520    break;
2521  case CURLOPT_SUPPRESS_CONNECT_HEADERS:
2522    data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
2523    break;
2524  case CURLOPT_SSH_COMPRESSION:
2525    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
2526    break;
2527  default:
2528    /* unknown tag and its companion, just ignore: */
2529    result = CURLE_UNKNOWN_OPTION;
2530    break;
2531  }
2532
2533  return result;
2534}
2535
2536/*
2537 * curl_easy_setopt() is the external interface for setting options on an
2538 * easy handle.
2539 */
2540
2541#undef curl_easy_setopt
2542CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
2543{
2544  va_list arg;
2545  CURLcode result;
2546
2547  if(!data)
2548    return CURLE_BAD_FUNCTION_ARGUMENT;
2549
2550  va_start(arg, tag);
2551
2552  result = Curl_vsetopt(data, tag, arg);
2553
2554  va_end(arg);
2555  return result;
2556}
2557