void Curl_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_cookie_loadfiles(data); } 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(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 */ data->change.cookielist = NULL; } 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); }
CURLSHcode curl_share_cleanup(CURLSH *sh) { struct Curl_share *share = (struct Curl_share *)sh; if (share == NULL) return CURLSHE_INVALID; if(share->lockfunc) share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, share->clientdata); if (share->dirty) { if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); return CURLSHE_IN_USE; } if(share->hostcache) Curl_hash_destroy(share->hostcache); #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(share->cookies) Curl_cookie_cleanup(share->cookies); #endif /* CURL_DISABLE_HTTP */ if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); free(share); return CURLSHE_OK; }
CURLSHcode curl_share_cleanup(CURLSH *sh) { struct Curl_share *share = (struct Curl_share *)sh; if (share == NULL) return CURLSHE_INVALID; share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, share->clientdata); if (share->dirty) { share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); return CURLSHE_IN_USE; } if(share->hostcache) Curl_hash_destroy(share->hostcache); if(share->cookies) Curl_cookie_cleanup(share->cookies); share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); free (share); return CURLSHE_OK; }
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; }
CURLSHcode curl_share_cleanup(CURLSH *sh) { struct Curl_share *share = (struct Curl_share *)sh; if(share == NULL) return CURLSHE_INVALID; if(share->lockfunc) share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, share->clientdata); if(share->dirty) { if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); return CURLSHE_IN_USE; } if(share->hostcache) { Curl_hash_destroy(share->hostcache); share->hostcache = NULL; } #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(share->cookies) Curl_cookie_cleanup(share->cookies); #endif #ifdef USE_SSL if(share->sslsession) { size_t i; for(i = 0; i < share->max_ssl_sessions; i++) Curl_ssl_kill_session(&(share->sslsession[i])); free(share->sslsession); } #endif if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); free(share); 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; 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_cookie_init() * * Inits a cookie struct to read data from a local file. This is always * called before any cookies are set. File may be NULL. * * If 'newsession' is TRUE, discard all "session cookies" on read from file. * * Returns NULL on out of memory. Invalid cookies are ignored. ****************************************************************************/ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, const char *file, struct CookieInfo *inc, bool newsession) { struct CookieInfo *c; FILE *fp = NULL; bool fromfile = TRUE; char *line = NULL; if(NULL == inc) { /* we didn't get a struct, create one */ c = calloc(1, sizeof(struct CookieInfo)); if(!c) return NULL; /* failed to get memory */ c->filename = strdup(file?file:"none"); /* copy the name just in case */ if(!c->filename) goto fail; /* failed to get memory */ } else { /* we got an already existing one, use that */ c = inc; } c->running = FALSE; /* this is not running, this is init */ if(file && !strcmp(file, "-")) { fp = stdin; fromfile = FALSE; } else if(file && !*file) { /* points to a "" string */ fp = NULL; } else fp = file?fopen(file, FOPEN_READTEXT):NULL; c->newsession = newsession; /* new session? */ if(fp) { char *lineptr; bool headerline; line = malloc(MAX_COOKIE_LINE); if(!line) goto fail; while(get_line(line, MAX_COOKIE_LINE, fp)) { if(checkprefix("Set-Cookie:", line)) { /* This is a cookie line, get it! */ lineptr = &line[11]; headerline = TRUE; } else { lineptr = line; headerline = FALSE; } while(*lineptr && ISBLANK(*lineptr)) lineptr++; Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL); } free(line); /* free the line buffer */ remove_expired(c); /* run this once, not on every cookie */ if(fromfile) fclose(fp); } c->running = TRUE; /* now, we're running */ return c; fail: free(line); if(!inc) /* Only clean up if we allocated it here, as the original could still be in * use by a share handle */ Curl_cookie_cleanup(c); if(fromfile && fp) fclose(fp); return NULL; /* out of memory */ }