From 606562aa7ea28ee0fdd5bf2cd6febada9594ad19 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 May 2006 22:46:38 +0000 Subject: [PATCH] Michael Wallner provided a patch that allows "SESS" to be set with CURLOPT_COOKIELIST, which then makes all session cookies get cleared. (slightly edited by me, and the re-indent in cookie.c was also done by me) --- CHANGES | 4 + RELEASE-NOTES | 3 +- docs/libcurl/curl_easy_setopt.3 | 2 + lib/cookie.c | 230 ++++++++++++++++++++------------ lib/cookie.h | 4 +- lib/url.c | 15 ++- 6 files changed, 160 insertions(+), 98 deletions(-) diff --git a/CHANGES b/CHANGES index 9f08a3036..1c8202070 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changelog +Daniel (25 May 2006) +- Michael Wallner provided a patch that allows "SESS" to be set with + CURLOPT_COOKIELIST, which then makes all session cookies get cleared. + Daniel (11 May 2006) - David McCreedy provided a fix for CURLINFO_LASTSOCKET that does extended checks on the to-be-returned socket to make sure it truly seems to be alive diff --git a/RELEASE-NOTES b/RELEASE-NOTES index cebc62aaa..ca693e1e1 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -11,6 +11,7 @@ Curl and libcurl 7.15.4 This release includes the following changes: + o CURLOPT_COOKIELIST set to "SESS" clears all session cookies o CURLINFO_LASTSOCKET returned sockets are now checked more before returned o curl-config got a --checkfor option to compare version numbers o line end conversions for FTP ASCII transfers @@ -56,6 +57,6 @@ advice from friends like these: Dan Fandrich, Ilja van Sprundel, David McCreedy, Tor Arntsen, Xavier Bouchoux, David Byron, Michele Bini, Ates Goral, Katie Wang, Robson Braga Araujo, Ale Vesely, Paul Querna, Gisle Vanem, Mark Eichin, Roland Blom, Andreas - Ntaflos, David Shaw + Ntaflos, David Shaw, Michael Wallner Thanks! (and sorry if I forgot to mention someone) diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index 69fa8b3cf..5e5afddc6 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -762,6 +762,8 @@ Pass a char * to a cookie string. Cookie can be either in Netscape / Mozilla format or just regular HTTP-style header (Set-Cookie: ...) format. If cURL cookie engine was not enabled it will enable its cookie engine. Passing a magic string \&"ALL" will erase all cookies known by cURL. (Added in 7.14.1) +Passing the special string \&"SESS" will only erase all session cookies known +by cURL. (Added in 7.15.4) .IP CURLOPT_HTTPGET Pass a long. If the long is non-zero, this forces the HTTP request to get back to GET. usable if a POST, HEAD, PUT or a custom request have been used diff --git a/lib/cookie.c b/lib/cookie.c index a8519c4e3..d934868ca 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -733,68 +733,81 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, char *host, char *path, bool secure) { - struct Cookie *newco; - struct Cookie *co; - time_t now = time(NULL); - struct Cookie *mainco=NULL; + struct Cookie *newco; + struct Cookie *co; + time_t now = time(NULL); + struct Cookie *mainco=NULL; - if(!c || !c->cookies) - return NULL; /* no cookie struct or no cookies in the struct */ + if(!c || !c->cookies) + return NULL; /* no cookie struct or no cookies in the struct */ - co = c->cookies; + co = c->cookies; - while(co) { - /* only process this cookie if it is not expired or had no expire - date AND that if the cookie requires we're secure we must only - continue if we are! */ - if( (co->expires<=0 || (co->expires> now)) && - (co->secure?secure:TRUE) ) { + while(co) { + /* only process this cookie if it is not expired or had no expire + date AND that if the cookie requires we're secure we must only + continue if we are! */ + if( (co->expires<=0 || (co->expires> now)) && + (co->secure?secure:TRUE) ) { - /* now check if the domain is correct */ - if(!co->domain || - (co->tailmatch && tailmatch(co->domain, host)) || - (!co->tailmatch && strequal(host, co->domain)) ) { - /* the right part of the host matches the domain stuff in the - cookie data */ + /* now check if the domain is correct */ + if(!co->domain || + (co->tailmatch && tailmatch(co->domain, host)) || + (!co->tailmatch && strequal(host, co->domain)) ) { + /* the right part of the host matches the domain stuff in the + cookie data */ - /* now check the left part of the path with the cookies path - requirement */ - if(!co->path || - checkprefix(co->path, path) ) { + /* now check the left part of the path with the cookies path + requirement */ + if(!co->path || + checkprefix(co->path, path) ) { - /* and now, we know this is a match and we should create an - entry for the return-linked-list */ + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ - newco = (struct Cookie *)malloc(sizeof(struct Cookie)); - if(newco) { - /* first, copy the whole source cookie: */ - memcpy(newco, co, sizeof(struct Cookie)); + newco = (struct Cookie *)malloc(sizeof(struct Cookie)); + if(newco) { + /* first, copy the whole source cookie: */ + memcpy(newco, co, sizeof(struct Cookie)); - /* then modify our next */ - newco->next = mainco; + /* then modify our next */ + newco->next = mainco; - /* point the main to us */ - mainco = newco; - } - else { - /* failure, clear up the allocated chain and return NULL */ - while(mainco) { - co = mainco->next; - free(mainco); - mainco = co; - } + /* point the main to us */ + mainco = newco; + } + else { + /* failure, clear up the allocated chain and return NULL */ + while(mainco) { + co = mainco->next; + free(mainco); + mainco = co; + } - return NULL; - } - } - } - } - co = co->next; - } + return NULL; + } + } + } + } + co = co->next; + } - return mainco; /* return the new list */ + return mainco; /* return the new list */ } +/***************************************************************************** + * + * Curl_cookie_clearall() + * + * Clear all existing cookies and reset the counter. + * + ****************************************************************************/ +void Curl_cookie_clearall(struct CookieInfo *cookies) +{ + Curl_cookie_freelist(cookies->cookies); + cookies->cookies = NULL; + cookies->numcookies = 0; +} /***************************************************************************** * @@ -806,17 +819,56 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, void Curl_cookie_freelist(struct Cookie *co) { - struct Cookie *next; - if(co) { - while(co) { - next = co->next; - free(co); /* we only free the struct since the "members" are all + struct Cookie *next; + if(co) { + while(co) { + next = co->next; + free(co); /* we only free the struct since the "members" are all just copied! */ - co = next; - } - } + co = next; + } + } } + +/***************************************************************************** + * + * Curl_cookie_clearsess() + * + * Free all session cookies in the cookies list. + * + ****************************************************************************/ +void Curl_cookie_clearsess(struct CookieInfo *cookies) +{ + struct Cookie *first, *curr, *next, *prev = NULL; + + if(!cookies->cookies) + return; + + first = curr = prev = cookies->cookies; + + for(; curr; curr = next) { + next = curr->next; + if(!curr->expires) { + if(first == curr) + first = next; + + if(prev == curr) + prev = next; + else + prev->next = next; + + free(curr); + cookies->numcookies--; + } + else + prev = curr; + } + + cookies->cookies = first; +} + + /***************************************************************************** * * Curl_cookie_cleanup() @@ -826,20 +878,20 @@ void Curl_cookie_freelist(struct Cookie *co) ****************************************************************************/ void Curl_cookie_cleanup(struct CookieInfo *c) { - struct Cookie *co; - struct Cookie *next; - if(c) { - if(c->filename) - free(c->filename); - co = c->cookies; + struct Cookie *co; + struct Cookie *next; + if(c) { + if(c->filename) + free(c->filename); + co = c->cookies; - while(co) { - next = co->next; - freecookie(co); - co = next; - } - free(c); /* free the base struct as well */ - } + while(co) { + next = co->next; + freecookie(co); + co = next; + } + free(c); /* free the base struct as well */ + } } /* get_netscape_format() @@ -850,24 +902,24 @@ void Curl_cookie_cleanup(struct CookieInfo *c) */ static char *get_netscape_format(const struct Cookie *co) { - return aprintf( - "%s%s\t" /* domain */ - "%s\t" /* tailmatch */ - "%s\t" /* path */ - "%s\t" /* secure */ - "%" FORMAT_OFF_T "\t" /* expires */ - "%s\t" /* name */ - "%s", /* value */ - /* Make sure all domains are prefixed with a dot if they allow - tailmatching. This is Mozilla-style. */ - (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", - co->domain?co->domain:"unknown", - co->tailmatch?"TRUE":"FALSE", - co->path?co->path:"/", - co->secure?"TRUE":"FALSE", - co->expires, - co->name, - co->value?co->value:""); + return aprintf( + "%s%s\t" /* domain */ + "%s\t" /* tailmatch */ + "%s\t" /* path */ + "%s\t" /* secure */ + "%" FORMAT_OFF_T "\t" /* expires */ + "%s\t" /* name */ + "%s", /* value */ + /* Make sure all domains are prefixed with a dot if they allow + tailmatching. This is Mozilla-style. */ + (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", + co->domain?co->domain:"unknown", + co->tailmatch?"TRUE":"FALSE", + co->path?co->path:"/", + co->secure?"TRUE":"FALSE", + co->expires, + co->name, + co->value?co->value:""); } /* diff --git a/lib/cookie.h b/lib/cookie.h index 0dd863074..bdd222b9c 100644 --- a/lib/cookie.h +++ b/lib/cookie.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -89,6 +89,8 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, char *, struct CookieInfo *, bool); struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool); void Curl_cookie_freelist(struct Cookie *); +void Curl_cookie_clearall(struct CookieInfo *cookies); +void Curl_cookie_clearsess(struct CookieInfo *cookies); void Curl_cookie_cleanup(struct CookieInfo *); int Curl_cookie_output(struct CookieInfo *, char *); diff --git a/lib/url.c b/lib/url.c index 690b3f302..e9fa81168 100644 --- a/lib/url.c +++ b/lib/url.c @@ -829,12 +829,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, break; if(strequal(argptr, "ALL")) { - if(data->cookies) { - /* clear all cookies */ - Curl_cookie_freelist(data->cookies->cookies); - data->cookies->cookies = NULL; - data->cookies->numcookies = 0; - } + /* clear all cookies */ + Curl_cookie_clearall(data->cookies); + break; + } + else if(strequal(argptr, "SESS")) { + /* clear session cookies */ + Curl_cookie_clearsess(data->cookies); break; } @@ -2299,7 +2300,7 @@ static CURLcode ConnectPlease(struct connectdata *conn, break; case CURLPROXY_SOCKS4: return handleSock4Proxy(conn->proxyuser, conn) ? - CURLE_COULDNT_CONNECT : CURLE_OK; + CURLE_COULDNT_CONNECT : CURLE_OK; default: failf(conn->data, "unknown proxytype option given"); return CURLE_COULDNT_CONNECT;