aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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>