blob: d25eb69c3a2b57e4b2f27268f381caecb856e67d [file] [log] [blame]
Daniel Stenbergba4e69b2002-09-03 11:52:59 +00001/***************************************************************************
Daniel Stenberg34e8baa2004-05-12 12:04:38 +00002 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
Daniel Stenberg24dee482001-01-03 09:29:33 +00006 * \___|\___/|_| \_\_____|
7 *
Daniel Stenberg277df1c2007-01-13 23:32:14 +00008 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
Daniel Stenberg24dee482001-01-03 09:29:33 +00009 *
Daniel Stenbergba4e69b2002-09-03 11:52:59 +000010 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
Daniel Stenberg34e8baa2004-05-12 12:04:38 +000013 *
Daniel Stenberg24dee482001-01-03 09:29:33 +000014 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
Daniel Stenbergba4e69b2002-09-03 11:52:59 +000016 * furnished to do so, under the terms of the COPYING file.
Daniel Stenberg24dee482001-01-03 09:29:33 +000017 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * $Id$
Daniel Stenbergba4e69b2002-09-03 11:52:59 +000022 ***************************************************************************/
Daniel Stenbergae1912c1999-12-29 14:20:26 +000023
24/***
25
26
27RECEIVING COOKIE INFORMATION
28============================
29
30struct CookieInfo *cookie_init(char *file);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +000031
Daniel Stenberg39af3942004-10-06 07:50:18 +000032 Inits a cookie struct to store data in a local file. This is always
33 called before any cookies are set.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000034
35int cookies_set(struct CookieInfo *cookie, char *cookie_line);
36
Daniel Stenberg39af3942004-10-06 07:50:18 +000037 The 'cookie_line' parameter is a full "Set-cookie:" line as
38 received from a server.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000039
Daniel Stenberg39af3942004-10-06 07:50:18 +000040 The function need to replace previously stored lines that this new
41 line superceeds.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000042
Daniel Stenberg39af3942004-10-06 07:50:18 +000043 It may remove lines that are expired.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000044
Daniel Stenberg39af3942004-10-06 07:50:18 +000045 It should return an indication of success/error.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000046
47
48SENDING COOKIE INFORMATION
49==========================
50
51struct Cookies *cookie_getlist(struct CookieInfo *cookie,
52 char *host, char *path, bool secure);
53
Daniel Stenberg39af3942004-10-06 07:50:18 +000054 For a given host and path, return a linked list of cookies that
55 the client should send to the server if used now. The secure
56 boolean informs the cookie if a secure connection is achieved or
57 not.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000058
Daniel Stenberg39af3942004-10-06 07:50:18 +000059 It shall only return cookies that haven't expired.
Daniel Stenbergae1912c1999-12-29 14:20:26 +000060
Daniel Stenberg34e8baa2004-05-12 12:04:38 +000061
Daniel Stenbergae1912c1999-12-29 14:20:26 +000062Example set of cookies:
Daniel Stenberg34e8baa2004-05-12 12:04:38 +000063
Daniel Stenbergae1912c1999-12-29 14:20:26 +000064 Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
65 Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
66 domain=.fidelity.com; path=/ftgw; secure
67 Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
68 domain=.fidelity.com; path=/; secure
69 Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
70 domain=.fidelity.com; path=/; secure
71 Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
72 domain=.fidelity.com; path=/; secure
73 Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
74 domain=.fidelity.com; path=/; secure
75 Set-cookie:
76 Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
77 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
78****/
79
Sterling Hughesad6fca22003-03-31 15:59:17 +000080
Daniel Stenbergb6e18f22000-08-24 14:26:33 +000081#include "setup.h"
82
Daniel Stenbergac269a82004-12-05 23:59:32 +000083#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Daniel Stenberg08ef2082002-06-11 11:13:01 +000084
Daniel Stenbergae1912c1999-12-29 14:20:26 +000085#include <stdlib.h>
86#include <string.h>
Daniel Stenbergae1912c1999-12-29 14:20:26 +000087
Daniel Stenberg2236ba02005-07-27 22:17:14 +000088#define _MPRINTF_REPLACE /* without this on windows OS we get undefined reference to snprintf */
89#include <curl/mprintf.h>
90
Daniel Stenberg168703b2003-08-11 09:55:11 +000091#include "urldata.h"
Daniel Stenbergae1912c1999-12-29 14:20:26 +000092#include "cookie.h"
Daniel Stenberg96dde762000-05-22 14:12:12 +000093#include "strequal.h"
Daniel Stenberg870bacd2001-05-30 11:06:56 +000094#include "strtok.h"
Daniel Stenberg168703b2003-08-11 09:55:11 +000095#include "sendf.h"
Daniel Stenbergbbafb2e2004-05-11 11:30:23 +000096#include "memory.h"
Daniel Stenberga676c182005-08-17 08:55:43 +000097#include "share.h"
98#include "strtoofft.h"
Daniel Stenbergae1912c1999-12-29 14:20:26 +000099
Daniel Stenberg0f8facb2000-10-09 11:12:34 +0000100/* The last #include file should be: */
Daniel Stenberg2bd71d72003-06-26 06:50:32 +0000101#ifdef CURLDEBUG
Daniel Stenberg0f8facb2000-10-09 11:12:34 +0000102#include "memdebug.h"
103#endif
104
Daniel Stenbergbe7ce432004-10-03 21:02:01 +0000105
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000106static void freecookie(struct Cookie *co)
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000107{
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000108 if(co->expirestr)
109 free(co->expirestr);
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000110 if(co->domain)
111 free(co->domain);
112 if(co->path)
113 free(co->path);
114 if(co->name)
115 free(co->name);
116 if(co->value)
117 free(co->value);
Daniel Stenbergf40c9b82004-10-16 13:54:40 +0000118 if(co->maxage)
119 free(co->maxage);
Daniel Stenberg67abd4c2004-12-22 22:33:31 +0000120 if(co->version)
121 free(co->version);
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000122
123 free(co);
124}
125
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000126static bool tailmatch(const char *little, const char *bigone)
127{
Daniel Stenbergd5710642004-02-26 13:40:43 +0000128 size_t littlelen = strlen(little);
129 size_t biglen = strlen(bigone);
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000130
131 if(littlelen > biglen)
132 return FALSE;
133
Daniel Stenberg99482502004-03-10 09:41:37 +0000134 return (bool)strequal(little, bigone+biglen-littlelen);
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000135}
136
Daniel Stenberga676c182005-08-17 08:55:43 +0000137/*
138 * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
139 */
140void Curl_cookie_loadfiles(struct SessionHandle *data)
141{
142 struct curl_slist *list = data->change.cookielist;
143 if(list) {
144 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
145 while(list) {
146 data->cookies = Curl_cookie_init(data,
147 list->data,
148 data->cookies,
149 data->set.cookiesession);
150 list = list->next;
151 }
152 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
153 curl_slist_free_all(data->change.cookielist); /* clean up list */
154 data->change.cookielist = NULL; /* don't do this again! */
155 }
156}
157
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000158/****************************************************************************
159 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000160 * Curl_cookie_add()
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000161 *
162 * Add a single cookie line to the cookie keeping object.
163 *
164 ***************************************************************************/
165
Daniel Stenberg40311042001-01-05 10:11:41 +0000166struct Cookie *
Daniel Stenberg168703b2003-08-11 09:55:11 +0000167Curl_cookie_add(struct SessionHandle *data,
168 /* The 'data' pointer here may be NULL at times, and thus
169 must only be used very carefully for things that can deal
170 with data being NULL. Such as infof() and similar */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000171
Daniel Stenberg168703b2003-08-11 09:55:11 +0000172 struct CookieInfo *c,
Daniel Stenberg40311042001-01-05 10:11:41 +0000173 bool httpheader, /* TRUE if HTTP header-style line */
Daniel Stenbergd8b2c812002-07-29 22:22:49 +0000174 char *lineptr, /* first character of the line */
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000175 char *domain, /* default domain */
176 char *path) /* full path used when this cookie is set,
177 used to get default path for the cookie
178 unless set */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000179{
180 struct Cookie *clist;
Daniel Stenberg35558e62004-06-22 21:15:51 +0000181 char *what;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000182 char name[MAX_NAME];
183 char *ptr;
184 char *semiptr;
185 struct Cookie *co;
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000186 struct Cookie *lastc=NULL;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000187 time_t now = time(NULL);
188 bool replace_old = FALSE;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000189 bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000190
Yang Tsef08ac862007-03-25 02:30:58 +0000191#ifdef CURL_DISABLE_VERBOSE_STRINGS
192 (void)data;
193#endif
194
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000195 /* First, alloc and init a new struct for it */
Daniel Stenberg7d8cd592004-02-26 14:52:16 +0000196 co = (struct Cookie *)calloc(sizeof(struct Cookie), 1);
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000197 if(!co)
198 return NULL; /* bail out if we're this low on memory */
199
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000200 if(httpheader) {
201 /* This line was read off a HTTP-header */
Daniel Stenberga23a8972002-02-26 13:07:53 +0000202 char *sep;
Daniel Stenberg35558e62004-06-22 21:15:51 +0000203
204 what = malloc(MAX_COOKIE_LINE);
205 if(!what) {
206 free(co);
207 return NULL;
208 }
209
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000210 semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
Daniel Stenbergd8b2c812002-07-29 22:22:49 +0000211
Yang Tse6d05a332007-02-13 17:47:27 +0000212 while(*lineptr && ISBLANK(*lineptr))
Daniel Stenbergd8b2c812002-07-29 22:22:49 +0000213 lineptr++;
214
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000215 ptr = lineptr;
Daniel Stenberg28ad7dc2000-09-25 22:14:42 +0000216 do {
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000217 /* we have a <what>=<this> pair or a 'secure' word here */
Daniel Stenberga23a8972002-02-26 13:07:53 +0000218 sep = strchr(ptr, '=');
219 if(sep && (!semiptr || (semiptr>sep)) ) {
220 /*
221 * There is a = sign and if there was a semicolon too, which make sure
222 * that the semicolon comes _after_ the equal sign.
223 */
224
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000225 name[0]=what[0]=0; /* init the buffers */
Daniel Stenberga23a8972002-02-26 13:07:53 +0000226 if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
Daniel Stenberg3612c372002-02-27 07:38:04 +0000227 MAX_COOKIE_LINE_TXT "[^;\r\n]",
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000228 name, what)) {
Daniel Stenberg3612c372002-02-27 07:38:04 +0000229 /* this is a <name>=<what> pair */
230
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000231 char *whatptr;
232
Daniel Stenberg3612c372002-02-27 07:38:04 +0000233 /* Strip off trailing whitespace from the 'what' */
Daniel Stenbergd5710642004-02-26 13:40:43 +0000234 size_t len=strlen(what);
Yang Tse6d05a332007-02-13 17:47:27 +0000235 while(len && ISBLANK(what[len-1])) {
Daniel Stenberg3612c372002-02-27 07:38:04 +0000236 what[len-1]=0;
237 len--;
238 }
239
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000240 /* Skip leading whitespace from the 'what' */
241 whatptr=what;
Yang Tse6d05a332007-02-13 17:47:27 +0000242 while(*whatptr && ISBLANK(*whatptr)) {
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000243 whatptr++;
244 }
245
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000246 if(strequal("path", name)) {
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000247 co->path=strdup(whatptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000248 if(!co->path) {
249 badcookie = TRUE; /* out of memory bad */
250 break;
251 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000252 }
253 else if(strequal("domain", name)) {
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000254 /* note that this name may or may not have a preceeding dot, but
255 we don't care about that, we treat the names the same anyway */
256
Daniel Stenberg4d17d682004-01-29 13:56:45 +0000257 const char *domptr=whatptr;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000258 int dotcount=1;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000259
Daniel Stenbergde6ab3d2004-08-04 12:26:27 +0000260 /* Count the dots, we need to make sure that there are enough
261 of them. */
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000262
263 if('.' == whatptr[0])
264 /* don't count the initial dot, assume it */
Daniel Stenberg4d17d682004-01-29 13:56:45 +0000265 domptr++;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000266
267 do {
Daniel Stenberg4d17d682004-01-29 13:56:45 +0000268 domptr = strchr(domptr, '.');
269 if(domptr) {
270 domptr++;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000271 dotcount++;
272 }
Daniel Stenberg4d17d682004-01-29 13:56:45 +0000273 } while(domptr);
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000274
Daniel Stenberg98ee12b2003-08-04 23:05:57 +0000275 /* The original Netscape cookie spec defined that this domain name
276 MUST have three dots (or two if one of the seven holy TLDs),
277 but it seems that these kinds of cookies are in use "out there"
278 so we cannot be that strict. I've therefore lowered the check
279 to not allow less than two dots. */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000280
Daniel Stenberg98ee12b2003-08-04 23:05:57 +0000281 if(dotcount < 2) {
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000282 /* Received and skipped a cookie with a domain using too few
283 dots. */
284 badcookie=TRUE; /* mark this as a bad cookie */
Daniel Stenberg0e031652004-07-26 15:42:07 +0000285 infof(data, "skipped cookie with illegal dotcount domain: %s\n",
Daniel Stenberg168703b2003-08-11 09:55:11 +0000286 whatptr);
Daniel Stenberg465de792003-05-15 22:28:19 +0000287 }
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000288 else {
289 /* Now, we make sure that our host is within the given domain,
290 or the given domain is not valid and thus cannot be set. */
291
Daniel Stenberg755f98e2004-05-21 20:40:15 +0000292 if('.' == whatptr[0])
293 whatptr++; /* ignore preceeding dot */
294
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000295 if(!domain || tailmatch(whatptr, domain)) {
Daniel Stenberg4d17d682004-01-29 13:56:45 +0000296 const char *tailptr=whatptr;
297 if(tailptr[0] == '.')
298 tailptr++;
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000299 co->domain=strdup(tailptr); /* don't prefix w/dots
300 internally */
301 if(!co->domain) {
302 badcookie = TRUE;
303 break;
304 }
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000305 co->tailmatch=TRUE; /* we always do that if the domain name was
306 given */
307 }
Daniel Stenberg465de792003-05-15 22:28:19 +0000308 else {
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000309 /* we did not get a tailmatch and then the attempted set domain
310 is not a domain to which the current host belongs. Mark as
311 bad. */
312 badcookie=TRUE;
Daniel Stenberg0e031652004-07-26 15:42:07 +0000313 infof(data, "skipped cookie with bad tailmatch domain: %s\n",
Daniel Stenberg168703b2003-08-11 09:55:11 +0000314 whatptr);
Daniel Stenberg465de792003-05-15 22:28:19 +0000315 }
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000316 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000317 }
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000318 else if(strequal("version", name)) {
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000319 co->version=strdup(whatptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000320 if(!co->version) {
321 badcookie = TRUE;
322 break;
323 }
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000324 }
325 else if(strequal("max-age", name)) {
326 /* Defined in RFC2109:
327
328 Optional. The Max-Age attribute defines the lifetime of the
329 cookie, in seconds. The delta-seconds value is a decimal non-
330 negative integer. After delta-seconds seconds elapse, the
331 client should discard the cookie. A value of zero means the
332 cookie should be discarded immediately.
333
334 */
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000335 co->maxage = strdup(whatptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000336 if(!co->maxage) {
337 badcookie = TRUE;
338 break;
339 }
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000340 co->expires =
Daniel Stenberg6b1220b2005-04-26 13:08:49 +0000341 atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + (long)now;
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000342 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000343 else if(strequal("expires", name)) {
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000344 co->expirestr=strdup(whatptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000345 if(!co->expirestr) {
346 badcookie = TRUE;
347 break;
348 }
Daniel Stenberg90e1a692005-08-17 09:11:27 +0000349 co->expires = curl_getdate(what, &now);
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000350 }
351 else if(!co->name) {
352 co->name = strdup(name);
Daniel Stenberg2361aab2002-04-14 18:21:17 +0000353 co->value = strdup(whatptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000354 if(!co->name || !co->value) {
355 badcookie = TRUE;
356 break;
357 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000358 }
Daniel Stenbergc8926132001-08-14 08:17:29 +0000359 /*
360 else this is the second (or more) name we don't know
361 about! */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000362 }
363 else {
364 /* this is an "illegal" <what>=<this> pair */
365 }
366 }
367 else {
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000368 if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000369 what)) {
370 if(strequal("secure", what))
371 co->secure = TRUE;
Daniel Stenbergc8926132001-08-14 08:17:29 +0000372 /* else,
373 unsupported keyword without assign! */
374
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000375 }
376 }
Daniel Stenberga23a8972002-02-26 13:07:53 +0000377 if(!semiptr || !*semiptr) {
378 /* we already know there are no more cookies */
379 semiptr = NULL;
380 continue;
381 }
Daniel Stenberg28ad7dc2000-09-25 22:14:42 +0000382
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000383 ptr=semiptr+1;
Yang Tse6d05a332007-02-13 17:47:27 +0000384 while(ptr && *ptr && ISBLANK(*ptr))
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000385 ptr++;
386 semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
Daniel Stenberg87037132002-01-07 23:05:36 +0000387
388 if(!semiptr && *ptr)
389 /* There are no more semicolons, but there's a final name=value pair
390 coming up */
Daniel Stenberga23a8972002-02-26 13:07:53 +0000391 semiptr=strchr(ptr, '\0');
Daniel Stenberg28ad7dc2000-09-25 22:14:42 +0000392 } while(semiptr);
Daniel Stenberg598e8df2001-09-26 07:08:29 +0000393
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000394 if(!badcookie && !co->domain) {
395 if(domain) {
396 /* no domain was given in the header line, set the default */
397 co->domain=strdup(domain);
398 if(!co->domain)
399 badcookie = TRUE;
400 }
Daniel Stenberga23a8972002-02-26 13:07:53 +0000401 }
402
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000403 if(!badcookie && !co->path && path) {
404 /* no path was given in the header line, set the default */
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000405 char *endslash = strrchr(path, '/');
406 if(endslash) {
Daniel Stenbergd5710642004-02-26 13:40:43 +0000407 size_t pathlen = endslash-path+1; /* include the ending slash */
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000408 co->path=malloc(pathlen+1); /* one extra for the zero byte */
409 if(co->path) {
410 memcpy(co->path, path, pathlen);
411 co->path[pathlen]=0; /* zero terminate */
412 }
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000413 else
414 badcookie = TRUE;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000415 }
416 }
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000417
Daniel Stenberg35558e62004-06-22 21:15:51 +0000418 free(what);
419
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000420 if(badcookie || !co->name) {
421 /* we didn't get a cookie name or a bad one,
422 this is an illegal line, bail out */
423 freecookie(co);
424 return NULL;
425 }
426
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000427 }
428 else {
429 /* This line is NOT a HTTP header style line, we do offer support for
430 reading the odd netscape cookies-file format here */
431 char *firstptr;
Daniel Stenbergd5676592001-05-29 19:17:39 +0000432 char *tok_buf;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000433 int fields;
434
435 if(lineptr[0]=='#') {
436 /* don't even try the comments */
437 free(co);
438 return NULL;
439 }
440 /* strip off the possible end-of-line characters */
Daniel Stenberg96dde762000-05-22 14:12:12 +0000441 ptr=strchr(lineptr, '\r');
442 if(ptr)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000443 *ptr=0; /* clear it */
Daniel Stenberg96dde762000-05-22 14:12:12 +0000444 ptr=strchr(lineptr, '\n');
445 if(ptr)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000446 *ptr=0; /* clear it */
447
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000448 firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000449
450 /* Here's a quick check to eliminate normal HTTP-headers from this */
451 if(!firstptr || strchr(firstptr, ':')) {
452 free(co);
453 return NULL;
454 }
455
456 /* Now loop through the fields and init the struct we already have
457 allocated */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000458 for(ptr=firstptr, fields=0; ptr && !badcookie;
Daniel Stenbergefd836d2003-04-30 17:03:43 +0000459 ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000460 switch(fields) {
461 case 0:
Daniel Stenberg465de792003-05-15 22:28:19 +0000462 if(ptr[0]=='.') /* skip preceeding dots */
463 ptr++;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000464 co->domain = strdup(ptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000465 if(!co->domain)
466 badcookie = TRUE;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000467 break;
468 case 1:
Daniel Stenberg72dec6c2001-05-23 13:04:19 +0000469 /* This field got its explanation on the 23rd of May 2001 by
470 Andrés García:
471
472 flag: A TRUE/FALSE value indicating if all machines within a given
473 domain can access the variable. This value is set automatically by
474 the browser, depending on the value you set for the domain.
475
476 As far as I can see, it is set to true when the cookie says
477 .domain.com and to false when the domain is complete www.domain.com
Daniel Stenberg72dec6c2001-05-23 13:04:19 +0000478 */
Daniel Stenberg99482502004-03-10 09:41:37 +0000479 co->tailmatch=(bool)strequal(ptr, "TRUE"); /* store information */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000480 break;
481 case 2:
Daniel Stenberg8dc9f432001-05-23 09:26:45 +0000482 /* It turns out, that sometimes the file format allows the path
483 field to remain not filled in, we try to detect this and work
484 around it! Andrés García made us aware of this... */
485 if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
486 /* only if the path doesn't look like a boolean option! */
487 co->path = strdup(ptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000488 if(!co->path)
489 badcookie = TRUE;
Daniel Stenberg8dc9f432001-05-23 09:26:45 +0000490 break;
491 }
492 /* this doesn't look like a path, make one up! */
493 co->path = strdup("/");
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000494 if(!co->path)
495 badcookie = TRUE;
Daniel Stenberg8dc9f432001-05-23 09:26:45 +0000496 fields++; /* add a field and fall down to secure */
497 /* FALLTHROUGH */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000498 case 3:
Daniel Stenberg99482502004-03-10 09:41:37 +0000499 co->secure = (bool)strequal(ptr, "TRUE");
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000500 break;
501 case 4:
Daniel Stenberga676c182005-08-17 08:55:43 +0000502 co->expires = curlx_strtoofft(ptr, NULL, 10);
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000503 break;
504 case 5:
505 co->name = strdup(ptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000506 if(!co->name)
507 badcookie = TRUE;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000508 break;
509 case 6:
510 co->value = strdup(ptr);
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000511 if(!co->value)
512 badcookie = TRUE;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000513 break;
514 }
515 }
Daniel Stenberg168703b2003-08-11 09:55:11 +0000516 if(6 == fields) {
517 /* we got a cookie with blank contents, fix it */
518 co->value = strdup("");
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000519 if(!co->value)
520 badcookie = TRUE;
521 else
522 fields++;
Daniel Stenberg168703b2003-08-11 09:55:11 +0000523 }
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000524
525 if(!badcookie && (7 != fields))
526 /* we did not find the sufficient number of fields */
527 badcookie = TRUE;
528
529 if(badcookie) {
530 freecookie(co);
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000531 return NULL;
532 }
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000533
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000534 }
535
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000536 if(!c->running && /* read from a file */
537 c->newsession && /* clean session cookies */
538 !co->expires) { /* this is a session cookie since it doesn't expire! */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000539 freecookie(co);
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000540 return NULL;
541 }
542
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000543 co->livecookie = c->running;
544
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000545 /* now, we have parsed the incoming line, we must now check if this
546 superceeds an already existing cookie, which it may if the previous have
547 the same domain and path as this */
548
549 clist = c->cookies;
550 replace_old = FALSE;
551 while(clist) {
552 if(strequal(clist->name, co->name)) {
553 /* the names are identical */
554
555 if(clist->domain && co->domain) {
Daniel Stenberg465de792003-05-15 22:28:19 +0000556 if(strequal(clist->domain, co->domain))
557 /* The domains are identical */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000558 replace_old=TRUE;
559 }
560 else if(!clist->domain && !co->domain)
561 replace_old = TRUE;
562
563 if(replace_old) {
564 /* the domains were identical */
565
566 if(clist->path && co->path) {
567 if(strequal(clist->path, co->path)) {
568 replace_old = TRUE;
569 }
570 else
571 replace_old = FALSE;
572 }
573 else if(!clist->path && !co->path)
574 replace_old = TRUE;
575 else
576 replace_old = FALSE;
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000577
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000578 }
579
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000580 if(replace_old && !co->livecookie && clist->livecookie) {
581 /* Both cookies matched fine, except that the already present
582 cookie is "live", which means it was set from a header, while
583 the new one isn't "live" and thus only read from a file. We let
584 live cookies stay alive */
585
586 /* Free the newcomer and get out of here! */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000587 freecookie(co);
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000588 return NULL;
589 }
590
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000591 if(replace_old) {
592 co->next = clist->next; /* get the next-pointer first */
593
594 /* then free all the old pointers */
595 if(clist->name)
596 free(clist->name);
597 if(clist->value)
598 free(clist->value);
599 if(clist->domain)
600 free(clist->domain);
601 if(clist->path)
602 free(clist->path);
603 if(clist->expirestr)
604 free(clist->expirestr);
605
Daniel Stenbergc6a8bb32000-02-01 23:54:51 +0000606 if(clist->version)
607 free(clist->version);
608 if(clist->maxage)
609 free(clist->maxage);
610
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000611 *clist = *co; /* then store all the new data */
Daniel Stenbergc6822f52001-10-24 11:36:55 +0000612
613 free(co); /* free the newly alloced memory */
614 co = clist; /* point to the previous struct instead */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000615
Daniel Stenbergd9a77732002-01-07 14:56:15 +0000616 /* We have replaced a cookie, now skip the rest of the list but
617 make sure the 'lastc' pointer is properly set */
618 do {
619 lastc = clist;
620 clist = clist->next;
621 } while(clist);
622 break;
623 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000624 }
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000625 lastc = clist;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000626 clist = clist->next;
627 }
628
Daniel Stenberg168703b2003-08-11 09:55:11 +0000629 if(c->running)
630 /* Only show this when NOT reading the cookies from a file */
631 infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, expire %d\n",
632 replace_old?"Replaced":"Added", co->name, co->value,
633 co->domain, co->path, co->expires);
634
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000635 if(!replace_old) {
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000636 /* then make the last item point on this new one */
637 if(lastc)
638 lastc->next = co;
639 else
640 c->cookies = co;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000641 }
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000642
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000643 c->numcookies++; /* one more cookie in the jar */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000644 return co;
645}
646
647/*****************************************************************************
648 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000649 * Curl_cookie_init()
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000650 *
651 * Inits a cookie struct to read data from a local file. This is always
652 * called before any cookies are set. File may be NULL.
653 *
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000654 * If 'newsession' is TRUE, discard all "session cookies" on read from file.
655 *
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000656 ****************************************************************************/
Daniel Stenberg168703b2003-08-11 09:55:11 +0000657struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
658 char *file,
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000659 struct CookieInfo *inc,
660 bool newsession)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000661{
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000662 struct CookieInfo *c;
663 FILE *fp;
Daniel Stenberg9280c202000-02-10 23:14:53 +0000664 bool fromfile=TRUE;
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000665
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000666 if(NULL == inc) {
667 /* we didn't get a struct, create one */
Daniel Stenbergce945bd2004-06-30 12:05:07 +0000668 c = (struct CookieInfo *)calloc(1, sizeof(struct CookieInfo));
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000669 if(!c)
670 return NULL; /* failed to get memory */
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000671 c->filename = strdup(file?file:"none"); /* copy the name just in case */
672 }
673 else {
674 /* we got an already existing one, use that */
675 c = inc;
676 }
677 c->running = FALSE; /* this is not running, this is init */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000678
Daniel Stenbergf2a25962001-10-10 12:48:32 +0000679 if(file && strequal(file, "-")) {
Daniel Stenberg9280c202000-02-10 23:14:53 +0000680 fp = stdin;
681 fromfile=FALSE;
682 }
Daniel Stenberg6f752c62005-03-04 00:26:50 +0000683 else if(file && !*file) {
684 /* points to a "" string */
685 fp = NULL;
686 }
Daniel Stenberg9280c202000-02-10 23:14:53 +0000687 else
688 fp = file?fopen(file, "r"):NULL;
689
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000690 c->newsession = newsession; /* new session? */
691
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000692 if(fp) {
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000693 char *lineptr;
694 bool headerline;
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000695
Daniel Stenbergce945bd2004-06-30 12:05:07 +0000696 char *line = (char *)malloc(MAX_COOKIE_LINE);
697 if(line) {
698 while(fgets(line, MAX_COOKIE_LINE, fp)) {
699 if(checkprefix("Set-Cookie:", line)) {
700 /* This is a cookie line, get it! */
701 lineptr=&line[11];
702 headerline=TRUE;
703 }
704 else {
705 lineptr=line;
706 headerline=FALSE;
707 }
Yang Tse6d05a332007-02-13 17:47:27 +0000708 while(*lineptr && ISBLANK(*lineptr))
Daniel Stenbergce945bd2004-06-30 12:05:07 +0000709 lineptr++;
710
711 Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
712 }
713 free(line); /* free the line buffer */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000714 }
Daniel Stenberg9280c202000-02-10 23:14:53 +0000715 if(fromfile)
716 fclose(fp);
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000717 }
718
Daniel Stenberg980a47b2002-05-07 09:58:13 +0000719 c->running = TRUE; /* now, we're running */
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000720
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000721 return c;
722}
723
724/*****************************************************************************
725 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000726 * Curl_cookie_getlist()
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000727 *
728 * For a given host and path, return a linked list of cookies that the
729 * client should send to the server if used now. The secure boolean informs
730 * the cookie if a secure connection is achieved or not.
731 *
732 * It shall only return cookies that haven't expired.
733 *
734 ****************************************************************************/
735
Daniel Stenberg40311042001-01-05 10:11:41 +0000736struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
737 char *host, char *path, bool secure)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000738{
Daniel Stenberg606562a2006-05-24 22:46:38 +0000739 struct Cookie *newco;
740 struct Cookie *co;
741 time_t now = time(NULL);
742 struct Cookie *mainco=NULL;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000743
Daniel Stenberg606562a2006-05-24 22:46:38 +0000744 if(!c || !c->cookies)
745 return NULL; /* no cookie struct or no cookies in the struct */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000746
Daniel Stenberg606562a2006-05-24 22:46:38 +0000747 co = c->cookies;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000748
Daniel Stenberg606562a2006-05-24 22:46:38 +0000749 while(co) {
750 /* only process this cookie if it is not expired or had no expire
751 date AND that if the cookie requires we're secure we must only
752 continue if we are! */
753 if( (co->expires<=0 || (co->expires> now)) &&
754 (co->secure?secure:TRUE) ) {
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000755
Daniel Stenberg606562a2006-05-24 22:46:38 +0000756 /* now check if the domain is correct */
757 if(!co->domain ||
758 (co->tailmatch && tailmatch(co->domain, host)) ||
759 (!co->tailmatch && strequal(host, co->domain)) ) {
760 /* the right part of the host matches the domain stuff in the
761 cookie data */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000762
Daniel Stenberg606562a2006-05-24 22:46:38 +0000763 /* now check the left part of the path with the cookies path
764 requirement */
765 if(!co->path ||
Daniel Stenberg28611702006-07-08 18:52:08 +0000766 /* not using checkprefix() because matching should be
767 case-sensitive */
768 !strncmp(co->path, path, strlen(co->path)) ) {
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000769
Daniel Stenberg606562a2006-05-24 22:46:38 +0000770 /* and now, we know this is a match and we should create an
771 entry for the return-linked-list */
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000772
Daniel Stenberg606562a2006-05-24 22:46:38 +0000773 newco = (struct Cookie *)malloc(sizeof(struct Cookie));
774 if(newco) {
775 /* first, copy the whole source cookie: */
776 memcpy(newco, co, sizeof(struct Cookie));
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000777
Daniel Stenberg606562a2006-05-24 22:46:38 +0000778 /* then modify our next */
779 newco->next = mainco;
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000780
Daniel Stenberg606562a2006-05-24 22:46:38 +0000781 /* point the main to us */
782 mainco = newco;
783 }
784 else {
785 /* failure, clear up the allocated chain and return NULL */
786 while(mainco) {
787 co = mainco->next;
788 free(mainco);
789 mainco = co;
790 }
Daniel Stenberg5dcab072004-05-10 14:04:06 +0000791
Daniel Stenberg606562a2006-05-24 22:46:38 +0000792 return NULL;
793 }
794 }
795 }
796 }
797 co = co->next;
798 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000799
Daniel Stenberg606562a2006-05-24 22:46:38 +0000800 return mainco; /* return the new list */
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000801}
802
Daniel Stenberg606562a2006-05-24 22:46:38 +0000803/*****************************************************************************
804 *
805 * Curl_cookie_clearall()
806 *
807 * Clear all existing cookies and reset the counter.
808 *
809 ****************************************************************************/
810void Curl_cookie_clearall(struct CookieInfo *cookies)
811{
Daniel Stenberg277df1c2007-01-13 23:32:14 +0000812 if(cookies) {
813 Curl_cookie_freelist(cookies->cookies);
814 cookies->cookies = NULL;
815 cookies->numcookies = 0;
816 }
Daniel Stenberg606562a2006-05-24 22:46:38 +0000817}
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000818
819/*****************************************************************************
820 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000821 * Curl_cookie_freelist()
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000822 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000823 * Free a list of cookies previously returned by Curl_cookie_getlist();
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000824 *
825 ****************************************************************************/
826
Daniel Stenberg40311042001-01-05 10:11:41 +0000827void Curl_cookie_freelist(struct Cookie *co)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000828{
Daniel Stenberg606562a2006-05-24 22:46:38 +0000829 struct Cookie *next;
830 if(co) {
831 while(co) {
832 next = co->next;
833 free(co); /* we only free the struct since the "members" are all
Daniel Stenberg39af3942004-10-06 07:50:18 +0000834 just copied! */
Daniel Stenberg606562a2006-05-24 22:46:38 +0000835 co = next;
836 }
837 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000838}
839
Daniel Stenberg606562a2006-05-24 22:46:38 +0000840
841/*****************************************************************************
842 *
843 * Curl_cookie_clearsess()
844 *
845 * Free all session cookies in the cookies list.
846 *
847 ****************************************************************************/
848void Curl_cookie_clearsess(struct CookieInfo *cookies)
849{
850 struct Cookie *first, *curr, *next, *prev = NULL;
851
852 if(!cookies->cookies)
853 return;
854
855 first = curr = prev = cookies->cookies;
856
857 for(; curr; curr = next) {
858 next = curr->next;
859 if(!curr->expires) {
860 if(first == curr)
861 first = next;
862
863 if(prev == curr)
864 prev = next;
865 else
866 prev->next = next;
867
868 free(curr);
869 cookies->numcookies--;
870 }
871 else
872 prev = curr;
873 }
874
875 cookies->cookies = first;
876}
877
878
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000879/*****************************************************************************
880 *
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000881 * Curl_cookie_cleanup()
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000882 *
883 * Free a "cookie object" previous created with cookie_init().
884 *
885 ****************************************************************************/
Daniel Stenberg40311042001-01-05 10:11:41 +0000886void Curl_cookie_cleanup(struct CookieInfo *c)
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000887{
Daniel Stenberg606562a2006-05-24 22:46:38 +0000888 struct Cookie *co;
889 struct Cookie *next;
890 if(c) {
891 if(c->filename)
892 free(c->filename);
893 co = c->cookies;
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000894
Daniel Stenberg606562a2006-05-24 22:46:38 +0000895 while(co) {
896 next = co->next;
897 freecookie(co);
898 co = next;
899 }
900 free(c); /* free the base struct as well */
901 }
Daniel Stenbergae1912c1999-12-29 14:20:26 +0000902}
903
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000904/* get_netscape_format()
905 *
906 * Formats a string for Netscape output file, w/o a newline at the end.
907 *
908 * Function returns a char * to a formatted line. Has to be free()d
909*/
910static char *get_netscape_format(const struct Cookie *co)
911{
Daniel Stenberg606562a2006-05-24 22:46:38 +0000912 return aprintf(
913 "%s%s\t" /* domain */
914 "%s\t" /* tailmatch */
915 "%s\t" /* path */
916 "%s\t" /* secure */
917 "%" FORMAT_OFF_T "\t" /* expires */
918 "%s\t" /* name */
919 "%s", /* value */
920 /* Make sure all domains are prefixed with a dot if they allow
921 tailmatching. This is Mozilla-style. */
922 (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
923 co->domain?co->domain:"unknown",
924 co->tailmatch?"TRUE":"FALSE",
925 co->path?co->path:"/",
926 co->secure?"TRUE":"FALSE",
927 co->expires,
928 co->name,
929 co->value?co->value:"");
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000930}
931
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000932/*
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000933 * Curl_cookie_output()
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000934 *
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000935 * Writes all internally known cookies to the specified file. Specify
936 * "-" as file name to write to stdout.
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000937 *
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000938 * The function returns non-zero on write failure.
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000939 */
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000940int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000941{
942 struct Cookie *co;
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000943 FILE *out;
944 bool use_stdout=FALSE;
945
Daniel Stenberg3f5227d2001-09-10 07:43:08 +0000946 if((NULL == c) || (0 == c->numcookies))
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000947 /* If there are no known cookies, we don't write or even create any
948 destination file */
949 return 0;
950
951 if(strequal("-", dumphere)) {
952 /* use stdout */
953 out = stdout;
954 use_stdout=TRUE;
955 }
956 else {
957 out = fopen(dumphere, "w");
958 if(!out)
959 return 1; /* failure */
960 }
961
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000962 if(c) {
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000963 char *format_ptr;
964
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000965 fputs("# Netscape HTTP Cookie File\n"
Daniel Stenberg68e9f752006-09-27 21:00:45 +0000966 "# http://curlm.haxx.se/rfc/cookie_spec.html\n"
Daniel Stenberge719f412001-10-08 06:43:22 +0000967 "# This file was generated by libcurl! Edit at your own risk.\n\n",
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000968 out);
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000969 co = c->cookies;
Daniel Stenberg34e8baa2004-05-12 12:04:38 +0000970
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000971 while(co) {
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000972 format_ptr = get_netscape_format(co);
973 if (format_ptr == NULL) {
974 fprintf(out, "#\n# Fatal libcurl error\n");
Dan Fandrich7e743492007-04-04 22:49:12 +0000975 fclose(out);
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000976 return 1;
977 }
978 fprintf(out, "%s\n", format_ptr);
979 free(format_ptr);
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000980 co=co->next;
981 }
982 }
Daniel Stenberga2b6ef32001-08-29 09:32:18 +0000983
984 if(!use_stdout)
985 fclose(out);
986
987 return 0;
Daniel Stenbergc9c21152001-08-23 14:05:25 +0000988}
989
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000990struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
991{
Daniel Stenberg1c388a52005-07-28 21:49:58 +0000992 struct curl_slist *list = NULL;
993 struct curl_slist *beg;
994 struct Cookie *c;
995 char *line;
Daniel Stenberg2236ba02005-07-27 22:17:14 +0000996
Daniel Stenberg1c388a52005-07-28 21:49:58 +0000997 if ((data->cookies == NULL) ||
998 (data->cookies->numcookies == 0))
999 return NULL;
Daniel Stenberg2236ba02005-07-27 22:17:14 +00001000
Daniel Stenberg1c388a52005-07-28 21:49:58 +00001001 c = data->cookies->cookies;
Daniel Stenberg2236ba02005-07-27 22:17:14 +00001002
Daniel Stenberg1c388a52005-07-28 21:49:58 +00001003 beg = list;
1004 while (c) {
1005 /* fill the list with _all_ the cookies we know */
1006 line = get_netscape_format(c);
1007 if (line == NULL) {
Yang Tsed9e89e12007-04-07 04:51:35 +00001008 curl_slist_free_all(beg);
Daniel Stenberg1c388a52005-07-28 21:49:58 +00001009 return NULL;
1010 }
1011 list = curl_slist_append(list, line);
1012 free(line);
Yang Tsed9e89e12007-04-07 04:51:35 +00001013 if (list == NULL) {
1014 curl_slist_free_all(beg);
1015 return NULL;
1016 }
1017 else if (beg == NULL) {
1018 beg = list;
1019 }
Daniel Stenberg1c388a52005-07-28 21:49:58 +00001020 c = c->next;
1021 }
Daniel Stenberg2236ba02005-07-27 22:17:14 +00001022
Daniel Stenberg1c388a52005-07-28 21:49:58 +00001023 return list;
Daniel Stenberg2236ba02005-07-27 22:17:14 +00001024}
1025
Daniel Stenbergac269a82004-12-05 23:59:32 +00001026#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */