717 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			717 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: cookie.c,v 1.11 2010/07/26 11:38:53 htrb Exp $ */
 | 
						|
 | 
						|
/*
 | 
						|
 * References for version 0 cookie:                                  
 | 
						|
 *   [NETACAPE] http://www.netscape.com/newsref/std/cookie_spec.html
 | 
						|
 *
 | 
						|
 * References for version 1 cookie:                                  
 | 
						|
 *   [RFC 2109] http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt
 | 
						|
 *   [DRAFT 12] http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-12.txt
 | 
						|
 */
 | 
						|
 | 
						|
#include "fm.h"
 | 
						|
#include "html.h"
 | 
						|
 | 
						|
#ifdef USE_COOKIE
 | 
						|
#include <time.h>
 | 
						|
#include "local.h"
 | 
						|
#include "regex.h"
 | 
						|
#include "myctype.h"
 | 
						|
 | 
						|
static int is_saved = 1;
 | 
						|
 | 
						|
#define contain_no_dots(p, ep) (total_dot_number((p),(ep),1)==0)
 | 
						|
 | 
						|
static unsigned int
 | 
						|
total_dot_number(char *p, char *ep, unsigned int max_count)
 | 
						|
{
 | 
						|
    unsigned int count = 0;
 | 
						|
    if (!ep)
 | 
						|
	ep = p + strlen(p);
 | 
						|
 | 
						|
    for (; p < ep && count < max_count; p++) {
 | 
						|
	if (*p == '.')
 | 
						|
	    count++;
 | 
						|
    }
 | 
						|
    return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static char *
 | 
						|
domain_match(char *host, char *domain)
 | 
						|
{
 | 
						|
    int m0, m1;
 | 
						|
 | 
						|
    /* [RFC 2109] s. 2, "domain-match", case 1
 | 
						|
     * (both are IP and identical)
 | 
						|
     */
 | 
						|
    regexCompile("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+", 0);
 | 
						|
    m0 = regexMatch(host, -1, 1);
 | 
						|
    m1 = regexMatch(domain, -1, 1);
 | 
						|
    if (m0 && m1) {
 | 
						|
	if (strcasecmp(host, domain) == 0)
 | 
						|
	    return host;
 | 
						|
    }
 | 
						|
    else if (!m0 && !m1) {
 | 
						|
	int offset;
 | 
						|
	char *domain_p;
 | 
						|
	/*
 | 
						|
	 * "." match all domains (w3m only),
 | 
						|
	 * and ".local" match local domains ([DRAFT 12] s. 2)
 | 
						|
	 */
 | 
						|
	if (strcasecmp(domain, ".") == 0 || strcasecmp(domain, ".local") == 0) {
 | 
						|
	    offset = strlen(host);
 | 
						|
	    domain_p = &host[offset];
 | 
						|
	    if (domain[1] == '\0' || contain_no_dots(host, domain_p))
 | 
						|
		return domain_p;
 | 
						|
	}
 | 
						|
	/*
 | 
						|
	 * special case for domainName = .hostName
 | 
						|
	 * see nsCookieService.cpp in Firefox.
 | 
						|
	 */
 | 
						|
	else if (domain[0] == '.' && strcasecmp(host, &domain[1]) == 0) {
 | 
						|
	    return host;
 | 
						|
	}
 | 
						|
	/* [RFC 2109] s. 2, cases 2, 3 */
 | 
						|
	else {
 | 
						|
	    offset = (domain[0] != '.') ? 0 : strlen(host) - strlen(domain);
 | 
						|
	    domain_p = &host[offset];
 | 
						|
	    if (offset >= 0 && strcasecmp(domain_p, domain) == 0)
 | 
						|
		return domain_p;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static struct portlist *
 | 
						|
make_portlist(Str port)
 | 
						|
{
 | 
						|
    struct portlist *first = NULL, *pl;
 | 
						|
    char *p;
 | 
						|
    Str tmp = Strnew();
 | 
						|
 | 
						|
    p = port->ptr;
 | 
						|
    while (*p) {
 | 
						|
	while (*p && !IS_DIGIT(*p))
 | 
						|
	    p++;
 | 
						|
	Strclear(tmp);
 | 
						|
	while (*p && IS_DIGIT(*p))
 | 
						|
	    Strcat_char(tmp, *(p++));
 | 
						|
	if (tmp->length == 0)
 | 
						|
	    break;
 | 
						|
	pl = New(struct portlist);
 | 
						|
	pl->port = atoi(tmp->ptr);
 | 
						|
	pl->next = first;
 | 
						|
	first = pl;
 | 
						|
    }
 | 
						|
    Strfree(tmp);
 | 
						|
    return first;
 | 
						|
}
 | 
						|
 | 
						|
static Str
 | 
						|
portlist2str(struct portlist *first)
 | 
						|
{
 | 
						|
    struct portlist *pl;
 | 
						|
    Str tmp;
 | 
						|
 | 
						|
    tmp = Sprintf("%d", first->port);
 | 
						|
    for (pl = first->next; pl; pl = pl->next)
 | 
						|
	Strcat(tmp, Sprintf(", %d", pl->port));
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
port_match(struct portlist *first, int port)
 | 
						|
{
 | 
						|
    struct portlist *pl;
 | 
						|
 | 
						|
    for (pl = first; pl; pl = pl->next) {
 | 
						|
	if (pl->port == port)
 | 
						|
	    return 1;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
check_expired_cookies(void)
 | 
						|
{
 | 
						|
    struct cookie *p, *p1;
 | 
						|
    time_t now = time(NULL);
 | 
						|
 | 
						|
    if (!First_cookie)
 | 
						|
	return;
 | 
						|
 | 
						|
    if (First_cookie->expires != (time_t) - 1 && First_cookie->expires < now) {
 | 
						|
	if (!(First_cookie->flag & COO_DISCARD))
 | 
						|
	    is_saved = 0;
 | 
						|
	First_cookie = First_cookie->next;
 | 
						|
    }
 | 
						|
 | 
						|
    for (p = First_cookie; p && p->next; p = p1) {
 | 
						|
	p1 = p->next;
 | 
						|
	if (p1->expires != (time_t) - 1 && p1->expires < now) {
 | 
						|
	    if (!(p1->flag & COO_DISCARD))
 | 
						|
		is_saved = 0;
 | 
						|
	    p->next = p1->next;
 | 
						|
	    p1 = p;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Str
 | 
						|
make_cookie(struct cookie *cookie)
 | 
						|
{
 | 
						|
    Str tmp = Strdup(cookie->name);
 | 
						|
    Strcat_char(tmp, '=');
 | 
						|
    Strcat(tmp, cookie->value);
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
match_cookie(ParsedURL *pu, struct cookie *cookie, char *domainname)
 | 
						|
{
 | 
						|
    if (!domainname)
 | 
						|
	return 0;
 | 
						|
 | 
						|
    if (!domain_match(domainname, cookie->domain->ptr))
 | 
						|
	return 0;
 | 
						|
    if (strncmp(cookie->path->ptr, pu->file, cookie->path->length) != 0)
 | 
						|
	return 0;
 | 
						|
#ifdef USE_SSL
 | 
						|
    if (cookie->flag & COO_SECURE && pu->scheme != SCM_HTTPS)
 | 
						|
	return 0;
 | 
						|
#else				/* not USE_SSL */
 | 
						|
    if (cookie->flag & COO_SECURE)
 | 
						|
	return 0;
 | 
						|
#endif				/* not USE_SSL */
 | 
						|
    if (cookie->portl && !port_match(cookie->portl, pu->port))
 | 
						|
	return 0;
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
struct cookie *
 | 
						|
get_cookie_info(Str domain, Str path, Str name)
 | 
						|
{
 | 
						|
    struct cookie *p;
 | 
						|
 | 
						|
    for (p = First_cookie; p; p = p->next) {
 | 
						|
	if (Strcasecmp(p->domain, domain) == 0 &&
 | 
						|
	    Strcmp(p->path, path) == 0 && Strcasecmp(p->name, name) == 0)
 | 
						|
	    return p;
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
Str
 | 
						|
find_cookie(ParsedURL *pu)
 | 
						|
{
 | 
						|
    Str tmp;
 | 
						|
    struct cookie *p, *p1, *fco = NULL;
 | 
						|
    int version = 0;
 | 
						|
    char *fq_domainname, *domainname;
 | 
						|
 | 
						|
    fq_domainname = FQDN(pu->host);
 | 
						|
    check_expired_cookies();
 | 
						|
    for (p = First_cookie; p; p = p->next) {
 | 
						|
	domainname = (p->version == 0) ? fq_domainname : pu->host;
 | 
						|
	if (p->flag & COO_USE && match_cookie(pu, p, domainname)) {
 | 
						|
	    for (p1 = fco; p1 && Strcasecmp(p1->name, p->name);
 | 
						|
		 p1 = p1->next) ;
 | 
						|
	    if (p1)
 | 
						|
		continue;
 | 
						|
	    p1 = New(struct cookie);
 | 
						|
	    bcopy(p, p1, sizeof(struct cookie));
 | 
						|
	    p1->next = fco;
 | 
						|
	    fco = p1;
 | 
						|
	    if (p1->version > version)
 | 
						|
		version = p1->version;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (!fco)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    tmp = Strnew();
 | 
						|
    if (version > 0)
 | 
						|
	Strcat(tmp, Sprintf("$Version=\"%d\"; ", version));
 | 
						|
 | 
						|
    Strcat(tmp, make_cookie(fco));
 | 
						|
    for (p1 = fco->next; p1; p1 = p1->next) {
 | 
						|
	Strcat_charp(tmp, "; ");
 | 
						|
	Strcat(tmp, make_cookie(p1));
 | 
						|
	if (version > 0) {
 | 
						|
	    if (p1->flag & COO_PATH)
 | 
						|
		Strcat(tmp, Sprintf("; $Path=\"%s\"", p1->path->ptr));
 | 
						|
	    if (p1->flag & COO_DOMAIN)
 | 
						|
		Strcat(tmp, Sprintf("; $Domain=\"%s\"", p1->domain->ptr));
 | 
						|
	    if (p1->portl)
 | 
						|
		Strcat(tmp,
 | 
						|
		       Sprintf("; $Port=\"%s\"", portlist2str(p1->portl)->ptr));
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
check_avoid_wrong_number_of_dots_domain( Str domain )
 | 
						|
{
 | 
						|
   TextListItem *tl;
 | 
						|
    int avoid_wrong_number_of_dots_domain = FALSE;
 | 
						|
 | 
						|
    if (Cookie_avoid_wrong_number_of_dots_domains && 
 | 
						|
            Cookie_avoid_wrong_number_of_dots_domains->nitem > 0) {
 | 
						|
        for (tl = Cookie_avoid_wrong_number_of_dots_domains->first;
 | 
						|
                tl != NULL; tl = tl->next) {
 | 
						|
            if (domain_match(domain->ptr, tl->ptr)) {
 | 
						|
                avoid_wrong_number_of_dots_domain = TRUE;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (avoid_wrong_number_of_dots_domain == TRUE) {
 | 
						|
        return TRUE;
 | 
						|
    } else {
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
add_cookie(ParsedURL *pu, Str name, Str value,
 | 
						|
	   time_t expires, Str domain, Str path,
 | 
						|
	   int flag, Str comment, int version, Str port, Str commentURL)
 | 
						|
{
 | 
						|
    struct cookie *p;
 | 
						|
    char *domainname = (version == 0) ? FQDN(pu->host) : pu->host;
 | 
						|
    Str odomain = domain, opath = path;
 | 
						|
    struct portlist *portlist = NULL;
 | 
						|
    int use_security = !(flag & COO_OVERRIDE);
 | 
						|
 | 
						|
#define COOKIE_ERROR(err) if(!((err) & COO_OVERRIDE_OK) || use_security) return (err)
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
    fprintf(stderr, "host: [%s, %s] %d\n", pu->host, pu->file, flag);
 | 
						|
    fprintf(stderr, "cookie: [%s=%s]\n", name->ptr, value->ptr);
 | 
						|
    fprintf(stderr, "expires: [%s]\n", asctime(gmtime(&expires)));
 | 
						|
    if (domain)
 | 
						|
	fprintf(stderr, "domain: [%s]\n", domain->ptr);
 | 
						|
    if (path)
 | 
						|
	fprintf(stderr, "path: [%s]\n", path->ptr);
 | 
						|
    fprintf(stderr, "version: [%d]\n", version);
 | 
						|
    if (port)
 | 
						|
	fprintf(stderr, "port: [%s]\n", port->ptr);
 | 
						|
#endif				/* DEBUG */
 | 
						|
    /* [RFC 2109] s. 4.3.2 case 2; but this (no request-host) shouldn't happen */
 | 
						|
    if (!domainname)
 | 
						|
	return COO_ENODOT;
 | 
						|
 | 
						|
    if (domain) {
 | 
						|
	char *dp;
 | 
						|
	/* [DRAFT 12] s. 4.2.2 (does not apply in the case that
 | 
						|
	 * host name is the same as domain attribute for version 0
 | 
						|
	 * cookie)
 | 
						|
	 * I think that this rule has almost the same effect as the
 | 
						|
	 * tail match of [NETSCAPE].
 | 
						|
	 */
 | 
						|
	if (domain->ptr[0] != '.' &&
 | 
						|
	    (version > 0 || strcasecmp(domainname, domain->ptr) != 0))
 | 
						|
	    domain = Sprintf(".%s", domain->ptr);
 | 
						|
 | 
						|
	if (version == 0) {
 | 
						|
	    /* [NETSCAPE] rule */
 | 
						|
	    unsigned int n = total_dot_number(domain->ptr,
 | 
						|
				     domain->ptr + domain->length,
 | 
						|
				     3);
 | 
						|
	    if (n < 2) {
 | 
						|
		if (! check_avoid_wrong_number_of_dots_domain(domain)) {
 | 
						|
		    COOKIE_ERROR(COO_ESPECIAL);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    /* [DRAFT 12] s. 4.3.2 case 2 */
 | 
						|
	    if (strcasecmp(domain->ptr, ".local") != 0 &&
 | 
						|
		contain_no_dots(&domain->ptr[1], &domain->ptr[domain->length]))
 | 
						|
		COOKIE_ERROR(COO_ENODOT);
 | 
						|
	}
 | 
						|
 | 
						|
	/* [RFC 2109] s. 4.3.2 case 3 */
 | 
						|
	if (!(dp = domain_match(domainname, domain->ptr)))
 | 
						|
	    COOKIE_ERROR(COO_EDOM);
 | 
						|
	/* [RFC 2409] s. 4.3.2 case 4 */
 | 
						|
	/* Invariant: dp contains matched domain */
 | 
						|
	if (version > 0 && !contain_no_dots(domainname, dp))
 | 
						|
	    COOKIE_ERROR(COO_EBADHOST);
 | 
						|
    }
 | 
						|
    if (path) {
 | 
						|
	/* [RFC 2109] s. 4.3.2 case 1 */
 | 
						|
	if (version > 0 && strncmp(path->ptr, pu->file, path->length) != 0)
 | 
						|
	    COOKIE_ERROR(COO_EPATH);
 | 
						|
    }
 | 
						|
    if (port) {
 | 
						|
	/* [DRAFT 12] s. 4.3.2 case 5 */
 | 
						|
	portlist = make_portlist(port);
 | 
						|
	if (portlist && !port_match(portlist, pu->port))
 | 
						|
	    COOKIE_ERROR(COO_EPORT);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!domain)
 | 
						|
	domain = Strnew_charp(domainname);
 | 
						|
    if (!path) {
 | 
						|
	path = Strnew_charp(pu->file);
 | 
						|
	while (path->length > 0 && Strlastchar(path) != '/')
 | 
						|
	    Strshrink(path, 1);
 | 
						|
	if (Strlastchar(path) == '/')
 | 
						|
	    Strshrink(path, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    p = get_cookie_info(domain, path, name);
 | 
						|
    if (!p) {
 | 
						|
	p = New(struct cookie);
 | 
						|
	p->flag = 0;
 | 
						|
	if (default_use_cookie)
 | 
						|
	    p->flag |= COO_USE;
 | 
						|
	p->next = First_cookie;
 | 
						|
	First_cookie = p;
 | 
						|
    }
 | 
						|
 | 
						|
    copyParsedURL(&p->url, pu);
 | 
						|
    p->name = name;
 | 
						|
    p->value = value;
 | 
						|
    p->expires = expires;
 | 
						|
    p->domain = domain;
 | 
						|
    p->path = path;
 | 
						|
    p->comment = comment;
 | 
						|
    p->version = version;
 | 
						|
    p->portl = portlist;
 | 
						|
    p->commentURL = commentURL;
 | 
						|
 | 
						|
    if (flag & COO_SECURE)
 | 
						|
	p->flag |= COO_SECURE;
 | 
						|
    else
 | 
						|
	p->flag &= ~COO_SECURE;
 | 
						|
    if (odomain)
 | 
						|
	p->flag |= COO_DOMAIN;
 | 
						|
    else
 | 
						|
	p->flag &= ~COO_DOMAIN;
 | 
						|
    if (opath)
 | 
						|
	p->flag |= COO_PATH;
 | 
						|
    else
 | 
						|
	p->flag &= ~COO_PATH;
 | 
						|
    if (flag & COO_DISCARD || p->expires == (time_t) - 1) {
 | 
						|
	p->flag |= COO_DISCARD;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	p->flag &= ~COO_DISCARD;
 | 
						|
	is_saved = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    check_expired_cookies();
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
struct cookie *
 | 
						|
nth_cookie(int n)
 | 
						|
{
 | 
						|
    struct cookie *p;
 | 
						|
    int i;
 | 
						|
    for (p = First_cookie, i = 0; p; p = p->next, i++) {
 | 
						|
	if (i == n)
 | 
						|
	    return p;
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
#define str2charp(str) ((str)? (str)->ptr : "")
 | 
						|
 | 
						|
void
 | 
						|
save_cookies(void)
 | 
						|
{
 | 
						|
    struct cookie *p;
 | 
						|
    char *cookie_file;
 | 
						|
    FILE *fp;
 | 
						|
 | 
						|
    check_expired_cookies();
 | 
						|
 | 
						|
    if (!First_cookie || is_saved || no_rc_dir)
 | 
						|
	return;
 | 
						|
 | 
						|
    cookie_file = rcFile(COOKIE_FILE);
 | 
						|
    if (!(fp = fopen(cookie_file, "w")))
 | 
						|
	return;
 | 
						|
 | 
						|
    for (p = First_cookie; p; p = p->next) {
 | 
						|
	if (!(p->flag & COO_USE) || p->flag & COO_DISCARD)
 | 
						|
	    continue;
 | 
						|
	fprintf(fp, "%s\t%s\t%s\t%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\n",
 | 
						|
		parsedURL2Str(&p->url)->ptr,
 | 
						|
		p->name->ptr, p->value->ptr, (long)p->expires,
 | 
						|
		p->domain->ptr, p->path->ptr, p->flag,
 | 
						|
		p->version, str2charp(p->comment),
 | 
						|
		(p->portl) ? portlist2str(p->portl)->ptr : "",
 | 
						|
		str2charp(p->commentURL));
 | 
						|
    }
 | 
						|
    fclose(fp);
 | 
						|
    chmod(cookie_file, S_IRUSR | S_IWUSR);
 | 
						|
}
 | 
						|
 | 
						|
static Str
 | 
						|
readcol(char **p)
 | 
						|
{
 | 
						|
    Str tmp = Strnew();
 | 
						|
    while (**p && **p != '\n' && **p != '\r' && **p != '\t')
 | 
						|
	Strcat_char(tmp, *((*p)++));
 | 
						|
    if (**p == '\t')
 | 
						|
	(*p)++;
 | 
						|
    return tmp;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
load_cookies(void)
 | 
						|
{
 | 
						|
    struct cookie *cookie, *p;
 | 
						|
    FILE *fp;
 | 
						|
    Str line;
 | 
						|
    char *str;
 | 
						|
 | 
						|
    if (!(fp = fopen(rcFile(COOKIE_FILE), "r")))
 | 
						|
	return;
 | 
						|
 | 
						|
    if (First_cookie) {
 | 
						|
	for (p = First_cookie; p->next; p = p->next) ;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	p = NULL;
 | 
						|
    }
 | 
						|
    for (;;) {
 | 
						|
	line = Strfgets(fp);
 | 
						|
 | 
						|
	if (line->length == 0)
 | 
						|
	    break;
 | 
						|
	str = line->ptr;
 | 
						|
	cookie = New(struct cookie);
 | 
						|
	cookie->next = NULL;
 | 
						|
	cookie->flag = 0;
 | 
						|
	cookie->version = 0;
 | 
						|
	cookie->expires = (time_t) - 1;
 | 
						|
	cookie->comment = NULL;
 | 
						|
	cookie->portl = NULL;
 | 
						|
	cookie->commentURL = NULL;
 | 
						|
	parseURL(readcol(&str)->ptr, &cookie->url, NULL);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->name = readcol(&str);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->value = readcol(&str);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->expires = (time_t) atol(readcol(&str)->ptr);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->domain = readcol(&str);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->path = readcol(&str);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->flag = atoi(readcol(&str)->ptr);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->version = atoi(readcol(&str)->ptr);
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->comment = readcol(&str);
 | 
						|
	if (cookie->comment->length == 0)
 | 
						|
	    cookie->comment = NULL;
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->portl = make_portlist(readcol(&str));
 | 
						|
	if (!*str)
 | 
						|
	    break;
 | 
						|
	cookie->commentURL = readcol(&str);
 | 
						|
	if (cookie->commentURL->length == 0)
 | 
						|
	    cookie->commentURL = NULL;
 | 
						|
 | 
						|
	if (p)
 | 
						|
	    p->next = cookie;
 | 
						|
	else
 | 
						|
	    First_cookie = cookie;
 | 
						|
	p = cookie;
 | 
						|
    }
 | 
						|
 | 
						|
    fclose(fp);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
initCookie(void)
 | 
						|
{
 | 
						|
    load_cookies();
 | 
						|
    check_expired_cookies();
 | 
						|
}
 | 
						|
 | 
						|
Buffer *
 | 
						|
cookie_list_panel(void)
 | 
						|
{
 | 
						|
    /* FIXME: gettextize? */
 | 
						|
    Str src = Strnew_charp("<html><head><title>Cookies</title></head>"
 | 
						|
			   "<body><center><b>Cookies</b></center>"
 | 
						|
			   "<p><form method=internal action=cookie>");
 | 
						|
    struct cookie *p;
 | 
						|
    int i;
 | 
						|
    char *tmp, tmp2[80];
 | 
						|
 | 
						|
    if (!use_cookie || !First_cookie)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    Strcat_charp(src, "<ol>");
 | 
						|
    for (p = First_cookie, i = 0; p; p = p->next, i++) {
 | 
						|
	tmp = html_quote(parsedURL2Str(&p->url)->ptr);
 | 
						|
	if (p->expires != (time_t) - 1) {
 | 
						|
#ifdef HAVE_STRFTIME
 | 
						|
	    strftime(tmp2, 80, "%a, %d %b %Y %H:%M:%S GMT",
 | 
						|
		     gmtime(&p->expires));
 | 
						|
#else				/* not HAVE_STRFTIME */
 | 
						|
	    struct tm *gmt;
 | 
						|
	    static char *dow[] = {
 | 
						|
		"Sun ", "Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat "
 | 
						|
	    };
 | 
						|
	    static char *month[] = {
 | 
						|
		"Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ",
 | 
						|
		"Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec "
 | 
						|
	    };
 | 
						|
	    gmt = gmtime(&p->expires);
 | 
						|
	    strcpy(tmp2, dow[gmt->tm_wday]);
 | 
						|
	    sprintf(&tmp2[4], "%02d ", gmt->tm_mday);
 | 
						|
	    strcpy(&tmp2[7], month[gmt->tm_mon]);
 | 
						|
	    if (gmt->tm_year < 1900)
 | 
						|
		sprintf(&tmp2[11], "%04d %02d:%02d:%02d GMT",
 | 
						|
			(gmt->tm_year) + 1900, gmt->tm_hour, gmt->tm_min,
 | 
						|
			gmt->tm_sec);
 | 
						|
	    else
 | 
						|
		sprintf(&tmp2[11], "%04d %02d:%02d:%02d GMT",
 | 
						|
			gmt->tm_year, gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
 | 
						|
#endif				/* not HAVE_STRFTIME */
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    tmp2[0] = '\0';
 | 
						|
	Strcat_charp(src, "<li>");
 | 
						|
	Strcat_charp(src, "<h1><a href=\"");
 | 
						|
	Strcat_charp(src, tmp);
 | 
						|
	Strcat_charp(src, "\">");
 | 
						|
	Strcat_charp(src, tmp);
 | 
						|
	Strcat_charp(src, "</a></h1>");
 | 
						|
 | 
						|
	Strcat_charp(src, "<table cellpadding=0>");
 | 
						|
	if (!(p->flag & COO_SECURE)) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Cookie:</b></td><td>");
 | 
						|
	    Strcat_charp(src, html_quote(make_cookie(p)->ptr));
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	if (p->comment) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Comment:</b></td><td>");
 | 
						|
	    Strcat_charp(src, html_quote(p->comment->ptr));
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	if (p->commentURL) {
 | 
						|
	    Strcat_charp(src,
 | 
						|
			 "<tr><td width=\"80\"><b>CommentURL:</b></td><td>");
 | 
						|
	    Strcat_charp(src, "<a href=\"");
 | 
						|
	    Strcat_charp(src, html_quote(p->commentURL->ptr));
 | 
						|
	    Strcat_charp(src, "\">");
 | 
						|
	    Strcat_charp(src, html_quote(p->commentURL->ptr));
 | 
						|
	    Strcat_charp(src, "</a>");
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	if (tmp2[0]) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Expires:</b></td><td>");
 | 
						|
	    Strcat_charp(src, tmp2);
 | 
						|
	    if (p->flag & COO_DISCARD)
 | 
						|
		Strcat_charp(src, " (Discard)");
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	Strcat_charp(src, "<tr><td width=\"80\"><b>Version:</b></td><td>");
 | 
						|
	Strcat_charp(src, Sprintf("%d", p->version)->ptr);
 | 
						|
	Strcat_charp(src, "</td></tr><tr><td>");
 | 
						|
	if (p->domain) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Domain:</b></td><td>");
 | 
						|
	    Strcat_charp(src, html_quote(p->domain->ptr));
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	if (p->path) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Path:</b></td><td>");
 | 
						|
	    Strcat_charp(src, html_quote(p->path->ptr));
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	if (p->portl) {
 | 
						|
	    Strcat_charp(src, "<tr><td width=\"80\"><b>Port:</b></td><td>");
 | 
						|
	    Strcat_charp(src, html_quote(portlist2str(p->portl)->ptr));
 | 
						|
	    Strcat_charp(src, "</td></tr>");
 | 
						|
	}
 | 
						|
	Strcat_charp(src, "<tr><td width=\"80\"><b>Secure:</b></td><td>");
 | 
						|
	Strcat_charp(src, (p->flag & COO_SECURE) ? "Yes" : "No");
 | 
						|
	Strcat_charp(src, "</td></tr><tr><td>");
 | 
						|
 | 
						|
	Strcat(src, Sprintf("<tr><td width=\"80\"><b>Use:</b></td><td>"
 | 
						|
			    "<input type=radio name=\"%d\" value=1%s>Yes"
 | 
						|
			    "  "
 | 
						|
			    "<input type=radio name=\"%d\" value=0%s>No",
 | 
						|
			    i, (p->flag & COO_USE) ? " checked" : "",
 | 
						|
			    i, (!(p->flag & COO_USE)) ? " checked" : ""));
 | 
						|
	Strcat_charp(src,
 | 
						|
		     "</td></tr><tr><td><input type=submit value=\"OK\"></table><p>");
 | 
						|
    }
 | 
						|
    Strcat_charp(src, "</ol></form></body></html>");
 | 
						|
    return loadHTMLString(src);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
set_cookie_flag(struct parsed_tagarg *arg)
 | 
						|
{
 | 
						|
    int n, v;
 | 
						|
    struct cookie *p;
 | 
						|
 | 
						|
    while (arg) {
 | 
						|
	if (arg->arg && *arg->arg && arg->value && *arg->value) {
 | 
						|
	    n = atoi(arg->arg);
 | 
						|
	    v = atoi(arg->value);
 | 
						|
	    if ((p = nth_cookie(n)) != NULL) {
 | 
						|
		if (v && !(p->flag & COO_USE))
 | 
						|
		    p->flag |= COO_USE;
 | 
						|
		else if (!v && p->flag & COO_USE)
 | 
						|
		    p->flag &= ~COO_USE;
 | 
						|
		if (!(p->flag & COO_DISCARD))
 | 
						|
		    is_saved = 0;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	arg = arg->next;
 | 
						|
    }
 | 
						|
    backBf();
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
check_cookie_accept_domain(char *domain)
 | 
						|
{
 | 
						|
    TextListItem *tl;
 | 
						|
 | 
						|
    if (domain == NULL)
 | 
						|
	return 0;
 | 
						|
 | 
						|
    if (Cookie_accept_domains && Cookie_accept_domains->nitem > 0) {
 | 
						|
	for (tl = Cookie_accept_domains->first; tl != NULL; tl = tl->next) {
 | 
						|
	    if (domain_match(domain, tl->ptr))
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (Cookie_reject_domains && Cookie_reject_domains->nitem > 0) {
 | 
						|
	for (tl = Cookie_reject_domains->first; tl != NULL; tl = tl->next) {
 | 
						|
	    if (domain_match(domain, tl->ptr))
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
#endif				/* USE_COOKIE */
 |