diff options
author | Daniel Stenberg <daniel@haxx.se> | 2010-01-19 23:19:59 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2010-01-19 23:19:59 +0000 |
commit | 877dad1e24876030a7dd8738648f0f0245b6331a (patch) | |
tree | b82c0d879adcc4a7aef27c2a13e2c094ccab7118 | |
parent | 01030e9240e112b55cad1d5413823fb21d521265 (diff) |
- As was pointed out on the http-state mailing list, the order of cookies in a
HTTP Cookie: header _needs_ to be sorted on the path length in the cases
where two cookies using the same name are set more than once using
(overlapping) paths. Realizing this, identically named cookies must be
sorted correctly. But detecting only identically named cookies and take care
of them individually is harder than just to blindly and unconditionally sort
all cookies based on their path lengths. All major browsers also already do
this, so this makes our behavior one step closer to them in the cookie area.
Test case 8 was the only one that broke due to this change and I updated it
accordingly.
-rw-r--r-- | CHANGES | 13 | ||||
-rw-r--r-- | RELEASE-NOTES | 1 | ||||
-rw-r--r-- | lib/cookie.c | 48 | ||||
-rw-r--r-- | tests/data/test8 | 2 |
4 files changed, 62 insertions, 2 deletions
@@ -6,6 +6,19 @@ Changelog +Daniel Stenberg (20 Jan 2010) +- As was pointed out on the http-state mailing list, the order of cookies in a + HTTP Cookie: header _needs_ to be sorted on the path length in the cases + where two cookies using the same name are set more than once using + (overlapping) paths. Realizing this, identically named cookies must be + sorted correctly. But detecting only identically named cookies and take care + of them individually is harder than just to blindly and unconditionally sort + all cookies based on their path lengths. All major browsers also already do + this, so this makes our behavior one step closer to them in the cookie area. + + Test case 8 was the only one that broke due to this change and I updated it + accordingly. + Daniel Stenberg (19 Jan 2010) - David McCreedy brought a fix and a new test case (129) to make libcurl work again when downloading files over FTP using ASCII and it turns out that the diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 37b314c1e..e4abf5fa4 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -46,6 +46,7 @@ This release includes the following bugfixes: o progress callback called repeatedly during slow connects o curl_multi_fdset() would return -1 too often during SCP/SFTP transfers o FTP file size checks with ASCII transfers + o HTTP Cookie: headers sort cookies based on specified path lengths This release includes the following known bugs: diff --git a/lib/cookie.c b/lib/cookie.c index 7be8fc3c5..3a3edd516 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -774,6 +774,18 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, return c; } +/* sort this so that the longest path gets before the shorter path */ +static int cookie_sort(const void *p1, const void *p2) +{ + struct Cookie *c1 = *(struct Cookie **)p1; + struct Cookie *c2 = *(struct Cookie **)p2; + + size_t l1 = c1->path?strlen(c1->path):0; + size_t l2 = c2->path?strlen(c2->path):0; + + return l2 - l1; +} + /***************************************************************************** * * Curl_cookie_getlist() @@ -794,6 +806,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, struct Cookie *co; time_t now = time(NULL); struct Cookie *mainco=NULL; + int matches=0; if(!c || !c->cookies) return NULL; /* no cookie struct or no cookies in the struct */ @@ -834,8 +847,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, /* point the main to us */ mainco = newco; + + matches++; } else { + fail: /* failure, clear up the allocated chain and return NULL */ while(mainco) { co = mainco->next; @@ -851,6 +867,36 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, co = co->next; } + if(matches) { + /* Now we need to make sure that if there is a name appearing more than + once, the longest specified path version comes first. To make this + the swiftest way, we just sort them all based on path length. */ + struct Cookie **array; + int i; + + /* alloc an array and store all cookie pointers */ + array = (struct Cookie **)malloc(sizeof(struct Cookie *) * matches); + if(!array) + goto fail; + + co = mainco; + + for(i=0; co; co = co->next) + array[i++] = co; + + /* now sort the cookie pointers in path lenth order */ + qsort(array, matches, sizeof(struct Cookie *), cookie_sort); + + /* remake the linked list order according to the new order */ + + mainco = array[0]; /* start here */ + for(i=0; i<matches-1; i++) + array[i]->next = array[i+1]; + array[matches-1]->next = NULL; /* terminate the list */ + + free(array); /* remove the temporary data again */ + } + return mainco; /* return the new list */ } diff --git a/tests/data/test8 b/tests/data/test8 index 6131894fd..15e643b66 100644 --- a/tests/data/test8 +++ b/tests/data/test8 @@ -55,7 +55,7 @@ Set-Cookie: blexp=yesyes; domain=.0.0.1; domain=.0.0.1; expiry=totally bad; GET /we/want/8 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Cookie: blexp=yesyes; cookie=yes; partmatch=present; foobar=name
+Cookie: cookie=yes; partmatch=present; foobar=name; blexp=yesyes
</protocol> </verify> |