File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / setopt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>