]> granicus.if.org Git - curl/commitdiff
- As was pointed out on the http-state mailing list, the order of cookies in a
authorDaniel Stenberg <daniel@haxx.se>
Tue, 19 Jan 2010 23:19:59 +0000 (23:19 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 19 Jan 2010 23:19:59 +0000 (23:19 +0000)
  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.

CHANGES
RELEASE-NOTES
lib/cookie.c
tests/data/test8

diff --git a/CHANGES b/CHANGES
index 79ab4f630d02f40f5f1f6d4c27b50864f948d6d6..c8dfd118057c9e8a6e2e97bbb7b904a4e69ba007 100644 (file)
--- 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
index 37b314c1eaedc24b45bff286da42a490fa530f25..e4abf5fa408e2bc9730c08eec9b39137917b6991 100644 (file)
@@ -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:
 
index 7be8fc3c597d30e6811c96dd2d26143df42f5400..3a3edd51695e1fc8c6972e66a777d1950062bd3a 100644 (file)
@@ -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 */
 }
 
index 6131894fd687cd8b4daf672a75cfd363707fc9ab..15e643b66b152f5511de1facd95bd6ee2596a184 100644 (file)
@@ -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\r
 Host: %HOSTIP:%HTTPPORT\r
 Accept: */*\r
-Cookie: blexp=yesyes; cookie=yes; partmatch=present; foobar=name\r
+Cookie: cookie=yes; partmatch=present; foobar=name; blexp=yesyes\r
 \r
 </protocol>
 </verify>