int main(int argc, char **argv) { struct CookieInfo *c=NULL; if(argc>1) { c = Curl_cookie_init(argv[1], c); Curl_cookie_add(c, TRUE, "PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/ftgw; secure"); Curl_cookie_add(c, TRUE, "foobar=yes; domain=.haxx.se; path=/looser;"); c = Curl_cookie_init(argv[1], c); Curl_cookie_output(c); Curl_cookie_cleanup(c); return 0; } return 1; }
struct Cookie* curl_cookie_add(struct SessionHandle *data, const char* value, const char* domain, const char* path) { if(!data->cookies) data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); return Curl_cookie_add(data, data->cookies, TRUE, (char*)value, domain, path); }
/* * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). */ void Curl_cookie_loadfiles(struct SessionHandle *data) { struct curl_slist *list = data->change.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { data->cookies = Curl_cookie_init(data, list->data, data->cookies, data->set.cookiesession); list = list->next; } curl_slist_free_all(data->change.cookielist); /* clean up list */ data->change.cookielist = NULL; /* don't do this again! */ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } }
/* * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). * * NOTE: OOM or cookie parsing failures are ignored. */ void Curl_cookie_loadfiles(struct Curl_easy *data) { struct curl_slist *list = data->change.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { struct CookieInfo *newcookies = Curl_cookie_init(data, list->data, data->cookies, data->set.cookiesession); if(!newcookies) /* Failure may be due to OOM or a bad cookie; both are ignored * but only the first should be */ infof(data, "ignoring failed cookie_init for %s\n", list->data); else data->cookies = newcookies; list = list->next; } curl_slist_free_all(data->change.cookielist); /* clean up list */ data->change.cookielist = NULL; /* don't do this again! */ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } }
/* * curl_easy_duphandle() is an external interface to allow duplication of a * given input easy handle. The returned handle will be a new working handle * with all options set exactly as the input source handle. */ CURL *curl_easy_duphandle(CURL *incurl) { bool fail = TRUE; struct SessionHandle *data=(struct SessionHandle *)incurl; struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle)); if(NULL == outcurl) return NULL; /* failure */ do { /* * We setup a few buffers we need. We should probably make them * get setup on-demand in the code, as that would probably decrease * the likeliness of us forgetting to init a buffer here in the future. */ outcurl->state.headerbuff = malloc(HEADERSIZE); if(!outcurl->state.headerbuff) { break; } outcurl->state.headersize=HEADERSIZE; /* copy all userdefined values */ if(Curl_dupset(outcurl, data) != CURLE_OK) break; /* the connection cache is setup on demand */ outcurl->state.connc = NULL; outcurl->state.lastconnect = -1; outcurl->progress.flags = data->progress.flags; outcurl->progress.callback = data->progress.callback; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(data->cookies) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ outcurl->cookies = Curl_cookie_init(data, data->cookies->filename, outcurl->cookies, data->set.cookiesession); if(!outcurl->cookies) { break; } } #endif /* CURL_DISABLE_HTTP */ /* duplicate all values in 'change' */ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(data->change.cookielist) { outcurl->change.cookielist = Curl_slist_duplicate(data->change.cookielist); if (!outcurl->change.cookielist) break; } #endif /* CURL_DISABLE_HTTP */ if(data->change.url) { outcurl->change.url = strdup(data->change.url); if(!outcurl->change.url) break; outcurl->change.url_alloc = TRUE; } if(data->change.referer) { outcurl->change.referer = strdup(data->change.referer); if(!outcurl->change.referer) break; outcurl->change.referer_alloc = TRUE; } #ifdef USE_ARES /* If we use ares, we setup a new ares channel for the new handle */ if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel)) break; #endif #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_OF_NETWORK); outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, CURL_ICONV_CODESET_OF_HOST); outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_FOR_UTF8); #endif Curl_easy_initHandleData(outcurl); outcurl->magic = CURLEASY_MAGIC_NUMBER; fail = FALSE; /* we reach this point and thus we are OK */ } while(0); if(fail) { if(outcurl) { if(outcurl->state.connc && (outcurl->state.connc->type == CONNCACHE_PRIVATE)) Curl_rm_connc(outcurl->state.connc); if(outcurl->state.headerbuff) free(outcurl->state.headerbuff); #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(outcurl->change.cookielist) curl_slist_free_all(outcurl->change.cookielist); #endif if(outcurl->change.url) free(outcurl->change.url); if(outcurl->change.referer) free(outcurl->change.referer); Curl_freeset(outcurl); free(outcurl); /* free the memory again */ outcurl = NULL; } } return outcurl; }
/* * curl_easy_duphandle() is an external interface to allow duplication of a * given input easy handle. The returned handle will be a new working handle * with all options set exactly as the input source handle. */ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) { struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); if(NULL == outcurl) goto fail; /* * We setup a few buffers we need. We should probably make them * get setup on-demand in the code, as that would probably decrease * the likeliness of us forgetting to init a buffer here in the future. */ outcurl->state.headerbuff = malloc(HEADERSIZE); if(!outcurl->state.headerbuff) goto fail; outcurl->state.headersize = HEADERSIZE; /* copy all userdefined values */ if(Curl_dupset(outcurl, data)) goto fail; /* the connection cache is setup on demand */ outcurl->state.conn_cache = NULL; outcurl->state.lastconnect = NULL; outcurl->progress.flags = data->progress.flags; outcurl->progress.callback = data->progress.callback; if(data->cookies) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ outcurl->cookies = Curl_cookie_init(data, data->cookies->filename, outcurl->cookies, data->set.cookiesession); if(!outcurl->cookies) goto fail; } /* duplicate all values in 'change' */ if(data->change.cookielist) { outcurl->change.cookielist = Curl_slist_duplicate(data->change.cookielist); if(!outcurl->change.cookielist) goto fail; } if(data->change.url) { outcurl->change.url = strdup(data->change.url); if(!outcurl->change.url) goto fail; outcurl->change.url_alloc = TRUE; } if(data->change.referer) { outcurl->change.referer = strdup(data->change.referer); if(!outcurl->change.referer) goto fail; outcurl->change.referer_alloc = TRUE; } /* Clone the resolver handle, if present, for the new handle */ if(Curl_resolver_duphandle(&outcurl->state.resolver, data->state.resolver)) goto fail; Curl_convert_setup(outcurl); outcurl->magic = CURLEASY_MAGIC_NUMBER; /* we reach this point and thus we are OK */ return outcurl; fail: if(outcurl) { curl_slist_free_all(outcurl->change.cookielist); outcurl->change.cookielist = NULL; Curl_safefree(outcurl->state.headerbuff); Curl_safefree(outcurl->change.url); Curl_safefree(outcurl->change.referer); Curl_freeset(outcurl); free(outcurl); } return NULL; }
CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) { struct Curl_share *share = (struct Curl_share *)sh; va_list param; int type; curl_lock_function lockfunc; curl_unlock_function unlockfunc; void *ptr; if (share->dirty) /* don't allow setting options while one or more handles are already using this share */ return CURLSHE_IN_USE; va_start(param, option); switch(option) { case CURLSHOPT_SHARE: /* this is a type this share will share */ type = va_arg(param, int); share->specifier |= (1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: if (!share->hostcache) { share->hostcache = Curl_mk_dnscache(); if(!share->hostcache) return CURLSHE_NOMEM; } break; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) case CURL_LOCK_DATA_COOKIE: if (!share->cookies) { share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); if(!share->cookies) return CURLSHE_NOMEM; } break; #endif /* CURL_DISABLE_HTTP */ case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */ case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ default: return CURLSHE_BAD_OPTION; } break; case CURLSHOPT_UNSHARE: /* this is a type this share will no longer share */ type = va_arg(param, int); share->specifier &= ~(1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: if (share->hostcache) { Curl_hash_destroy(share->hostcache); share->hostcache = NULL; } break; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) case CURL_LOCK_DATA_COOKIE: if (share->cookies) { Curl_cookie_cleanup(share->cookies); share->cookies = NULL; } break; #endif /* CURL_DISABLE_HTTP */ case CURL_LOCK_DATA_SSL_SESSION: break; case CURL_LOCK_DATA_CONNECT: break; default: return CURLSHE_BAD_OPTION; } break; case CURLSHOPT_LOCKFUNC: lockfunc = va_arg(param, curl_lock_function); share->lockfunc = lockfunc; break; case CURLSHOPT_UNLOCKFUNC: unlockfunc = va_arg(param, curl_unlock_function); share->unlockfunc = unlockfunc; break; case CURLSHOPT_USERDATA: ptr = va_arg(param, void *); share->clientdata = ptr; break; default: return CURLSHE_BAD_OPTION; } return CURLSHE_OK; }
CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) { struct Curl_share *share = (struct Curl_share *)sh; va_list param; int type; curl_lock_function lockfunc; curl_unlock_function unlockfunc; void *ptr; CURLSHcode res = CURLSHE_OK; if(share->dirty) /* don't allow setting options while one or more handles are already using this share */ return CURLSHE_IN_USE; va_start(param, option); switch(option) { case CURLSHOPT_SHARE: /* this is a type this share will share */ type = va_arg(param, int); share->specifier |= (1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: break; case CURL_LOCK_DATA_COOKIE: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(!share->cookies) { share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); if(!share->cookies) res = CURLSHE_NOMEM; } #else /* CURL_DISABLE_HTTP */ res = CURLSHE_NOT_BUILT_IN; #endif break; case CURL_LOCK_DATA_SSL_SESSION: #ifdef USE_SSL if(!share->sslsession) { share->max_ssl_sessions = 8; share->sslsession = calloc(share->max_ssl_sessions, sizeof(struct curl_ssl_session)); share->sessionage = 0; if(!share->sslsession) res = CURLSHE_NOMEM; } #else res = CURLSHE_NOT_BUILT_IN; #endif break; case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ break; default: res = CURLSHE_BAD_OPTION; } break; case CURLSHOPT_UNSHARE: /* this is a type this share will no longer share */ type = va_arg(param, int); share->specifier &= ~(1<<type); switch( type ) { case CURL_LOCK_DATA_DNS: break; case CURL_LOCK_DATA_COOKIE: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(share->cookies) { Curl_cookie_cleanup(share->cookies); share->cookies = NULL; } #else /* CURL_DISABLE_HTTP */ res = CURLSHE_NOT_BUILT_IN; #endif break; case CURL_LOCK_DATA_SSL_SESSION: #ifdef USE_SSL Curl_safefree(share->sslsession); #else res = CURLSHE_NOT_BUILT_IN; #endif break; case CURL_LOCK_DATA_CONNECT: break; default: res = CURLSHE_BAD_OPTION; break; } break; case CURLSHOPT_LOCKFUNC: lockfunc = va_arg(param, curl_lock_function); share->lockfunc = lockfunc; break; case CURLSHOPT_UNLOCKFUNC: unlockfunc = va_arg(param, curl_unlock_function); share->unlockfunc = unlockfunc; break; case CURLSHOPT_USERDATA: ptr = va_arg(param, void *); share->clientdata = ptr; break; default: res = CURLSHE_BAD_OPTION; break; } va_end(param); return res; }
/* * curl_easy_duphandle() is an external interface to allow duplication of a * given input easy handle. The returned handle will be a new working handle * with all options set exactly as the input source handle. */ CURL *curl_easy_duphandle(CURL *incurl) { bool fail = TRUE; struct SessionHandle *data=(struct SessionHandle *)incurl; struct SessionHandle *outcurl = (struct SessionHandle *) calloc(sizeof(struct SessionHandle), 1); if(NULL == outcurl) return NULL; /* failure */ do { /* * We setup a few buffers we need. We should probably make them * get setup on-demand in the code, as that would probably decrease * the likeliness of us forgetting to init a buffer here in the future. */ outcurl->state.headerbuff=(char*)malloc(HEADERSIZE); if(!outcurl->state.headerbuff) { break; } outcurl->state.headersize=HEADERSIZE; /* copy all userdefined values */ outcurl->set = data->set; outcurl->state.numconnects = data->state.numconnects; outcurl->state.connects = (struct connectdata **) malloc(sizeof(struct connectdata *) * outcurl->state.numconnects); if(!outcurl->state.connects) { break; } memset(outcurl->state.connects, 0, sizeof(struct connectdata *)*outcurl->state.numconnects); outcurl->progress.flags = data->progress.flags; outcurl->progress.callback = data->progress.callback; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(data->cookies) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ outcurl->cookies = Curl_cookie_init(data, data->cookies->filename, outcurl->cookies, data->set.cookiesession); if(!outcurl->cookies) { break; } } #endif /* CURL_DISABLE_HTTP */ /* duplicate all values in 'change' */ if(data->change.url) { outcurl->change.url = strdup(data->change.url); if(!outcurl->change.url) break; outcurl->change.url_alloc = TRUE; } if(data->change.proxy) { outcurl->change.proxy = strdup(data->change.proxy); if(!outcurl->change.proxy) break; outcurl->change.proxy_alloc = TRUE; } if(data->change.referer) { outcurl->change.referer = strdup(data->change.referer); if(!outcurl->change.referer) break; outcurl->change.referer_alloc = TRUE; } #ifdef USE_ARES /* If we use ares, we setup a new ares channel for the new handle */ if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel)) break; #endif fail = FALSE; /* we reach this point and thus we are OK */ } while(0); if(fail) { if(outcurl) { if(outcurl->state.connects) free(outcurl->state.connects); if(outcurl->state.headerbuff) free(outcurl->state.headerbuff); if(outcurl->change.proxy) free(outcurl->change.proxy); if(outcurl->change.url) free(outcurl->change.url); if(outcurl->change.referer) free(outcurl->change.referer); free(outcurl); /* free the memory again */ outcurl = NULL; } } return outcurl; }