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
#if defined(WIN32) && !defined(__CYGWIN__)
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#ifdef HAVE_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
#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"
#include "easyif.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);
static bool IsPipeliningPossible(struct SessionHandle *handle);
static void conn_free(struct connectdata *conn);
static void signalPipeClose(struct curl_llist *pipe);
#define MAX_PIPELINE_LENGTH 5
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);
}
static void close_connections(struct SessionHandle *data)
{
/* Loop through all open connections and kill them one by one */
while(-1 != ConnectionKillOne(data))
; /* empty loop */
}
/*
* 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)
struct Curl_multi *m = data->multi;
Daniel Stenberg
committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#ifdef CURLDEBUG
/* only for debugging, scan through all connections and see if there's a
pipe reference still identifying this handle */
if(data->state.is_in_pipeline)
fprintf(stderr, "CLOSED when in pipeline!\n");
if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) {
struct conncache *c = data->state.connc;
int i;
struct curl_llist *pipe;
struct curl_llist_element *curr;
struct connectdata *connptr;
for(i=0; i< c->num; i++) {
connptr = c->connects[i];
if(!connptr)
continue;
pipe = connptr->send_pipe;
if(pipe) {
for (curr = pipe->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, connptr->bits.done);
}
}
}
pipe = connptr->recv_pipe;
if(pipe) {
for (curr = pipe->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, connptr->bits.done);
}
}
}
}
}
#endif
if(m)
/* This handle is still part of a multi handle, take care of this first
and detach this handle from there. */
Daniel Stenberg
committed
Curl_multi_rmeasy(data->multi, data);
Daniel Stenberg
committed
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 && (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);
/* free the connection cache if allocated privately */
Curl_rm_connc(data->state.connc);
Daniel Stenberg
committed
}
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
}
}
if(data->state.shared_conn) {
/* this handle is still being used by a shared connection cache and thus
we leave it around for now */
Curl_multi_add_closure(data->state.shared_conn, data);
return CURLE_OK;
}
/* Free the pathbuffer */
Curl_safefree(data->reqdata.pathbuffer);
Curl_safefree(data->reqdata.proto.generic);
/* 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
Curl_digest_cleanup(data);
Curl_safefree(data->info.contenttype);
Daniel Stenberg
committed
/* 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 */
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--;
/* create a connection cache of a private or multi type */
struct conncache *Curl_mk_connc(int type)
{
/* It is subject for debate how many default connections to have for a multi
connection cache... */
int default_amount = (type == CONNCACHE_PRIVATE)?5:10;
struct conncache *c;
c= calloc(sizeof(struct conncache), 1);
if(!c)
return NULL;
c->connects = calloc(sizeof(struct connectdata *), default_amount);
if(!c->connects) {
free(c);
return NULL;
}
c->num = default_amount;
return c;
}
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
/* Change number of entries of a connection cache */
CURLcode Curl_ch_connc(struct SessionHandle *data,
struct conncache *c,
long newamount)
{
int i;
struct connectdata **newptr;
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= (struct connectdata **)
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) {
int i;
for(i = 0; i < c->num; ++i)
conn_free(c->connects[i]);
free(c->connects);
}
free(c);
}
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;
data->magic = CURLEASY_MAGIC_NUMBER;
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
/* 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. */
Daniel Stenberg
committed
/* most recent connection is not yet defined */
data->state.lastconnect = -1;
Curl_easy_initHandleData(data);
/*
* 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;
Daniel Stenberg
committed
data->set.ssl.sessionid = TRUE; /* session ID caching enabled by default */
#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) {
ares_destroy(data->state.areschannel);
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();
}
}
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.
*/
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.
*/
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!
*/
data->set.reuse_fresh = (bool)(0 != va_arg(param, long));
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
/*
* Set to include the header in the general data output stream.
*/
data->set.include_header = (bool)(0 != va_arg(param, long));
/*
* Shut off the internal supported progress meter
*/
data->set.hide_progress = (bool)(0 != va_arg(param, long));
Daniel Stenberg
committed
if(data->set.hide_progress)
else
data->progress.flags &= ~PGRS_HIDE;
/*
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (bool)(0 != va_arg(param, long));
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.
*/
data->set.http_fail_on_error = (bool)(0 != va_arg(param, long));
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
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().
*/
data->set.get_filetime = (bool)(0 != va_arg(param, long));
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 = (bool)(0 != va_arg(param, long));
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.
*/
data->set.ftp_list_only = (bool)(0 != va_arg(param, long));
/*
* We want to upload and append to an existing (FTP) file.
*/
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);
/*
* 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).
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);
/*
* 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 = (bool)(0 != va_arg(param, long));
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 = (bool)(0 != va_arg(param, long));
case CURLOPT_UNRESTRICTED_AUTH:
* Send authentication (user+password) when following locations, even when
* hostname changed.
data->set.http_disable_hostname_check_before_authentication =
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)(0 != 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;