summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/cookie.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/cookie.c')
-rw-r--r--Utilities/cmcurl/lib/cookie.c152
1 files changed, 92 insertions, 60 deletions
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 2c028b381..a342c61de 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -40,7 +40,7 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
received from a server.
The function need to replace previously stored lines that this new
- line superceeds.
+ line supersedes.
It may remove lines that are expired.
@@ -84,12 +84,9 @@ Example set of cookies:
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-#ifdef USE_LIBPSL
-# include <libpsl.h>
-#endif
-
#include "urldata.h"
#include "cookie.h"
+#include "psl.h"
#include "strtok.h"
#include "sendf.h"
#include "slist.h"
@@ -253,9 +250,9 @@ static const char *get_top_domain(const char * const domain, size_t *outlen)
len = strlen(domain);
last = memrchr(domain, '.', len);
if(last) {
- first = memrchr(domain, '.', (size_t) (last - domain));
+ first = memrchr(domain, '.', (last - domain));
if(first)
- len -= (size_t) (++first - domain);
+ len -= (++first - domain);
}
if(outlen)
@@ -379,13 +376,13 @@ static void strstore(char **str, const char *newstr)
*/
static void remove_expired(struct CookieInfo *cookies)
{
- struct Cookie *co, *nx, *pv;
+ struct Cookie *co, *nx;
curl_off_t now = (curl_off_t)time(NULL);
unsigned int i;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ struct Cookie *pv = NULL;
co = cookies->cookies[i];
- pv = NULL;
while(co) {
nx = co->next;
if(co->expires && co->expires < now) {
@@ -406,6 +403,12 @@ static void remove_expired(struct CookieInfo *cookies)
}
}
+/* Make sure domain contains a dot or is localhost. */
+static bool bad_domain(const char *domain)
+{
+ return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
+}
+
/****************************************************************************
*
* Curl_cookie_add()
@@ -442,10 +445,6 @@ Curl_cookie_add(struct Curl_easy *data,
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
size_t myhash;
-#ifdef USE_LIBPSL
- const psl_ctx_t *psl;
-#endif
-
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -497,7 +496,7 @@ Curl_cookie_add(struct Curl_easy *data,
name + contents. Chrome and Firefox support 4095 or 4096 bytes
combo. */
freecookie(co);
- infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+ infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
nlen, len);
return NULL;
}
@@ -585,13 +584,8 @@ Curl_cookie_add(struct Curl_easy *data,
* TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact host name being "localhost".
*/
- {
- const char *dotp;
- /* check for more dots */
- dotp = strchr(whatptr, '.');
- if(!dotp && !strcasecompare("localhost", whatptr))
- domain = ":";
- }
+ if(bad_domain(whatptr))
+ domain = ":";
#endif
is_ip = isip(domain ? domain : whatptr);
@@ -723,9 +717,9 @@ Curl_cookie_add(struct Curl_easy *data,
if(!queryp)
endslash = strrchr(path, '/');
else
- endslash = memrchr(path, '/', (size_t)(queryp - path));
+ endslash = memrchr(path, '/', (queryp - path));
if(endslash) {
- size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
+ size_t pathlen = (endslash-path + 1); /* include end slash */
co->path = malloc(pathlen + 1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
@@ -880,9 +874,10 @@ Curl_cookie_add(struct Curl_easy *data,
}
co->livecookie = c->running;
+ co->creationtime = ++c->lastct;
/* 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
+ supersedes an already existing cookie, which it may if the previous have
the same domain and path as this */
/* at first, remove expired cookies */
@@ -890,14 +885,21 @@ Curl_cookie_add(struct Curl_easy *data,
remove_expired(c);
#ifdef USE_LIBPSL
- /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
- This needs a libpsl compiled with builtin data. */
+ /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
if(domain && co->domain && !isip(co->domain)) {
- psl = psl_builtin();
- if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
- infof(data,
- "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
- co->name, domain, co->domain);
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ int acceptable;
+
+ if(psl) {
+ acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain);
+
+ if(!acceptable) {
+ infof(data, "cookie '%s' dropped, domain '%s' must not "
+ "set cookies for '%s'\n", co->name, domain, co->domain);
freecookie(co);
return NULL;
}
@@ -951,6 +953,9 @@ Curl_cookie_add(struct Curl_easy *data,
if(replace_old) {
co->next = clist->next; /* get the next-pointer first */
+ /* when replacing, creationtime is kept from old */
+ co->creationtime = clist->creationtime;
+
/* then free all the old pointers */
free(clist->name);
free(clist->value);
@@ -1140,12 +1145,24 @@ static int cookie_sort(const void *p1, const void *p2)
if(l1 != l2)
return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
- /* 3 - compare cookie names */
- if(c1->name && c2->name)
- return strcmp(c1->name, c2->name);
+ /* 3 - compare cookie name lengths */
+ l1 = c1->name ? strlen(c1->name) : 0;
+ l2 = c2->name ? strlen(c2->name) : 0;
- /* sorry, can't be more deterministic */
- return 0;
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1;
+
+ /* 4 - compare cookie creation time */
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
+}
+
+/* sort cookies only according to creation time */
+static int cookie_sort_ct(const void *p1, const void *p2)
+{
+ struct Cookie *c1 = *(struct Cookie **)p1;
+ struct Cookie *c2 = *(struct Cookie **)p2;
+
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
}
#define CLONE(field) \
@@ -1174,6 +1191,7 @@ static struct Cookie *dup_cookie(struct Cookie *src)
d->secure = src->secure;
d->livecookie = src->livecookie;
d->httponly = src->httponly;
+ d->creationtime = src->creationtime;
}
return d;
@@ -1200,7 +1218,6 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
{
struct Cookie *newco;
struct Cookie *co;
- time_t now = time(NULL);
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
@@ -1218,11 +1235,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
co = c->cookies[myhash];
while(co) {
- /* only process this cookie if it is not expired or had no expire
- date AND that if the cookie requires we're secure we must only
- continue if we are! */
- if((!co->expires || (co->expires > now)) &&
- (co->secure?secure:TRUE)) {
+ /* if the cookie requires we're secure we must only continue if we are! */
+ if(co->secure?secure:TRUE) {
/* now check if the domain is correct */
if(!co->domain ||
@@ -1248,12 +1262,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
matches++;
}
- else {
- fail:
- /* failure, clear up the allocated chain and return NULL */
- Curl_cookie_freelist(mainco);
- return NULL;
- }
+ else
+ goto fail;
}
}
}
@@ -1291,6 +1301,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
}
return mainco; /* return the new list */
+
+fail:
+ /* failure, clear up the allocated chain and return NULL */
+ Curl_cookie_freelist(mainco);
+ return NULL;
}
/*****************************************************************************
@@ -1384,9 +1399,8 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
- unsigned int i;
-
if(c) {
+ unsigned int i;
free(c->filename);
for(i = 0; i < COOKIE_HASH_SIZE; i++)
Curl_cookie_freelist(c->cookies[i]);
@@ -1439,6 +1453,8 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
bool use_stdout = FALSE;
char *format_ptr;
unsigned int i;
+ unsigned int j;
+ struct Cookie **array;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
@@ -1452,6 +1468,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
if(0 == c->numcookies)
return 0;
+ array = malloc(sizeof(struct Cookie *) * c->numcookies);
+ if(!array)
+ return 1;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
@@ -1459,8 +1479,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
}
else {
out = fopen(dumphere, FOPEN_WRITETEXT);
- if(!out)
+ if(!out) {
+ free(array);
return 1; /* failure */
+ }
}
fputs("# Netscape HTTP Cookie File\n"
@@ -1468,22 +1490,32 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
+ j = 0;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
for(co = c->cookies[i]; co; co = co->next) {
if(!co->domain)
continue;
- format_ptr = get_netscape_format(co);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- if(!use_stdout)
- fclose(out);
- return 1;
- }
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
+ array[j++] = co;
}
}
+ qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+
+ for(i = 0; i < j; i++) {
+ format_ptr = get_netscape_format(array[i]);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ free(array);
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ }
+
+ free(array);
+
if(!use_stdout)
fclose(out);