aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2010-01-19 23:19:59 +0000
committerDaniel Stenberg <daniel@haxx.se>2010-01-19 23:19:59 +0000
commit877dad1e24876030a7dd8738648f0f0245b6331a (patch)
treeb82c0d879adcc4a7aef27c2a13e2c094ccab7118
parent01030e9240e112b55cad1d5413823fb21d521265 (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--CHANGES13
-rw-r--r--RELEASE-NOTES1
-rw-r--r--lib/cookie.c48
-rw-r--r--tests/data/test82
4 files changed, 62 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 79ab4f630..c8dfd1180 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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>