Skip to content
Snippets Groups Projects
url.c 145 KiB
Newer Older
  • Learn to ignore specific revisions
  • /***************************************************************************
    
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ \| |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *                             \___|\___/|_| \_\_____|
     *
    
     * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
     * This software is licensed as described in the file COPYING, which
     * you should have received as part of this distribution. The terms
     * are also available at http://curl.haxx.se/docs/copyright.html.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     * copies of the Software, and permit persons to whom the Software is
    
     * furnished to do so, under the terms of the COPYING file.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * $Id$
    
     ***************************************************************************/
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    /* -- WIN32 approved -- */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <errno.h>
    
    
    #ifdef WIN32
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <time.h>
    #include <io.h>
    #else
    #ifdef HAVE_SYS_SOCKET_H
    #include <sys/socket.h>
    #endif
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <netinet/in.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <sys/time.h>
    
    Gisle Vanem's avatar
    Gisle Vanem committed
    #endif
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <netdb.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef HAVE_ARPA_INET_H
    #include <arpa/inet.h>
    #endif
    #ifdef HAVE_NET_IF_H
    #include <net/if.h>
    #endif
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <sys/ioctl.h>
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    #ifdef HAVE_SYS_PARAM_H
    #include <sys/param.h>
    #endif
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifdef VMS
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <in.h>
    #include <inet.h>
    #endif
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #ifndef HAVE_SOCKET
    #error "We can't compile without socket() support!"
    #endif
    
    Gisle Vanem's avatar
     
    Gisle Vanem committed
    #include <tld.h>
    
    #ifdef HAVE_IDN_FREE_H
    #include <idn-free.h>
    #else
    
    void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
                                  libidn 0.4.5's make install! */
    
    #ifndef HAVE_IDN_FREE
    /* if idn_free() was not found in this version of libidn, use plain free()
       instead */
    #define idn_free(x) (free)(x)
    #endif
    
    #endif  /* USE_LIBIDN */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "urldata.h"
    #include "netrc.h"
    
    #include "formdata.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "hostip.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "sendf.h"
    #include "progress.h"
    #include "cookie.h"
    
    #include "strequal.h"
    
    #include "strtok.h"
    
    #include "share.h"
    
    #include "http_digest.h"
    
    #include "select.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    /* And now for the protocols */
    #include "ftp.h"
    #include "dict.h"
    #include "telnet.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include "http.h"
    #include "file.h"
    
    #include "connect.h"
    
    #include "http_ntlm.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #define _MPRINTF_REPLACE /* use our functions only */
    #include <curl/mprintf.h>
    
    
    /* The last #include file should be: */
    #include "memdebug.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    /* Local static prototypes */
    
    static long ConnectionKillOne(struct SessionHandle *data);
    
    static void conn_free(struct connectdata *conn);
    
    static void signalPipeClose(struct curl_llist *pipeline);
    
    #ifdef CURL_DISABLE_VERBOSE_STRINGS
    #define verboseconnect(x)  do { } while (0)
    #endif
    
    
    static const struct Curl_handler * const protocols[] = {
    
    
    #ifndef CURL_DISABLE_HTTP
      &Curl_handler_http,
    #endif
    
    #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
      &Curl_handler_https,
    #endif
    
    #ifndef CURL_DISABLE_FTP
      &Curl_handler_ftp,
    #endif
    
    #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
      &Curl_handler_ftps,
    #endif
    
    #ifndef CURL_DISABLE_TELNET
      &Curl_handler_telnet,
    #endif
    
    #ifndef CURL_DISABLE_DICT
      &Curl_handler_dict,
    #endif
    
    #ifndef CURL_DISABLE_LDAP
      &Curl_handler_ldap,
    #endif
    
    
    #if !defined(CURL_DISABLE_LDAP) && defined(HAVE_LDAP_SSL)
    
      &Curl_handler_ldaps,
    #endif
    
    #ifndef CURL_DISABLE_FILE
      &Curl_handler_file,
    #endif
    
    #ifndef CURL_DISABLE_TFTP
      &Curl_handler_tftp,
    #endif
    
    #ifdef USE_LIBSSH2
      &Curl_handler_scp,
      &Curl_handler_sftp,
    #endif
    
      (struct Curl_handler *) NULL
    };
    
    /*
     * Dummy handler for undefined protocol schemes.
     */
    
    
    static const struct Curl_handler Curl_handler_dummy = {
    
      ZERO_NULL,                            /* setup_connection */
      ZERO_NULL,                            /* do_it */
      ZERO_NULL,                            /* done */
      ZERO_NULL,                            /* do_more */
      ZERO_NULL,                            /* connect_it */
      ZERO_NULL,                            /* connecting */
      ZERO_NULL,                            /* doing */
      ZERO_NULL,                            /* proto_getsock */
      ZERO_NULL,                            /* doing_getsock */
      ZERO_NULL,                            /* disconnect */
    
    static void close_connections(struct SessionHandle *data)
    {
      /* Loop through all open connections and kill them one by one */
    
    Yang Tse's avatar
    Yang Tse committed
      long i;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      do
    
    Yang Tse's avatar
    Yang Tse committed
        i = ConnectionKillOne(data);
      while(i != -1L);
    
    void Curl_freeset(struct SessionHandle * data)
    {
      /* Free all dynamic strings stored in the data->set substructure. */
      enum dupstring i;
    
      for(i=(enum dupstring)0; i < STRING_LAST; i++)
    
    static CURLcode setstropt(char **charp, char * s)
    
    {
      /* Release the previous storage at `charp' and replace by a dynamic storage
         copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
    
    
    static CURLcode setstropt_userpwd(char *option, char **user_storage,
                                      char **pwd_storage)
    {
      char* separator;
      CURLcode result = CURLE_OK;
    
    
      separator = strchr(option, ':');
      if (separator != NULL) {
    
        /* store username part of option */
        char * p;
        size_t username_len = (size_t)(separator-option);
        p = malloc(username_len+1);
        if(!p)
          result = CURLE_OUT_OF_MEMORY;
        else {
          memcpy(p, option, username_len);
          p[username_len] = '\0';
          Curl_safefree(*user_storage);
          *user_storage = p;
        }
    
        /* store password part of option */
        if (result == CURLE_OK) {
          result = setstropt(pwd_storage, separator+1);
        }
      }
      else {
        result = setstropt(user_storage, option);
      }
      return result;
    }
    
    
    CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src)
    {
    
    Dan Fandrich's avatar
    Dan Fandrich committed
      CURLcode r = CURLE_OK;
    
      enum dupstring i;
    
      /* Copy src->set into dst->set first, then deal with the strings
         afterwards */
      dst->set = src->set;
    
      /* clear all string pointers first */
      memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
    
      /* duplicate all strings */
    
      for(i=(enum dupstring)0; i< STRING_LAST; i++) {
    
        r = setstropt(&dst->set.str[i], src->set.str[i]);
    
          break;
      }
    
      /* If a failure occurred, freeing has to be performed externally. */
      return r;
    }
    
    
    #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
    static void flush_cookies(struct SessionHandle *data, int cleanup)
    {
      if(data->set.str[STRING_COOKIEJAR]) {
        if(data->change.cookielist) {
          /* If there is a list of cookie files to read, do it first so that
    
             we have all the told files read before we write the new jar.
             Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
    
        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    
    
        /* if we have a destination file for all the cookies to get dumped to */
    
        if(Curl_cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
          infof(data, "WARNING: failed to save cookies in %s\n",
                data->set.str[STRING_COOKIEJAR]);
      }
      else {
        if(cleanup && data->change.cookielist)
          /* since nothing is written, we can just free the list of cookie file
             names */
          curl_slist_free_all(data->change.cookielist); /* clean up list */
    
        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    
      }
    
      if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
        Curl_cookie_cleanup(data->cookies);
      }
      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    }
    #endif
    
    
    /*
     * This is the internal function curl_easy_cleanup() calls. This should
     * cleanup and free all resources associated with this sessionhandle.
     *
     * NOTE: if we ever add something that attempts to write to a socket or
     * similar here, we must ignore SIGPIPE first. It is currently only done
     * when curl_easy_perform() is invoked.
     */
    
    
    CURLcode Curl_close(struct SessionHandle *data)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
    
    #ifdef CURLDEBUG
      /* only for debugging, scan through all connections and see if there's a
         pipe reference still identifying this handle */
    
      if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) {
        struct conncache *c = data->state.connc;
    
        struct curl_llist_element *curr;
        struct connectdata *connptr;
    
        for(i=0; i< c->num; i++) {
          connptr = c->connects[i];
          if(!connptr)
            continue;
    
    
          pipeline = connptr->send_pipe;
          if(pipeline) {
            for (curr = pipeline->head; curr; curr=curr->next) {
    
              if(data == (struct SessionHandle *) curr->ptr) {
                fprintf(stderr,
                        "MAJOR problem we %p are still in send pipe for %p done %d\n",
    
                        data, connptr, (int)connptr->bits.done);
    
          pipeline = connptr->recv_pipe;
          if(pipeline) {
            for (curr = pipeline->head; curr; curr=curr->next) {
    
              if(data == (struct SessionHandle *) curr->ptr) {
                fprintf(stderr,
                        "MAJOR problem we %p are still in recv pipe for %p done %d\n",
    
                        data, connptr, (int)connptr->bits.done);
    
          pipeline = connptr->pend_pipe;
          if(pipeline) {
            for (curr = pipeline->head; curr; curr=curr->next) {
              if(data == (struct SessionHandle *) curr->ptr) {
                fprintf(stderr,
                        "MAJOR problem we %p are still in pend pipe for %p done %d\n",
    
                        data, connptr, (int)connptr->bits.done);
    
      if(m)
        /* This handle is still part of a multi handle, take care of this first
           and detach this handle from there. */
    
      data->magic = 0; /* force a clear AFTER the possibly enforced removal from
                          the multi handle, since that function uses the magic
                          field! */
    
    
        if(data->state.connc->type == CONNCACHE_PRIVATE) {
          /* close all connections still alive that are in the private connection
             cache, as we no longer have the pointer left to the shared one. */
          close_connections(data);
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
          /* free the connection cache if allocated privately */
          Curl_rm_connc(data->state.connc);
    
        /* marked to be used by a pending connection so we can't kill this handle
           just yet */
        data->state.closed = TRUE;
    
      if(data->dns.hostcachetype == HCACHE_PRIVATE)
        Curl_hash_destroy(data->dns.hostcache);
    
      if(data->state.rangestringalloc)
        free(data->state.range);
    
      Curl_safefree(data->state.pathbuffer);
      Curl_safefree(data->state.proto.generic);
    
      /* Close down all open SSL info and sessions */
    
      if(data->change.referer_alloc)
        free(data->change.referer);
    
      if(data->change.url_alloc)
        free(data->change.url);
    
      Curl_safefree(data->state.headerbuff);
    
    #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
    
      Curl_safefree(data->info.contenttype);
    
      Curl_safefree(data->info.wouldredirect);
    
      /* this destroys the channel and we cannot use it anymore after this */
      ares_destroy(data->state.areschannel);
    
    
    #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
      /* close iconv conversion descriptors */
    
         iconv_close(data->inbound_cd);
      }
    
         iconv_close(data->outbound_cd);
      }
    
         iconv_close(data->utf8_cd);
      }
    #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
    
    
      /* No longer a dirty share, if it exists */
    
        Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
    
        Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
      }
    
      return CURLE_OK;
    }
    
    /* create a connection cache of a private or multi type */
    
    struct conncache *Curl_mk_connc(int type,
    
    Yang Tse's avatar
    Yang Tse committed
                                    long amount) /* set -1 to use default */
    
    {
      /* It is subject for debate how many default connections to have for a multi
         connection cache... */
    
    Yang Tse's avatar
    Yang Tse committed
    
    
    Yang Tse's avatar
    Yang Tse committed
      long default_amount;
    
    
    Yang Tse's avatar
    Yang Tse committed
        default_amount = (amount < 0) ? 5 : amount;
      }
      else {
        default_amount = (amount < 0) ? 10 : amount;
      }
    
    
      c= calloc(sizeof(struct conncache), 1);
      if(!c)
        return NULL;
    
    
      if((size_t)(default_amount) > ((size_t)-1) / sizeof(struct connectdata *))
    
    Yang Tse's avatar
    Yang Tse committed
        default_amount = ((size_t)-1) / sizeof(struct connectdata *);
    
      c->connects = calloc(sizeof(struct connectdata *), (size_t)default_amount);
    
      if(!c->connects) {
        free(c);
        return NULL;
      }
    
      c->num = default_amount;
    
      return c;
    }
    
    
    /* Change number of entries of a connection cache */
    CURLcode Curl_ch_connc(struct SessionHandle *data,
                           struct conncache *c,
                           long newamount)
    {
    
    Yang Tse's avatar
    Yang Tse committed
      long i;
    
      if(newamount < 1)
        newamount = 1; /* we better have at least one entry */
    
      if(!c) {
        /* we get a NULL pointer passed in as connection cache, which means that
           there is no cache created for this SessionHandle just yet, we create a
           brand new with the requested size.
        */
        data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, newamount);
        if(!data->state.connc)
          return CURLE_OUT_OF_MEMORY;
        return CURLE_OK;
      }
    
    
      if(newamount < c->num) {
        /* Since this number is *decreased* from the existing number, we must
           close the possibly open connections that live on the indexes that
           are being removed!
    
           NOTE: for conncache_multi cases we must make sure that we only
           close handles not in use.
        */
        for(i=newamount; i< c->num; i++)
          Curl_disconnect(c->connects[i]);
    
        /* If the most recent connection is no longer valid, mark it
           invalid. */
        if(data->state.lastconnect <= newamount)
          data->state.lastconnect = -1;
      }
      if(newamount > 0) {
    
        newptr = realloc(c->connects, sizeof(struct connectdata *) * newamount);
    
        if(!newptr)
          /* we closed a few connections in vain, but so what? */
          return CURLE_OUT_OF_MEMORY;
    
        /* nullify the newly added pointers */
        for(i=c->num; i<newamount; i++)
          newptr[i] = NULL;
    
        c->connects = newptr;
        c->num = newamount;
      }
      /* we no longer support less than 1 as size for the connection cache, and
         I'm not sure it ever worked to set it to zero */
      return CURLE_OK;
    }
    
    
    /* Free a connection cache. This is called from Curl_close() and
       curl_multi_cleanup(). */
    void Curl_rm_connc(struct conncache *c)
    {
      if(c->connects) {
    
        for(i = 0; i < c->num; ++i)
          conn_free(c->connects[i]);
    
        free(c->connects);
      }
    
      free(c);
    }
    
    
    /**
     * Curl_open()
     *
     * @param curl is a pointer to a sessionhandle pointer that gets set by this
     * function.
     * @return CURLcode
     */
    
    
    CURLcode Curl_open(struct SessionHandle **curl)
    
    #ifdef USE_ARES
      int status;
    #endif
    
      /* Very simple start-up: alloc the struct, init it with zeroes and return */
    
      data = calloc(1, sizeof(struct SessionHandle));
    
        DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
    
      if((status = ares_init(&data->state.areschannel)) != ARES_SUCCESS) {
    
        DEBUGF(fprintf(stderr, "Error: ares_init failed\n"));
    
          return CURLE_OUT_OF_MEMORY;
        else
          return CURLE_FAILED_INIT;
    
      }
      /* make sure that all other returns from this function should destroy the
         ares channel before returning error! */
    #endif
    
    
      /* We do some initial setup here, all those fields that can't be just 0 */
    
    
      data->state.headerbuff = malloc(HEADERSIZE);
    
      if(!data->state.headerbuff) {
        DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
    
      else {
        data->state.headersize=HEADERSIZE;
    
        data->set.out = stdout; /* default output to stdout */
        data->set.in  = stdin;  /* default input from stdin */
        data->set.err  = stderr;  /* default stderr to stderr */
    
        /* use fwrite as default function to store output */
    
        data->set.fwrite_func = (curl_write_callback)fwrite;
    
        /* use fread as default function to read input */
    
        data->set.fread_func = (curl_read_callback)fread;
    
        /* don't use a seek function by default */
        data->set.seek_func = ZERO_NULL;
        data->set.seek_client = ZERO_NULL;
    
    
        /* conversion callbacks for non-ASCII hosts */
    
        data->set.convfromnetwork = ZERO_NULL;
        data->set.convtonetwork   = ZERO_NULL;
        data->set.convfromutf8    = ZERO_NULL;
    
    
    #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
        /* conversion descriptors for iconv calls */
        data->outbound_cd = (iconv_t)-1;
        data->inbound_cd  = (iconv_t)-1;
        data->utf8_cd     = (iconv_t)-1;
    #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
    
    
        data->set.infilesize = -1; /* we don't know any size */
    
        data->set.maxredirs = -1; /* allow any amount by default */
    
        data->state.current_speed = -1; /* init to negative == impossible */
    
        data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
        data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
        data->set.ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
    
        data->set.ftp_filemethod = FTPFILE_MULTICWD;
    
        data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
    
        /* make libcurl quiet by default: */
        data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
        data->progress.flags |= PGRS_HIDE;
    
        /* Set the default size of the SSL session ID cache */
        data->set.ssl.numsessions = 5;
    
        data->set.proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
    
        data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
        data->set.httpauth = CURLAUTH_BASIC;  /* defaults to basic */
        data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
    
        /* This no longer creates a connection cache here. It is instead made on
           the first call to curl_easy_perform() or when the handle is added to a
           multi stack. */
    
        data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                            type */
    
        data->set.new_file_perms = 0644;    /* Default permissions */
        data->set.new_directory_perms = 0755; /* Default permissions */
    
        /* most recent connection is not yet defined */
        data->state.lastconnect = -1;
    
    
        /*
         * libcurl 7.10 introduced SSL verification *by default*! This needs to be
         * switched off unless wanted.
         */
        data->set.ssl.verifypeer = TRUE;
        data->set.ssl.verifyhost = 2;
    
        data->set.ssl.sessionid = TRUE; /* session ID caching enabled by default */
    
        /* This is our preferred CA cert bundle/path since install time */
    #if defined(CURL_CA_BUNDLE)
    
        res = setstropt(&data->set.str[STRING_SSL_CAFILE],
    
    #elif defined(CURL_CA_PATH)
        res = setstropt(&data->set.str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH);
    
      if(res) {
        ares_destroy(data->state.areschannel);
        if(data->state.headerbuff)
          free(data->state.headerbuff);
    
    CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
                         va_list param)
    
    #ifndef CURL_DISABLE_HTTP
      curl_off_t bigsize;
    #endif
    
        data->set.dns_cache_timeout = va_arg(param, long);
    
      case CURLOPT_DNS_USE_GLOBAL_CACHE:
    
      {
        /* remember we want this enabled */
        long use_cache = va_arg(param, long);
        data->set.global_dns_cache = (bool)(0 != use_cache);
      }
      break;
    
      case CURLOPT_SSL_CIPHER_LIST:
        /* set a list of cipher we want to use in the SSL connection */
    
        result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
    
                           va_arg(param, char *));
    
      case CURLOPT_RANDOM_FILE:
        /*
         * This is the path name to a file that contains random data to seed
         * the random SSL stuff with. The file is only used for reading.
         */
    
        result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
    
                           va_arg(param, char *));
    
        break;
      case CURLOPT_EGDSOCKET:
        /*
         * The Entropy Gathering Daemon socket pathname
         */
    
        result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
    
                           va_arg(param, char *));
    
      case CURLOPT_MAXCONNECTS:
        /*
         * Set the absolute number of maximum simultaneous alive connection that
         * libcurl is allowed to have.
         */
    
        result = Curl_ch_connc(data, data->state.connc, va_arg(param, long));
    
        break;
      case CURLOPT_FORBID_REUSE:
        /*
         * When this transfer is done, it must not be left to be reused by a
         * subsequent transfer but shall be closed immediately.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.reuse_forbid = (bool)(0 != va_arg(param, long));
    
        break;
      case CURLOPT_FRESH_CONNECT:
        /*
         * This transfer shall not use a previously cached connection but
         * should be made with a fresh new connect!
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.reuse_fresh = (bool)(0 != va_arg(param, long));
    
      case CURLOPT_VERBOSE:
    
        /*
         * Verbose means infof() calls that give a lot of information about
         * the connection and transfer procedures as well as internal choices.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.verbose = (bool)(0 != va_arg(param, long));
    
        break;
      case CURLOPT_HEADER:
    
        /*
         * Set to include the header in the general data output stream.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.include_header = (bool)(0 != va_arg(param, long));
    
        break;
      case CURLOPT_NOPROGRESS:
    
        /*
         * Shut off the internal supported progress meter
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.hide_progress = (bool)(0 != va_arg(param, long));
    
          data->progress.flags |= PGRS_HIDE;
    
        else
          data->progress.flags &= ~PGRS_HIDE;
    
        break;
      case CURLOPT_NOBODY:
    
        /*
         * Do not include the body part in the output data stream.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.opt_no_body = (bool)(0 != va_arg(param, long));
    
    
        /* in HTTP lingo, no body means using the HEAD request and if unset there
           really is no perfect method that is the "opposite" of HEAD but in
           reality most people probably think GET then. The important thing is
           that we can't let it remain HEAD if the opt_no_body is set FALSE since
           then we'll behave wrong when getting HTTP. */
        data->set.httpreq = data->set.opt_no_body?HTTPREQ_HEAD:HTTPREQ_GET;
    
        break;
      case CURLOPT_FAILONERROR:
    
        /*
         * Don't output the >=300 error code HTML-page, but instead only
         * return error.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.http_fail_on_error = (bool)(0 != va_arg(param, long));
    
        break;
      case CURLOPT_UPLOAD:
    
         * We want to sent data to the remote host. If this is HTTP, that equals
         * using the PUT request.
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.upload = (bool)(0 != va_arg(param, long));
    
          /* If this is HTTP, PUT is what's needed to "upload" */
    
        else
          /* In HTTP, the opposite of upload is either GET or a HEAD */
          data->set.httpreq = data->set.opt_no_body?HTTPREQ_HEAD:HTTPREQ_GET;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      case CURLOPT_FILETIME:
    
        /*
         * Try to get the file time of the remote document. The time will
         * later (possibly) become available using curl_easy_getinfo().
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.get_filetime = (bool)(0 != va_arg(param, long));
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        break;
    
      case CURLOPT_FTP_CREATE_MISSING_DIRS:
        /*
         * An FTP option that modifies an upload to create missing directories on
         * the server.
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.ftp_create_missing_dirs = (bool)(0 != va_arg(param, long));
    
      case CURLOPT_FTP_RESPONSE_TIMEOUT:
        /*
    
         * An FTP option that specifies how quickly an FTP response must be
    
         * obtained before it is considered failure.
         */
    
        data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
    
         * An option that changes the command to one that asks for a list
    
         * only, no file info details.
         */
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.ftp_list_only = (bool)(0 != va_arg(param, long));
    
         * We want to upload and append to an existing file.
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.ftp_append = (bool)(0 != va_arg(param, long));
    
      case CURLOPT_FTP_FILEMETHOD:
        /*
         * How do access files over FTP.
         */
    
        data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
    
      case CURLOPT_NETRC:
    
        /*
         * Parse the $HOME/.netrc file
         */
    
        data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
    
      case CURLOPT_NETRC_FILE:
        /*
         * Use this file instead of the $HOME/.netrc file
         */
    
        result = setstropt(&data->set.str[STRING_NETRC_FILE],
    
                           va_arg(param, char *));
    
        break;
    
         * This option was previously named 'FTPASCII'. Renamed to work with
         * more protocols than merely FTP.
         *
         * Transfer using ASCII (instead of BINARY).
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.prefer_ascii = (bool)(0 != va_arg(param, long));
    
        break;
      case CURLOPT_TIMECONDITION:
    
        /*
         * Set HTTP time condition. This must be one of the defines in the
         * curl/curl.h header file.
         */
    
        data->set.timecondition = (curl_TimeCond)va_arg(param, long);
    
      case CURLOPT_TIMEVALUE:
    
        /*
         * This is the value to compare with the remote document with the
         * method set with CURLOPT_TIMECONDITION
         */
    
        data->set.timevalue = (time_t)va_arg(param, long);
    
      case CURLOPT_SSLVERSION:
    
        /*
         * Set explicit SSL version to try to connect with, as some SSL
         * implementations are lame.
         */
    
        data->set.ssl.version = va_arg(param, long);
    
         * Switch on automatic referer that gets set if curl follows locations.
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.http_auto_referer = (bool)(0 != va_arg(param, long));
    
         * String to use at the value of Accept-Encoding header.
         *
         * If the encoding is set to "" we use an Accept-Encoding header that
         * encompasses all the encodings we support.
         * If the encoding is set to NULL we don't send an Accept-Encoding header
         * and ignore an received Content-Encoding header.
         *
    
        result = setstropt(&data->set.str[STRING_ENCODING],
    
                           (argptr && !*argptr)?
                           (char *) ALL_CONTENT_ENCODINGS: argptr);
    
         * Follow Location: header hints on a HTTP-server.
    
    Yang Tse's avatar
    Yang Tse committed
        data->set.http_follow_location = (bool)(0 != va_arg(param, long));
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
        break;
    
         * Send authentication (user+password) when following locations, even when
         * hostname changed.