[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wget
Subject:    cookies in wget...
From:       mbuf <mbuf () null ! xs4all ! nl>
Date:       1997-10-22 20:55:16
[Download RAW message or body]

Phew,

Due to inspiration, i have completed a bit of work on wget. The following patch
will implement a bit of cookies for wget. It is in no way finished.

First of all, privacy is not yet garantueed. Cookies are sent to every site (e.g., \
domain checking is not implemented yet; it's in there already, just a few lines to \
add - which i will do). So generally, when you are using this version within one \
site, it will work.

this version is going towards rfc 2109, and thus is netscape cookies \
compatible.again, it is no way near complete.

i have no idea what the normal procedure is to get (more final and debugged code :)) \
into the official wget distribution. Hrvoje?

Anyway, quite beta, here it is (my first work): (this version should apply neatly to \
1.4.5).

And eh, the debug statements are still in the code ;) 
(PS: Are these kinds of postings permitted to the list?).

my todo list:
  - maybe save cookies? (and/or share with lynx' cookie list)
  - implement domain matching (just seek the XXX and insert the strcmp)
  - debug, test, and make certain it meets RFC 2109 specifications
  - implement (maybe, very maybe) expiring cookies (due to time / memory \
                constraints).
  - more comments, move stuff to the right place, as hrvoje probably wants it :)

I hope i have the time to implement these last features (at least the rfc 2109 \
specs).

diff -N -d src/Makefile src-cookies/Makefile
40c40
< CFLAGS   =  -O2 -Wall -Wno-switch -Wno-implicit
---
> CFLAGS   =  -Wall -Wno-switch -Wno-implicit -g
55c55
<       getopt.c main.c version.c
---
> getopt.c main.c version.c cookie.c
58c58
<       getopt.o main$o version$o
---
> getopt.o main$o version$o cookie$o
diff -N -d src/cookie.c src-cookies/cookie.c
0a1,260
> /* Cookie management.
> Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
> 
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
> 
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> GNU General Public License for more details.
> 
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
> 
> 
> #ifdef HAVE_CONFIG_H
> #  include <config.h>
> #endif /* HAVE_CONFIG_H */
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/types.h>
> #ifdef HAVE_UNISTD_H
> #  include <unistd.h>
> #endif /* HAVE_UNISTD_H */
> #include <errno.h>
> #ifdef HAVE_STRING_H
> #  include <string.h>
> #else
> #  include <strings.h>
> #endif /* HAVE_STRING_H */
> #include <ctype.h>
> #include <assert.h>
> #include "cookie.h"
> 
> /* global variables */
> struct cookie *cookies = NULL;
> 
> /* macro to dup & alloc a string if defined, or return NULL if undefined */
> #define safestrdup(s) (char *) (s?nstrdup(s):NULL)
> 
> /* cookiesortkey - returns 0 if c2 is lower in sort than c1, any other value
> otherwise */
> #define cs(c1, c2) (strlen(c1->path) > strlen(c2->path))
> 
> /* cookiekey - returns 0 if the key doesn't match, any other value otherwise */
> #define ck(c1, domain, path, name) ((strcasecmp(c1->domain, domain)==0) && \
> (strcasecmp(c1->path, path)==0) && (strcasecmp(c1->name, name)==0)) 
> struct cookie *find_cookie(const char *name, const char *path, const char *domain)
> {
> struct cookie *temp = cookies;
> while (temp) {
> if (ck(temp, domain, path, name)) return temp;
> temp = temp->next;
> }
> return NULL;
> }
> 
> void
> cookie_purge(struct cookie *cookie)
> {
> free(cookie->name);
> if (cookie->value) free(cookie->value);
> if (cookie->comment) free(cookie->comment);
> free(cookie->domain);
> free(cookie->path);
> free(cookie);
> }
> 
> void 
> cookie_remove(const char *name, const char *domain, const char *path)
> {
> if (cookies) {
> if (ck(cookies, domain, path, name)) {
> struct cookie *temp = cookies;
> cookies = cookies->next;
> cookie_purge(temp);
> } else {
> struct cookie *temp = cookies;
> while ((temp->next) && (!ck(temp->next, domain, path, name))) temp = temp->next;
> if (!temp->next) {
> struct cookie *temp2 = temp->next;
> temp->next = temp->next->next;
> cookie_purge(temp2);
> }
> }
> }
> }
> 
> 
> void
> insertcookie(struct cookie *newcookie)
> {
> /* sort on length of paths, since "stronger" paths should be sent to the
> server first; */
> 
> if (!cookies)
> cookies = newcookie; 
> else if (cs(newcookie, cookies)) {
> newcookie->next = cookies;
> cookies = newcookie;
> } else if (!cookies->next)
> cookies->next = newcookie;
> else {
> struct cookie *tempcookie = cookies;
> while ((tempcookie->next->next) && cs(tempcookie->next, newcookie)) tempcookie = \
> tempcookie->next; if (!cs(tempcookie->next, newcookie)) {
> newcookie->next = tempcookie->next;
> tempcookie->next = newcookie;
> } else {
> tempcookie->next->next = newcookie;
> }
> }
> }
> 
> int countembeddeddots(const char *start, const char *end)
> {
> int dots = 0;
> 
> while ((end!=start) && (*end=='.')) end--;
> while (*start=='.') start++;
> 
> while (end > start) {
> if (*start =='.') dots++;
> start++;
> }
> return dots;
> }
> 
> int cookie_reject_path(const char *urlpath, const char *path) 
> {
> if (!path)
> return 0;
> 
> /* RFC 2109: The value for the Path attribute is not a prefix of the request-URI */
> path++;
> if (strncmp(path, urlpath, strlen(path))!=0)
> return 1;
> 
> return 0;
> }
> 
> /* returns 0 if the cookie should be accepted, any other value otherwise */
> int cookie_reject_domain(const char *urlhost, const char *domain)
> {
> const char *urlhostend, *domainend;
> 
> /* rfc 2109: The value for the Domain attribute starts with a dot */
> if (*domain!='.')
> return 1;
> urlhostend = urlhost;
> while (*urlhostend) urlhostend++;
> while (*domainend) domainend++;
> 
> /* RFC 2109: At least ONE embedded dot in domain */
> if (countembeddeddots(domain, domainend)==0)
> return 1;
> 
> while ((urlhostend!=urlhost) && (domainend!=domain)) {
> /* RFC 2109: domain should fully match host */
> if (*urlhostend != *domainend)
> return 1;
> urlhostend--; domainend--;
> }
> 
> /* RFC 2109: domain should fully match host */
> if (*urlhostend)
> return 1;
> 
> /* RFC 2109: Host part should have NO embedded dots */
> if (countembeddeddots(urlhost, urlhostend)>0)
> return 1;
> 
> return 0;
> }
> 
> /* Adds a cookie from the server to the cookie database. */
> void
> cookie_add(const char *name, const char *value, const char *comment, const char \
> *domain, const int max_age, const char *path, const int secure, const int version, \
> const int pathspecified) {
> struct cookie *newcookie;
> 
> printf("Adding cookie %s=%s; Path=%s%s; Domain=%s\n", name, value, path, \
> pathspecified?" (Specified)":"", domain); 
> newcookie = find_cookie(domain, path, name);
> if (!newcookie) {
> newcookie = (struct cookie *) nmalloc (sizeof(struct cookie));
> newcookie->name = safestrdup(name);
> newcookie->domain = safestrdup(domain);
> newcookie->path = safestrdup(path);
> newcookie->next = NULL;
> insertcookie(newcookie);
> } else {
> free(newcookie->value);
> free(newcookie->comment);
> }
> newcookie->value = safestrdup(value);
> newcookie->comment = safestrdup(comment);
> newcookie->max_age = max_age;
> newcookie->secure = secure;
> newcookie->version = version;
> newcookie->pathspecified = pathspecified;
> }
> 
> char *
> bake_cookie(const char *host, const char *path)
> {
> char *str;
> int len;
> struct cookie *cookie = cookies;
> str = NULL;
> len = 0;
> 
> while (cookie) {
> printf("Checking cookie (cookiepath: %s, real path: %s)\n", cookie->path, path);
> if (strncmp(&cookie->path[1], path, strlen(cookie->path-1))==0) {
> char *tmpstr;
> int tmplen;
> char *cookiepath, *cookiedomain;
> 
> printf("Sending cookie %s (%s/%s)=%s\n", cookie->name, cookie->path, \
> cookie->domain, cookie->value); 
> if (cookie->pathspecified) {
> cookiepath = (char *) nmalloc(7 + strlen(cookie->path));
> sprintf(cookiepath, "$Path=%s", cookie->path);
> } else cookiepath = NULL;
> 
> tmplen = len + 
> 7 + 1
> + 9 + (cookie->version/10) +
> + 1 + strlen(cookie->name) + 1 + strlen(cookie->value) + 1
> + cookiepath ? 1 + strlen(cookie->path) : 0
> + cookiedomain ? 1 + strlen(cookiedomain)  : 0
> + 2;
> 
> /* domain stuff, XXX */
> tmpstr = (char *) nmalloc(tmplen);
> sprintf(tmpstr, "%sCookie: $Version=%d;%s=%s%s%s%s%s\r\n",
> str?str:"",
> cookie->version,
> cookie->name,
> cookie->value,
> cookiepath?";":"",
> cookiepath?cookiepath:"",
> cookiedomain?";":"",
> cookiedomain?cookiedomain:"");
> free(str);
> str = tmpstr;
> len = tmplen;
> }
> cookie = cookie->next;
> } 
> 
> printf("Cookie that will be sent: %s\n", str?str:"");
> 
> return str;
> }
diff -N -d src/cookie.h src-cookies/cookie.h
0a1,48
> /* Declarations for cookie management.
> Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
> 
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
> 
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> GNU General Public License for more details.
> 
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
> 
> 
> 
> #ifndef COOKIE_H
> #define COOKIE_H
> 
> struct cookie {
> char *name;
> char *value;
> char *comment;
> char *domain;
> int max_age;
> char *path;
> int secure;
> int version;
> int pathspecified;
> struct cookie *next;
> };
> 
> void
> cookie_add(const char *name, const char *value, const char *comment, const char \
> *domain, const int max_age, const char *path, const int secure, const int version, \
> const int pathspecified); 
> int 
> cookie_reject_path(const char *urlpath, const char *path);
> 
> int
> cookie_reject_path(const char *urlhost, const char *domain);
> 
> char *
> bake_cookie(const char *host, const char *path);
> 
> #endif /* COOKIE_H */
diff -N -d src/http.c src-cookies/http.c
52a53
> #include "cookie.h"
243a245,328
> int hgetcookieav(char **hdr, char **name, char **value)
> {
> while ((**hdr) && (**hdr==' ')) (*hdr)++;
> *name = *hdr;
> *value = NULL;
> while ((**hdr) && (**hdr!='=') && (**hdr!=';')) (*hdr)++;
> if (**hdr==';') {
> **hdr=0;
> (*hdr)++;
> return 1;
> }
> if (!**hdr)
> return 0;
> **hdr=0;
> (*hdr)++;
> *value = *hdr;
> while ((**hdr) && (**hdr!=';')) (*hdr)++;
> if (**hdr==';') {
> **hdr=0;
> (*hdr)++;
> return 1;
> }
> return 0;
> }
> 
> /* Checks the current header for a chookie, and if set, adds it to 
> the cookie database. */
> void
> hgetcookie(const char *hdr, urlinfo *u)
> {
> static const int l = 11;           /* strlen("Set-Cookie:") */
> char *name, *value, *comment, *domain, *path;
> char *tmpname, *tmpvalue;
> int secure, cont, max_age, version, pathspecified;
> char *tmphdr_start, *tmphdr, *tmppath;
> 
> name = value = domain = path = comment = NULL;
> cont = 0;
> tmppath = NULL;
> pathspecified = 0;
> 
> /* Defaults according to RFC 2109 */
> version = 0;
> max_age = -1; /* end of session */
> secure = 0;
> version = 0;
> path = u->dir;
> 
> if (strncasecmp(hdr, SETCOOKIE_H, l))
> return;
> hdr += (l + hskip_lws(hdr + l));
> if (!*hdr)
> return;
> tmphdr_start = tmphdr = strdup(hdr);
> cont = hgetcookieav(&tmphdr, &name, &value);
> while (cont) {
> cont = hgetcookieav(&tmphdr, &tmpname, &tmpvalue);
> if (tmpvalue) {
> if (!strncasecmp(tmpname, "Comment", 7)) comment = tmpvalue; else
> if (!strncasecmp(tmpname, "Domain", 6)) domain = tmpvalue; else
> if (!strncasecmp(tmpname, "Max-Age", 7)) max_age = atoi(tmpvalue); else
> if (!strncasecmp(tmpname, "Path", 4)) {
> path = tmpvalue;
> pathspecified = 1;
> } else if (!strncasecmp(tmpname, "Version", 7)) version = atoi(tmpvalue);
> } else if (!strncasecmp(tmpname, "Secure", 6)) secure = 1;
> }
> 
> if ((!domain) || (!cookie_reject_domain(u->host, domain))) {
> if ((!pathspecified) || (!cookie_reject_path(u->dir, path))) {
> if (!domain) domain = u->host;
> if (max_age==0)
> cookie_remove(domain, path, name);
> else
> cookie_add(name, value, comment, domain, max_age, path, secure, version, \
> pathspecified); } else
> printf("Cookie rejected due to security or privacy violations. Requested cookie \
> path (%s) did not meet RFC 2109 specifications (%s)\n", path, u->dir); } else 
> printf("Cookie rejected due to security or privacy violations. Request cookie \
> domain (%s) did not meet RFC 2109 specifications\n", domain); 
> if (tmppath) free(tmppath);
> free(tmphdr_start);
> }
> 
323a409
> char *setcookie;
424a511,512
> /* Send out a cookie for the site, if present. */
> setcookie = bake_cookie(u->host, u->dir);
472a561
> 			     + (setcookie ? strlen(setcookie) : 0)
478c567
<    sprintf(request, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s:%d\r\nAccept: \
                %s\r\n%s%s%s%s%s%s\r\n",
---
> sprintf(request, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s:%d\r\nAccept: \
> %s\r\n%s%s%s%s%s%s%s\r\n",
482a572
> 	   setcookie ? setcookie : "",
623a714,715
> /* Check whether the server issued a cookie */
> hgetcookie(hdr, u);
diff -N -d src/http.h src-cookies/http.h
30a31
> #define SETCOOKIE_H "Set-Cookie:"


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic