started working on a function for writing (all) cookies, made it possible

to read multiple cookie files, no longer writes to the URL string passed
to the _add() function. The new stuff is now conditionally compiled on the
COOKIE define. Changed the _init() proto.
This commit is contained in:
Daniel Stenberg 2001-08-23 14:05:25 +00:00
parent d73d28a75b
commit c9c2115088
2 changed files with 147 additions and 38 deletions

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* In order to be useful for every potential user, curl and libcurl are * In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses. * dual-licensed under the MPL and the MIT/X-derivate licenses.
@ -95,7 +95,7 @@ Example set of cookies:
/**************************************************************************** /****************************************************************************
* *
* cookie_add() * Curl_cookie_add()
* *
* Add a single cookie line to the cookie keeping object. * Add a single cookie line to the cookie keeping object.
* *
@ -112,6 +112,7 @@ Curl_cookie_add(struct CookieInfo *c,
char *ptr; char *ptr;
char *semiptr; char *semiptr;
struct Cookie *co; struct Cookie *co;
struct Cookie *lastc=NULL;
time_t now = time(NULL); time_t now = time(NULL);
bool replace_old = FALSE; bool replace_old = FALSE;
@ -129,13 +130,11 @@ Curl_cookie_add(struct CookieInfo *c,
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
ptr = lineptr; ptr = lineptr;
do { do {
if(semiptr)
*semiptr='\0'; /* zero terminate for a while */
/* we have a <what>=<this> pair or a 'secure' word here */ /* we have a <what>=<this> pair or a 'secure' word here */
if(strchr(ptr, '=')) { if(strchr(ptr, '=')) {
name[0]=what[0]=0; /* init the buffers */ name[0]=what[0]=0; /* init the buffers */
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^=]=%" if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^=]=%"
MAX_COOKIE_LINE_TXT "[^\r\n]", MAX_COOKIE_LINE_TXT "[^;\r\n]",
name, what)) { name, what)) {
/* this is a legal <what>=<this> pair */ /* this is a legal <what>=<this> pair */
if(strequal("path", name)) { if(strequal("path", name)) {
@ -178,7 +177,7 @@ Curl_cookie_add(struct CookieInfo *c,
} }
} }
else { else {
if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^\r\n]", if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
what)) { what)) {
if(strequal("secure", what)) if(strequal("secure", what))
co->secure = TRUE; co->secure = TRUE;
@ -190,7 +189,6 @@ Curl_cookie_add(struct CookieInfo *c,
if(!semiptr) if(!semiptr)
continue; /* we already know there are no more cookies */ continue; /* we already know there are no more cookies */
*semiptr=';'; /* put the semicolon back */
ptr=semiptr+1; ptr=semiptr+1;
while(ptr && *ptr && isspace((int)*ptr)) while(ptr && *ptr && isspace((int)*ptr))
ptr++; ptr++;
@ -245,6 +243,7 @@ Curl_cookie_add(struct CookieInfo *c,
We don't currently take advantage of this knowledge. We don't currently take advantage of this knowledge.
*/ */
co->field1=strequal(ptr, "TRUE")+1; /* store information */
break; break;
case 2: case 2:
/* It turns out, that sometimes the file format allows the path /* It turns out, that sometimes the file format allows the path
@ -293,6 +292,8 @@ Curl_cookie_add(struct CookieInfo *c,
} }
co->livecookie = c->running;
/* now, we have parsed the incoming line, we must now check if this /* now, we have parsed the incoming line, we must now check if this
superceeds an already existing cookie, which it may if the previous have superceeds an already existing cookie, which it may if the previous have
the same domain and path as this */ the same domain and path as this */
@ -327,6 +328,26 @@ Curl_cookie_add(struct CookieInfo *c,
} }
if(replace_old && !co->livecookie && clist->livecookie) {
/* Both cookies matched fine, except that the already present
cookie is "live", which means it was set from a header, while
the new one isn't "live" and thus only read from a file. We let
live cookies stay alive */
/* Free the newcomer and get out of here! */
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
return NULL;
}
if(replace_old) { if(replace_old) {
co->next = clist->next; /* get the next-pointer first */ co->next = clist->next; /* get the next-pointer first */
@ -351,39 +372,49 @@ Curl_cookie_add(struct CookieInfo *c,
} }
} }
lastc = clist;
clist = clist->next; clist = clist->next;
} }
if(!replace_old) { if(!replace_old) {
/* then make the last item point on this new one */
/* first, point to our "next" */ if(lastc)
co->next = c->cookies; lastc->next = co;
/* then make ourselves first in the list */ else
c->cookies = co; c->cookies = co;
} }
return co; return co;
} }
/***************************************************************************** /*****************************************************************************
* *
* cookie_init() * Curl_cookie_init()
* *
* Inits a cookie struct to read data from a local file. This is always * Inits a cookie struct to read data from a local file. This is always
* called before any cookies are set. File may be NULL. * called before any cookies are set. File may be NULL.
* *
****************************************************************************/ ****************************************************************************/
struct CookieInfo *Curl_cookie_init(char *file) struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc)
{ {
char line[MAX_COOKIE_LINE]; char line[MAX_COOKIE_LINE];
struct CookieInfo *c; struct CookieInfo *c;
FILE *fp; FILE *fp;
bool fromfile=TRUE; bool fromfile=TRUE;
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo)); if(NULL == inc) {
if(!c) /* we didn't get a struct, create one */
return NULL; /* failed to get memory */ c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
memset(c, 0, sizeof(struct CookieInfo)); if(!c)
c->filename = strdup(file?file:"none"); /* copy the name just in case */ return NULL; /* failed to get memory */
memset(c, 0, sizeof(struct CookieInfo));
c->filename = strdup(file?file:"none"); /* copy the name just in case */
}
else {
/* we got an already existing one, use that */
c = inc;
}
c->running = FALSE; /* this is not running, this is init */
if(strequal(file, "-")) { if(strequal(file, "-")) {
fp = stdin; fp = stdin;
@ -393,34 +424,35 @@ struct CookieInfo *Curl_cookie_init(char *file)
fp = file?fopen(file, "r"):NULL; fp = file?fopen(file, "r"):NULL;
if(fp) { if(fp) {
char *lineptr;
bool headerline;
while(fgets(line, MAX_COOKIE_LINE, fp)) { while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(strnequal("Set-Cookie:", line, 11)) { if(strnequal("Set-Cookie:", line, 11)) {
/* This is a cookie line, get it! */ /* This is a cookie line, get it! */
char *lineptr=&line[11]; lineptr=&line[11];
while(*lineptr && isspace((int)*lineptr)) headerline=TRUE;
lineptr++;
Curl_cookie_add(c, TRUE, lineptr);
} }
else { else {
/* This might be a netscape cookie-file line, get it! */ lineptr=line;
char *lineptr=line; headerline=FALSE;
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(c, FALSE, lineptr);
} }
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(c, headerline, lineptr);
} }
if(fromfile) if(fromfile)
fclose(fp); fclose(fp);
} }
c->running = TRUE; /* now, we're running */
return c; return c;
} }
/***************************************************************************** /*****************************************************************************
* *
* cookie_getlist() * Curl_cookie_getlist()
* *
* For a given host and path, return a linked list of cookies that the * For a given host and path, return a linked list of cookies that the
* client should send to the server if used now. The secure boolean informs * client should send to the server if used now. The secure boolean informs
@ -492,9 +524,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/***************************************************************************** /*****************************************************************************
* *
* cookie_freelist() * Curl_cookie_freelist()
* *
* Free a list previously returned by cookie_getlist(); * Free a list of cookies previously returned by Curl_cookie_getlist();
* *
****************************************************************************/ ****************************************************************************/
@ -513,7 +545,7 @@ void Curl_cookie_freelist(struct Cookie *co)
/***************************************************************************** /*****************************************************************************
* *
* cookie_cleanup() * Curl_cookie_cleanup()
* *
* Free a "cookie object" previous created with cookie_init(). * Free a "cookie object" previous created with cookie_init().
* *
@ -552,3 +584,76 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
} }
} }
#ifdef COOKIE /* experiemental functions for the upcoming cookie jar stuff */
/*
* On my Solaris box, this command line builds this test program:
*
* gcc -g -o cooktest -DCOOKIE=1 -DHAVE_CONFIG_H -I.. -I../include cookie.c strequal.o getdate.o memdebug.o mprintf.o strtok.o -lnsl -lsocket
*
*/
void Curl_cookie_output(struct CookieInfo *c)
{
struct Cookie *co;
struct Cookie *next;
if(c) {
#if COOKIE > 1
if(c->filename)
printf("Got these cookies from: \"%s\"\n", c->filename);
#else
puts("# Netscape HTTP Cookie File\n"
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
"# This is generated by libcurl! Do not edit.\n");
#endif
co = c->cookies;
while(co) {
#if COOKIE > 1
printf("Name: %s\n", co->name?co->name:"");
printf(" Value: %s\n", co->value?co->value:"");
printf(" Domain: %s\n", co->domain?co->domain:"");
printf(" Path: %s\n", co->path?co->path:"");
printf(" Expire: %s\n", co->expirestr?co->expirestr:"");
printf(" Version: %s\n", co->version?co->version:"");
printf(" Max-Age: %s\n\n", co->maxage?co->maxage:"");
#endif
printf("%s\t" /* domain */
"%s\t" /* field1 */
"%s\t" /* path */
"%s\t" /* secure */
"%d\t" /* expires */
"%s\t" /* name */
"%s\n", /* value */
co->domain,
co->field1==2?"TRUE":"FALSE",
co->path,
co->secure?"TRUE":"FALSE",
co->expires,
co->name,
co->value);
co=co->next;
}
}
}
int main(int argc, char **argv)
{
struct CookieInfo *c=NULL;
if(argc>1) {
c = Curl_cookie_init(argv[1], c);
c = Curl_cookie_init(argv[1], c);
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_output(c);
Curl_cookie_cleanup(c);
return 0;
}
return 1;
}
#endif

View File

@ -40,19 +40,23 @@ struct Cookie {
char *domain; /* domain = <this> */ char *domain; /* domain = <this> */
time_t expires; /* expires = <this> */ time_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */ char *expirestr; /* the plain text version */
char field1; /* read from a cookie file, 1 => FALSE, 2=> TRUE */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */ char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */ char *maxage; /* Max-Age = <value> */
bool secure; /* whether the 'secure' keyword was used */ bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
}; };
struct CookieInfo { struct CookieInfo {
/* linked list of cookies we know of */ /* linked list of cookies we know of */
struct Cookie *cookies; struct Cookie *cookies;
char *filename; /* file we read from/write to */ char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
}; };
/* This is the maximum line length we accept for a cookie line */ /* This is the maximum line length we accept for a cookie line */
@ -64,7 +68,7 @@ struct CookieInfo {
#define MAX_NAME_TXT "255" #define MAX_NAME_TXT "255"
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool, char *); struct Cookie *Curl_cookie_add(struct CookieInfo *, bool, char *);
struct CookieInfo *Curl_cookie_init(char *); struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool); struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
void Curl_cookie_freelist(struct Cookie *); void Curl_cookie_freelist(struct Cookie *);
void Curl_cookie_cleanup(struct CookieInfo *); void Curl_cookie_cleanup(struct CookieInfo *);