Newer
Older
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
***************************************************************************/
#include "setup.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#endif
#ifdef HAVE_SYS_STAT_H
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
Daniel Stenberg
committed
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
#endif
#ifdef USE_LIBIDN
#include <idna.h>
#include <stringprep.h>
#ifdef HAVE_IDN_FREE_H
#include <idn-free.h>
#else
Daniel Stenberg
committed
void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
libidn 0.4.5's make install! */
#endif
#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
#include "urldata.h"
#include "netrc.h"
#include "formdata.h"
#include "base64.h"
Daniel Stenberg
committed
#include "sslgen.h"
Daniel Stenberg
committed
#include "transfer.h"
#include "sendf.h"
#include "progress.h"
#include "cookie.h"
#include "strerror.h"
#include "escape.h"
Daniel Stenberg
committed
#include "content_encoding.h"
#include "http_negotiate.h"
Daniel Stenberg
committed
#include "multiif.h"
/* And now for the protocols */
#include "ftp.h"
#include "dict.h"
#include "telnet.h"
#include "tftp.h"
#include "http.h"
#include "file.h"
#include "ldap.h"
Daniel Stenberg
committed
#include "url.h"
#include "inet_ntop.h"
Daniel Stenberg
committed
#include <ca-bundle.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
Daniel Stenberg
committed
#include "krb4.h"
#include "memory.h"
Daniel Stenberg
committed
/* The last #include file should be: */
#include "memdebug.h"
/* Local static prototypes */
static long ConnectionKillOne(struct SessionHandle *data);
Daniel Stenberg
committed
static bool ConnectionExists(struct SessionHandle *data,
struct connectdata *needle,
struct connectdata **usethis);
static long ConnectionStore(struct SessionHandle *data,
struct connectdata *conn);
Daniel Stenberg
committed
#ifndef USE_ARES
/* not for Win32, unless it is cygwin
not for ares builds */
#if !defined(WIN32) || defined(__CYGWIN__)
Daniel Stenberg
committed
#ifndef RETSIGTYPE
#define RETSIGTYPE void
#endif
#ifdef HAVE_SIGSETJMP
#endif
{
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
Daniel Stenberg
committed
#ifdef HAVE_SIGSETJMP
siglongjmp(curl_jmpenv, 1);
#endif
Daniel Stenberg
committed
#endif /* USE_ARES */
void Curl_safefree(void *ptr)
{
if(ptr)
free(ptr);
}
/*
* 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.
*/
Daniel Stenberg
committed
CURLcode Curl_close(struct SessionHandle *data)
Daniel Stenberg
committed
if(data->multi) {
/* this handle is still part of a multi handle, take care of this first */
Curl_multi_rmeasy(data->multi, data);
}
/* Loop through all open connections and kill them one by one */
Daniel Stenberg
committed
while(-1 != ConnectionKillOne(data))
; /* empty loop */
Daniel Stenberg
committed
if ( ! (data->share && data->share->hostcache) ) {
if ( !Curl_global_host_cache_use(data)) {
Daniel Stenberg
committed
Curl_hash_destroy(data->dns.hostcache);
Daniel Stenberg
committed
}
}
/* Close down all open SSL info and sessions */
Daniel Stenberg
committed
Curl_ssl_close_all(data);
Daniel Stenberg
committed
Curl_safefree(data->state.first_host);
Curl_safefree(data->state.scratch);
Daniel Stenberg
committed
if(data->change.proxy_alloc)
free(data->change.proxy);
Daniel Stenberg
committed
if(data->change.referer_alloc)
free(data->change.referer);
Daniel Stenberg
committed
if(data->change.url_alloc)
free(data->change.url);
Curl_safefree(data->state.headerbuff);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Daniel Stenberg
committed
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
if(data->set.cookiejar) {
Daniel Stenberg
committed
/* 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(data);
Daniel Stenberg
committed
/* we have a "destination" for all the cookies to get dumped to */
if(Curl_cookie_output(data->cookies, data->set.cookiejar))
Daniel Stenberg
committed
infof(data, "WARNING: failed to save cookies in %s\n",
data->set.cookiejar);
Daniel Stenberg
committed
else {
if(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 */
}
Daniel Stenberg
committed
if( !data->share || (data->cookies != data->share->cookies) ) {
Curl_cookie_cleanup(data->cookies);
}
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_digest_cleanup(data);
#endif
/* free the connection cache */
Daniel Stenberg
committed
free(data->state.connects);
Curl_safefree(data->info.contenttype);
Daniel Stenberg
committed
#ifdef USE_ARES
/* this destroys the channel and we cannot use it anymore after this */
ares_destroy(data->state.areschannel);
#endif
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
/* close iconv conversion descriptors */
if (data->inbound_cd != (iconv_t)-1) {
iconv_close(data->inbound_cd);
}
if (data->outbound_cd != (iconv_t)-1) {
iconv_close(data->outbound_cd);
}
if (data->utf8_cd != (iconv_t)-1) {
iconv_close(data->utf8_cd);
}
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
Daniel Stenberg
committed
/* No longer a dirty share, if it exists */
if (data->share)
data->share->dirty--;
Daniel Stenberg
committed
/**
* Curl_open()
*
* @param curl is a pointer to a sessionhandle pointer that gets set by this
* function.
* @return CURLcode
*/
Daniel Stenberg
committed
CURLcode Curl_open(struct SessionHandle **curl)
CURLcode res = CURLE_OK;
Daniel Stenberg
committed
struct SessionHandle *data;
/* Very simple start-up: alloc the struct, init it with zeroes and return */
Daniel Stenberg
committed
data = (struct SessionHandle *)calloc(1, sizeof(struct SessionHandle));
Daniel Stenberg
committed
if(!data)
/* this is a very serious error */
return CURLE_OUT_OF_MEMORY;
Daniel Stenberg
committed
#ifdef USE_ARES
if(ARES_SUCCESS != ares_init(&data->state.areschannel)) {
free(data);
return CURLE_FAILED_INIT;
}
/* make sure that all other returns from this function should destroy the
ares channel before returning error! */
#endif
Daniel Stenberg
committed
/* We do some initial setup here, all those fields that can't be just 0 */
data->state.headerbuff=(char*)malloc(HEADERSIZE);
if(!data->state.headerbuff)
res = CURLE_OUT_OF_MEMORY;
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 = (curl_write_callback)fwrite;
/* use fread as default function to read input */
data->set.fread = (curl_read_callback)fread;
Daniel Stenberg
committed
/* conversion callbacks for non-ASCII hosts */
data->set.convfromnetwork = (curl_conv_callback)NULL;
data->set.convtonetwork = (curl_conv_callback)NULL;
data->set.convfromutf8 = (curl_conv_callback)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 */
Daniel Stenberg
committed
data->set.postfieldsize = -1;
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 = 1080;
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 */
Daniel Stenberg
committed
/* create an array with connection data struct pointers */
data->state.numconnects = 5; /* hard-coded right now */
data->state.connects = (struct connectdata **)
calloc(sizeof(struct connectdata *) * data->state.numconnects, 1);
if(!data->state.connects)
res = CURLE_OUT_OF_MEMORY;
Daniel Stenberg
committed
/* 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;
#ifdef CURL_CA_BUNDLE
/* This is our preferred CA cert bundle since install time */
data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
#endif
}
if(res) {
#ifdef USE_ARES
ares_destroy(data->state.areschannel);
#endif
if(data->state.headerbuff)
free(data->state.headerbuff);
free(data);
data = NULL;
}
Daniel Stenberg
committed
*curl = data;
return CURLE_OK;
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
va_list param)
char *argptr;
Daniel Stenberg
committed
CURLcode result = CURLE_OK;
switch(option) {
Sterling Hughes
committed
case CURLOPT_DNS_CACHE_TIMEOUT:
data->set.dns_cache_timeout = va_arg(param, int);
break;
Sterling Hughes
committed
{
int use_cache = va_arg(param, int);
if (use_cache) {
Curl_global_host_cache_init();
}
data->set.global_dns_cache = use_cache;
}
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
data->set.ssl.cipher_list = va_arg(param, char *);
break;
case CURLOPT_RANDOM_FILE:
/*
* This is the path name to a file that contains random data to seed
* the random SSL stuff with. The file is only used for reading.
*/
Daniel Stenberg
committed
data->set.ssl.random_file = va_arg(param, char *);
break;
case CURLOPT_EGDSOCKET:
/*
* The Entropy Gathering Daemon socket pathname
*/
Daniel Stenberg
committed
data->set.ssl.egdsocket = va_arg(param, char *);
break;
case CURLOPT_MAXCONNECTS:
/*
* Set the absolute number of maximum simultaneous alive connection that
* libcurl is allowed to have.
*/
{
long newconnects= va_arg(param, long);
struct connectdata **newptr;
Daniel Stenberg
committed
if(newconnects < data->state.numconnects) {
/* 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! */
Daniel Stenberg
committed
for(i=newconnects; i< data->state.numconnects; i++)
Curl_disconnect(data->state.connects[i]);
Daniel Stenberg
committed
/* If the most recent connection is no longer valid, mark it invalid. */
if(data->state.lastconnect <= newconnects)
data->state.lastconnect = -1;
}
if(newconnects) {
newptr= (struct connectdata **)
Daniel Stenberg
committed
realloc(data->state.connects,
sizeof(struct connectdata *) * newconnects);
if(!newptr)
/* we closed a few connections in vain, but so what? */
return CURLE_OUT_OF_MEMORY;
Daniel Stenberg
committed
/* nullify the newly added pointers */
for(i=data->state.numconnects; i<newconnects; i++) {
newptr[i] = NULL;
}
Daniel Stenberg
committed
data->state.connects = newptr;
data->state.numconnects = newconnects;
}
else {
/* zero makes NO cache at all */
Daniel Stenberg
committed
if(data->state.connects)
free(data->state.connects);
Daniel Stenberg
committed
data->state.connects = NULL;
data->state.numconnects = 0;
data->state.lastconnect = -1;
}
}
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.
*/
Daniel Stenberg
committed
data->set.reuse_forbid = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
Daniel Stenberg
committed
data->set.reuse_fresh = va_arg(param, long)?TRUE:FALSE;
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
Daniel Stenberg
committed
data->set.verbose = va_arg(param, long)?TRUE:FALSE;
/*
* Set to include the header in the general data output stream.
*/
data->set.include_header = va_arg(param, long)?TRUE:FALSE;
/*
* Shut off the internal supported progress meter
*/
Daniel Stenberg
committed
data->set.hide_progress = va_arg(param, long)?TRUE:FALSE;
if(data->set.hide_progress)
else
data->progress.flags &= ~PGRS_HIDE;
/*
* Do not include the body part in the output data stream.
*/
Daniel Stenberg
committed
data->set.opt_no_body = va_arg(param, long)?TRUE:FALSE;
if(data->set.opt_no_body)
/* in HTTP lingo, this means using the HEAD request */
data->set.httpreq = HTTPREQ_HEAD;
break;
case CURLOPT_FAILONERROR:
/*
* Don't output the >=300 error code HTML-page, but instead only
* return error.
*/
Daniel Stenberg
committed
data->set.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
case CURLOPT_PUT:
* We want to sent data to the remote host. If this is HTTP, that equals
* using the PUT request.
Daniel Stenberg
committed
data->set.upload = va_arg(param, long)?TRUE:FALSE;
if(data->set.upload)
/* If this is HTTP, PUT is what's needed to "upload" */
Daniel Stenberg
committed
data->set.httpreq = HTTPREQ_PUT;
/*
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
Daniel Stenberg
committed
data->set.get_filetime = va_arg(param, long)?TRUE:FALSE;
case CURLOPT_FTP_CREATE_MISSING_DIRS:
/*
* An FTP option that modifies an upload to create missing directories on
* the server.
data->set.ftp_create_missing_dirs = va_arg( param , long )?TRUE:FALSE;
break;
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 );
break;
/*
* An FTP option that changes the command to one that asks for a list
* only, no file info details.
*/
Daniel Stenberg
committed
data->set.ftp_list_only = va_arg(param, long)?TRUE:FALSE;
/*
* We want to upload and append to an existing (FTP) file.
*/
Daniel Stenberg
committed
data->set.ftp_append = va_arg(param, long)?TRUE:FALSE;
case CURLOPT_FTP_FILEMETHOD:
/*
* How do access files over FTP.
*/
data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
/*
* Parse the $HOME/.netrc file
*/
data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
case CURLOPT_NETRC_FILE:
/*
* Use this file instead of the $HOME/.netrc file
*/
data->set.netrc_file = va_arg(param, char *);
break;
case CURLOPT_TRANSFERTEXT:
* This option was previously named 'FTPASCII'. Renamed to work with
* more protocols than merely FTP.
*
* Transfer using ASCII (instead of BINARY).
Daniel Stenberg
committed
data->set.prefer_ascii = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_TIMECONDITION:
/*
* Set HTTP time condition. This must be one of the defines in the
* curl/curl.h header file.
*/
data->set.timecondition = (curl_TimeCond)va_arg(param, long);
/*
* This is the value to compare with the remote document with the
* method set with CURLOPT_TIMECONDITION
*/
data->set.timevalue = (time_t)va_arg(param, long);
/*
* Set explicit SSL version to try to connect with, as some SSL
* implementations are lame.
*/
Daniel Stenberg
committed
data->set.ssl.version = va_arg(param, long);
#ifndef CURL_DISABLE_HTTP
case CURLOPT_AUTOREFERER:
* Switch on automatic referer that gets set if curl follows locations.
data->set.http_auto_referer = va_arg(param, long)?1:0;
case CURLOPT_ENCODING:
* String to use at the value of Accept-Encoding header.
*
* If the encoding is set to "" we use an Accept-Encoding header that
* encompasses all the encodings we support.
* If the encoding is set to NULL we don't send an Accept-Encoding header
* and ignore an received Content-Encoding header.
*
data->set.encoding = va_arg(param, char *);
if(data->set.encoding && !*data->set.encoding)
data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
break;
case CURLOPT_FOLLOWLOCATION:
* Follow Location: header hints on a HTTP-server.
data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
case CURLOPT_UNRESTRICTED_AUTH:
* Send authentication (user+password) when following locations, even when
* hostname changed.
data->set.http_disable_hostname_check_before_authentication =
va_arg(param, long)?TRUE:FALSE;
case CURLOPT_MAXREDIRS:
* The maximum amount of hops you allow curl to follow Location:
* headers. This should mostly be used to detect never-ending loops.
data->set.maxredirs = va_arg(param, long);
case CURLOPT_POST:
/* Does this option serve a purpose anymore? Yes it does, when
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
callback! */
Daniel Stenberg
committed
if(va_arg(param, long)) {
data->set.httpreq = HTTPREQ_POST;
Daniel Stenberg
committed
data->set.opt_no_body = FALSE; /* this is implied */
}
else
data->set.httpreq = HTTPREQ_GET;
case CURLOPT_POSTFIELDS:
Daniel Stenberg
committed
* A string with POST data. Makes curl HTTP POST. Even if it is NULL.
data->set.postfields = va_arg(param, char *);
Daniel Stenberg
committed
data->set.httpreq = HTTPREQ_POST;
case CURLOPT_POSTFIELDSIZE:
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
* figure it out. Enables binary posts.
data->set.postfieldsize = va_arg(param, long);
break;
case CURLOPT_POSTFIELDSIZE_LARGE:
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
* figure it out. Enables binary posts.
data->set.postfieldsize = va_arg(param, curl_off_t);
/*
* Set to make us do HTTP POST
*/
data->set.httppost = va_arg(param, struct curl_httppost *);
Daniel Stenberg
committed
data->set.httpreq = HTTPREQ_POST_FORM;
Daniel Stenberg
committed
data->set.opt_no_body = FALSE; /* this is implied */
case CURLOPT_REFERER:
* String to set in the HTTP Referer: field.
if(data->change.referer_alloc) {
free(data->change.referer);
data->change.referer_alloc = FALSE;
}
data->set.set_referer = va_arg(param, char *);
data->change.referer = data->set.set_referer;
case CURLOPT_USERAGENT:
* String to use in the HTTP User-Agent field
data->set.useragent = va_arg(param, char *);
case CURLOPT_HTTPHEADER:
* Set a list with HTTP headers to use (or replace internals with)
data->set.headers = va_arg(param, struct curl_slist *);
case CURLOPT_HTTP200ALIASES:
* Set a list of aliases for HTTP 200 in response header
data->set.http200aliases = va_arg(param, struct curl_slist *);
#if !defined(CURL_DISABLE_COOKIES)
case CURLOPT_COOKIE:
* Cookie string to send to the remote server in the request.
data->set.cookie = va_arg(param, char *);
case CURLOPT_COOKIEFILE:
* Set cookie file to read and parse. Can be used multiple times.
argptr = (char *)va_arg(param, void *);
if(argptr) {
struct curl_slist *cl;
/* append the cookie file name to the list of file names, and deal with
them later */
cl = curl_slist_append(data->change.cookielist, argptr);
if(!cl)
return CURLE_OUT_OF_MEMORY;
data->change.cookielist = cl;
}
case CURLOPT_COOKIEJAR:
* Set cookie file name to dump all cookies to when we're done.
data->set.cookiejar = (char *)va_arg(param, void *);
* Activate the cookie parser. This may or may not already
* have been made.
data->cookies = Curl_cookie_init(data, NULL, data->cookies,
data->set.cookiesession);
break;
case CURLOPT_COOKIESESSION:
* Set this option to TRUE to start a new "cookie session". It will
* prevent the forthcoming read-cookies-from-file actions to accept
* cookies that are marked as being session cookies, as they belong to a
* previous session.
*
* In the original Netscape cookie spec, "session cookies" are cookies
* with no expire date set. RFC2109 describes the same action if no
* 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
* a 'Discard' action that can enforce the discard even for cookies that
* have a Max-Age.
*
* We run mostly with the original cookie spec, as hardly anyone implements
* anything else.
data->set.cookiesession = (bool)va_arg(param, long);
Daniel Stenberg
committed
case CURLOPT_COOKIELIST:
argptr = va_arg(param, char *);
Daniel Stenberg
committed
if(argptr == NULL)
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
if(strequal(argptr, "ALL")) {
/* clear all cookies */
Curl_cookie_clearall(data->cookies);
break;
}
else if(strequal(argptr, "SESS")) {
/* clear session cookies */
Curl_cookie_clearsess(data->cookies);
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
}
Daniel Stenberg
committed
if(!data->cookies)
Daniel Stenberg
committed
/* if cookie engine was not running, activate it */
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
Daniel Stenberg
committed
argptr = strdup(argptr);
if(!argptr) {
result = CURLE_OUT_OF_MEMORY;
break;
}
if(checkprefix("Set-Cookie:", argptr))
Daniel Stenberg
committed
/* HTTP Header format line */
Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
else
/* Netscape format line */
Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
Daniel Stenberg
committed
free(argptr);
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
#endif /* CURL_DISABLE_COOKIES */
case CURLOPT_HTTPGET:
* Set to force us do HTTP GET
if(va_arg(param, long)) {
data->set.httpreq = HTTPREQ_GET;
data->set.upload = FALSE; /* switch off upload */
Daniel Stenberg
committed
data->set.opt_no_body = FALSE; /* this is implied */
}
case CURLOPT_HTTP_VERSION:
/*
* This sets a requested HTTP version to be used. The value is one of
* the listed enums in curl/curl.h.
*/
data->set.httpversion = va_arg(param, long);
break;
case CURLOPT_HTTPPROXYTUNNEL:
* Tunnel operations through the proxy instead of normal proxy use
data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
case CURLOPT_CUSTOMREQUEST:
* Set a custom string to use as request
data->set.customrequest = va_arg(param, char *);
/* we don't set
data->set.httpreq = HTTPREQ_CUSTOM;
here, we continue as if we were using the already set type
and this just changes the actual request keyword */
/*
* Explicitly set HTTP proxy port number.
*/
Daniel Stenberg
committed
data->set.proxyport = va_arg(param, long);
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
*/
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
Daniel Stenberg
committed
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
#endif
if(!auth)
return CURLE_FAILED_INIT; /* no supported types left! */
data->set.httpauth = auth;
}
break;
case CURLOPT_PROXYAUTH:
/*
* Set HTTP Authentication type BITMASK.
*/
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
Daniel Stenberg
committed
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
#endif
if(!auth)
return CURLE_FAILED_INIT; /* no supported types left! */
data->set.proxyauth = auth;
}
break;
#endif /* CURL_DISABLE_HTTP */
Daniel Stenberg
committed
case CURLOPT_PROXY:
/*
* Set proxy server:port to use as HTTP proxy.
*
* If the proxy is set to "" we explicitly say that we don't want to use a
* proxy (even though there might be environment variables saying so).
*
* Setting it to NULL, means no proxy but allows the environment variables
* to decide for us.
*/
if(data->change.proxy_alloc) {
/*
* The already set string is allocated, free that first
*/
data->change.proxy_alloc=FALSE;;
free(data->change.proxy);
}
data->set.set_proxy = va_arg(param, char *);
data->change.proxy = data->set.set_proxy;
break;
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
case CURLOPT_WRITEHEADER:
/*
* Custom pointer to pass the header write callback function
*/
data->set.writeheader = (void *)va_arg(param, void *);
break;
case CURLOPT_ERRORBUFFER:
/*
* Error buffer provided by the caller to get the human readable
* error string in.
*/
data->set.errorbuffer = va_arg(param, char *);
break;
case CURLOPT_FILE:
/*
* FILE pointer to write to or include in the data write callback
*/
data->set.out = va_arg(param, FILE *);
break;
case CURLOPT_FTPPORT:
/*
* Use FTP PORT, this also specifies which IP address to use
*/
data->set.ftpport = va_arg(param, char *);
data->set.ftp_use_port = data->set.ftpport?1:0;
break;
case CURLOPT_FTP_USE_EPRT:
data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_FTP_USE_EPSV: