about summary refs log tree commit diff stats
path: root/src/LYCookie.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/LYCookie.c')
-rw-r--r--src/LYCookie.c1358
1 files changed, 567 insertions, 791 deletions
diff --git a/src/LYCookie.c b/src/LYCookie.c
index 8efc4e6c..fdf37227 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -296,6 +296,30 @@ PRIVATE BOOL is_prefix ARGS2(CONST char *, a, CONST char *, b)
 }
 
 /*
+ * Find the domain-entry for the given name.
+ */
+PRIVATE domain_entry * find_domain_entry ARGS1(
+    CONST char *,	name)
+{
+    HTList *hl;
+    domain_entry *de = NULL;
+
+    if (name != 0
+     && *name != '\0') {
+	for (hl = domain_list; hl != NULL; hl = hl->next) {
+	    de = (domain_entry *)hl->object;
+	    if (de != NULL
+	     && de->domain != NULL
+	     && !strcasecomp(name, de->domain)) {
+		break;
+	    }
+	    de = NULL;
+	}
+    }
+    return de;
+}
+
+/*
 **  Store a cookie somewhere in the domain list. - AK & FM
 */
 PRIVATE void store_cookie ARGS3(
@@ -333,19 +357,8 @@ PRIVATE void store_cookie ARGS3(
      *	is already listed.
      */
     cookie_list = NULL;
-    for (hl = domain_list; hl != NULL; hl = hl->next) {
-	de = (domain_entry *)hl->object;
-	if ((de != NULL && de->domain != NULL) &&
-	    !strcasecomp(co->domain, de->domain)) {
-		cookie_list = de->cookie_list;
-		break;
-	}
-    }
-
-    if(hl == NULL) {
-	de = NULL;
-	cookie_list = NULL;
-    }
+    if ((de = find_domain_entry(co->domain)) != NULL)
+	cookie_list = de->cookie_list;
 
     /*
      * Apply sanity checks.
@@ -375,6 +388,7 @@ PRIVATE void store_cookie ARGS3(
 	    return;
 	}
     }
+
     /*
      * The next 4 conditions do NOT apply if the domain is still
      * the default of request-host. (domains - case insensitive).
@@ -398,15 +412,13 @@ PRIVATE void store_cookie ARGS3(
 	 *  value otherwise qualified. - FM
 	 */
 	if (co->domain[0] != '.' || co->domain[1] == '\0') {
-	    CTRACE((tfp, "store_cookie: Rejecting domain '%s'.\n",
-		    co->domain));
+	    CTRACE((tfp, "store_cookie: Rejecting domain '%s'.\n", co->domain));
 	    freeCookie(co);
 	    return;
 	}
 	ptr = strchr((co->domain + 1), '.');
 	if (ptr == NULL || ptr[1] == '\0') {
-	    CTRACE((tfp, "store_cookie: Rejecting domain '%s'.\n",
-		    co->domain));
+	    CTRACE((tfp, "store_cookie: Rejecting domain '%s'.\n", co->domain));
 	    freeCookie(co);
 	    return;
 	}
@@ -468,8 +480,8 @@ PRIVATE void store_cookie ARGS3(
 		       hostname);
 	    if (!HTConfirmDefault(msg, NO)) {
 		CTRACE((tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n",
-					co->domain,
-					hostname));
+			co->domain,
+			hostname));
 		freeCookie(co);
 		FREE(msg);
 		return;
@@ -490,28 +502,14 @@ PRIVATE void store_cookie ARGS3(
 	FREE(msg);
     }
 
-    if (hl == NULL) {
+    if (de == NULL) {
 	/*
-	 *	Domain not found; add a new entry for this domain.
+	 * Domain not found; add a new entry for this domain.
 	 */
 	de = typecalloc(domain_entry);
 	if (de == NULL)
 	    outofmem(__FILE__, "store_cookie");
-#if 0	/* was: ifdef EXP_PERSISTENT_COOKIES */
-	/*
-	 * The default behavior for this new domain could be set
-	 * differently if the cookie comes from a file, as the
-	 * code had it originally, but there doesn't seem to be
-	 * a good reason for it any more; setting more permissive
-	 * behavior for individual domains is now possible via
-	 * configuration options. - kw
-	 */
-	if (persistent_cookies
-	 && (co->flags & COOKIE_FLAG_FROM_FILE))
-	    de->bv = ACCEPT_ALWAYS; /* ?? */
-	else
-#endif
-	    de->bv = QUERY_USER;
+	de->bv = QUERY_USER;
 	de->invcheck_bv = DEFAULT_INVCHECK_BV; /* should this go here? */
 	cookie_list = de->cookie_list = HTList_new();
 	StrAllocCopy(de->domain, co->domain);
@@ -823,6 +821,260 @@ PRIVATE char * scan_cookie_sublist ARGS6(
 }
 
 /*
+ * Presence of value is needed (indicated normally by '=') to start a cookie,
+ * but it can be an empty string.  - kw 1999-06-24
+ */
+PRIVATE char *alloc_attr_value ARGS2(
+	CONST char *,	value_start,
+	CONST char *,	value_end)
+{
+    char *value = NULL;
+
+    if (value_start && value_end >= value_start) {
+	int value_len = (value_end - value_start);
+
+	if (value_len > max_cookies_buffer) {
+	    value_len = max_cookies_buffer;
+	}
+	value = typecallocn(char, value_len + 1);
+	if (value == NULL)
+	    outofmem(__FILE__, "LYProcessSetCookies");
+	LYstrncpy(value, value_start, value_len);
+    }
+    return value;
+}
+
+#define FLAGS_INVALID_PORT 1
+#define FLAGS_KNOWN_ATTR   2
+#define FLAGS_MAXAGE_ATTR  4
+
+PRIVATE unsigned parse_attribute ARGS9(
+	unsigned,	flags,
+	cookie *,	cur_cookie,
+	int *,		cookie_len,
+	CONST char *,	attr_start,
+	int,		attr_len,
+	char *,		value,
+	CONST char *,	address,
+	char *,		hostname,
+	int,		port)
+{
+    BOOLEAN known_attr = NO;
+    int url_type;
+
+    flags &= ~FLAGS_KNOWN_ATTR;
+    if (attr_len == 6 && !strncasecomp(attr_start, "secure", 6)) {
+	if (value == NULL) {
+	    known_attr = YES;
+	    if (cur_cookie != NULL) {
+		cur_cookie->flags |= COOKIE_FLAG_SECURE;
+	    }
+	} else {
+	    /*
+	     *	If secure has a value, assume someone
+	     *	misused it as cookie name. - FM
+	     */
+	    known_attr = NO;
+	}
+    } else if (attr_len == 7 && !strncasecomp(attr_start, "discard", 7)) {
+	if (value == NULL) {
+	    known_attr = YES;
+	    if (cur_cookie != NULL) {
+		cur_cookie->flags |= COOKIE_FLAG_DISCARD;
+	    }
+	} else {
+	    /*
+	     *	If discard has a value, assume someone
+	     *	used it as a cookie name. - FM
+	     */
+	    known_attr = NO;
+	}
+    } else if (attr_len == 7 && !strncasecomp(attr_start, "comment", 7)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat comment. - FM
+	     */
+	    cur_cookie->comment == NULL) {
+	    StrAllocCopy(cur_cookie->comment, value);
+	    *cookie_len += strlen(cur_cookie->comment);
+	}
+    } else if (attr_len == 10 && !strncasecomp(attr_start,
+					  "commentURL", 10)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat commentURL. - FM
+	     */
+	    cur_cookie->commentURL == NULL) {
+	    /*
+	     *	We should get only absolute URLs as
+	     *	values, but will resolve versus the
+	     *	request's URL just in case. - FM
+	     */
+	    cur_cookie->commentURL = HTParse(value,
+					     address,
+					     PARSE_ALL);
+	    /*
+	     *	Accept only URLs for http or https servers. - FM
+	     */
+	    if ((url_type = is_url(cur_cookie->commentURL)) &&
+		(url_type == HTTP_URL_TYPE ||
+		 url_type == HTTPS_URL_TYPE)) {
+		*cookie_len += strlen(cur_cookie->commentURL);
+	    } else {
+		CTRACE((tfp, "LYProcessSetCookies: Rejecting commentURL value '%s'\n",
+			    cur_cookie->commentURL));
+		FREE(cur_cookie->commentURL);
+	    }
+	}
+    } else if (attr_len == 6 && !strncasecomp(attr_start, "domain", 6)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat domain. - FM
+	     */
+	    !(cur_cookie->flags & COOKIE_FLAG_DOMAIN_SET)) {
+	    *cookie_len -= strlen(cur_cookie->domain);
+	    /*
+	     *	If the value does not have a lead dot,
+	     *	but does have an embedded dot, and is
+	     *	not an exact match to the hostname, nor
+	     *	is a numeric IP address, add a lead dot.
+	     *	Otherwise, use the value as is. - FM
+	     *	(domains - case insensitive).
+	     */
+	    if (value[0] != '.' && value[0] != '\0' &&
+		value[1] != '\0' && strcasecomp(value, hostname)) {
+		char *ptr = strchr(value, '.');
+		if (ptr != NULL && ptr[1] != '\0') {
+		    ptr = value;
+		    while (*ptr == '.' ||
+			   isdigit(UCH(*ptr)))
+			ptr++;
+		    if (*ptr != '\0') {
+			CTRACE((tfp,
+       "LYProcessSetCookies: Adding lead dot for domain value '%s'\n",
+				    value));
+			StrAllocCopy(cur_cookie->domain, ".");
+			StrAllocCat(cur_cookie->domain, value);
+		    } else {
+			StrAllocCopy(cur_cookie->domain, value);
+		    }
+		} else {
+		    StrAllocCopy(cur_cookie->domain, value);
+		}
+	    } else {
+		StrAllocCopy(cur_cookie->domain, value);
+	    }
+	    *cookie_len += strlen(cur_cookie->domain);
+	    cur_cookie->flags |= COOKIE_FLAG_DOMAIN_SET;
+	}
+    } else if (attr_len == 4 && !strncasecomp(attr_start, "path", 4)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat path. - FM
+	     */
+	    !(cur_cookie->flags & COOKIE_FLAG_PATH_SET)) {
+	    *cookie_len -= strlen(cur_cookie->path);
+	    StrAllocCopy(cur_cookie->path, value);
+	    *cookie_len += (cur_cookie->pathlen = strlen(cur_cookie->path));
+	    cur_cookie->flags |= COOKIE_FLAG_PATH_SET;
+	}
+    } else if (attr_len == 4 && !strncasecomp(attr_start, "port", 4)) {
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat port. - FM
+	     */
+	    cur_cookie->PortList == NULL) {
+	    char *cp = value;
+	    while ((*cp != '\0') &&
+		   (isdigit(UCH(*cp)) ||
+		    *cp == ',' || *cp == ' ')) {
+		cp++;
+	    }
+	    if (*cp == '\0') {
+		if (!port_matches(port, value)) {
+		    flags |= FLAGS_INVALID_PORT;
+		} else {
+		    StrAllocCopy(cur_cookie->PortList, value);
+		    *cookie_len += strlen(cur_cookie->PortList);
+		}
+		known_attr = YES;
+	    } else {
+		known_attr = NO;
+	    }
+	} else if (cur_cookie != NULL) {
+	    /*
+	     *	Don't process a repeat port. - FM
+	     */
+	    if (cur_cookie->PortList == NULL) {
+		HTSprintf0(&(cur_cookie->PortList), "%d", port);
+		*cookie_len += strlen(cur_cookie->PortList);
+	    }
+	    known_attr = YES;
+	}
+    } else if (attr_len == 7 && !strncasecomp(attr_start, "version", 7)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat version. - FM
+	     */
+	    cur_cookie->version < 1) {
+	    int temp = strtol(value, NULL, 10);
+	    if (errno != -ERANGE) {
+		cur_cookie->version = temp;
+	    }
+	}
+    } else if (attr_len == 7 && !strncasecomp(attr_start, "max-age", 7)) {
+	known_attr = YES;
+	if (cur_cookie != NULL && value &&
+	    /*
+	     *	Don't process a repeat max-age. - FM
+	     */
+	    !(flags & FLAGS_MAXAGE_ATTR)) {
+	    int temp = strtol(value, NULL, 10);
+	    cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+	    if (errno == -ERANGE) {
+		cur_cookie->expires = (time_t)0;
+	    } else {
+		cur_cookie->expires = (time(NULL) + temp);
+		CTRACE((tfp, "LYSetCookie: expires %ld, %s",
+			    (long) cur_cookie->expires,
+			    ctime(&cur_cookie->expires)));
+	    }
+	    flags |= FLAGS_MAXAGE_ATTR;
+	}
+    } else if (attr_len == 7 && !strncasecomp(attr_start, "expires", 7)) {
+	/*
+	 *  Convert an 'expires' attribute value if we haven't
+	 *  received a 'max-age'.  Note that 'expires' should not
+	 *  be used in Version 1 cookies, but it might be used for
+	 *  "backward compatibility", and, in turn, ill-informed
+	 *  people surely would start using it instead of, rather
+	 *  than in addition to, 'max-age'. - FM
+	 */
+	known_attr = YES;
+	if ((cur_cookie != NULL && !(flags & FLAGS_MAXAGE_ATTR)) &&
+	     !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) {
+	    if (value) {
+		cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+		cur_cookie->expires = LYmktime(value, FALSE);
+		if (cur_cookie->expires > 0) {
+		    CTRACE((tfp, "LYSetCookie: expires %ld, %s",
+				(long) cur_cookie->expires,
+				ctime(&cur_cookie->expires)));
+		}
+	    }
+	}
+    }
+    if (known_attr)
+	flags |= FLAGS_KNOWN_ATTR;
+    return flags;
+}
+
+/*
 **  Process potentially concatenated Set-Cookie2 and/or Set-Cookie
 **  headers. - FM
 */
@@ -837,11 +1089,10 @@ PRIVATE void LYProcessSetCookies ARGS6(
     CONST char *p, *attr_start, *attr_end, *value_start, *value_end;
     HTList *CombinedCookies = NULL, *cl = NULL;
     cookie *cur_cookie = NULL, *co = NULL;
-    int length = 0, url_type = 0;
+    int cookie_len = 0;
     int NumCookies = 0;
-    BOOL MaxAgeAttrSet = FALSE;
     BOOL Quoted = FALSE;
-    BOOLEAN invalidport = FALSE;
+    unsigned parse_flags = 0;
 
     if (!(SetCookie && *SetCookie) &&
 	!(SetCookie2 && *SetCookie2)) {
@@ -1052,257 +1303,32 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	 *  Now, we can handle this attribute/value pair.
 	 */
 	if (attr_end > attr_start) {
-	    int len = (attr_end - attr_start);
-	    BOOLEAN known_attr = NO;
-	    char *value = NULL;
-
-	    if (value_start && value_end >= value_start) {
-		/*
-		 * Presence of value is now needed (indicated normally by '=')
-		 * to start a cookie, but it can now be an empty string.
-		 * - kw 1999-06-24
-		 */
-		int value_len = (value_end - value_start);
-
-		if (value_len > max_cookies_buffer) {
-		    value_len = max_cookies_buffer;
-		}
-		value = typecallocn(char, value_len + 1);
-		if (value == NULL)
-		    outofmem(__FILE__, "LYProcessSetCookies");
-		LYstrncpy(value, value_start, value_len);
-	    }
-	    if (len == 6 && !strncasecomp(attr_start, "secure", 6)) {
-		if (value == NULL) {
-		    known_attr = YES;
-		    if (cur_cookie != NULL) {
-			cur_cookie->flags |= COOKIE_FLAG_SECURE;
-		    }
-		} else {
-		    /*
-		     *	If secure has a value, assume someone
-		     *	misused it as cookie name. - FM
-		     */
-		    known_attr = NO;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "discard", 7)) {
-		if (value == NULL) {
-		    known_attr = YES;
-		    if (cur_cookie != NULL) {
-			cur_cookie->flags |= COOKIE_FLAG_DISCARD;
-		    }
-		} else {
-		    /*
-		     *	If discard has a value, assume someone
-		     *	used it as a cookie name. - FM
-		     */
-		    known_attr = NO;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "comment", 7)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat comment. - FM
-		     */
-		    cur_cookie->comment == NULL) {
-		    StrAllocCopy(cur_cookie->comment, value);
-		    length += strlen(cur_cookie->comment);
-		}
-	    } else if (len == 10 && !strncasecomp(attr_start,
-						  "commentURL", 10)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat commentURL. - FM
-		     */
-		    cur_cookie->commentURL == NULL) {
-		    /*
-		     *	We should get only absolute URLs as
-		     *	values, but will resolve versus the
-		     *	request's URL just in case. - FM
-		     */
-		    cur_cookie->commentURL = HTParse(value,
-						     address,
-						     PARSE_ALL);
-		    /*
-		     *	Accept only URLs for http or https servers. - FM
-		     */
-		    if ((url_type = is_url(cur_cookie->commentURL)) &&
-			(url_type == HTTP_URL_TYPE ||
-			 url_type == HTTPS_URL_TYPE)) {
-			length += strlen(cur_cookie->commentURL);
-		    } else {
-			CTRACE((tfp, "LYProcessSetCookies: Rejecting commentURL value '%s'\n",
-				    cur_cookie->commentURL));
-			FREE(cur_cookie->commentURL);
-		    }
-		}
-	    } else if (len == 6 && !strncasecomp(attr_start, "domain", 6)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat domain. - FM
-		     */
-		    !(cur_cookie->flags & COOKIE_FLAG_DOMAIN_SET)) {
-		    length -= strlen(cur_cookie->domain);
-		    /*
-		     *	If the value does not have a lead dot,
-		     *	but does have an embedded dot, and is
-		     *	not an exact match to the hostname, nor
-		     *	is a numeric IP address, add a lead dot.
-		     *	Otherwise, use the value as is. - FM
-		     *	(domains - case insensitive).
-		     */
-		    if (value[0] != '.' && value[0] != '\0' &&
-			value[1] != '\0' && strcasecomp(value, hostname)) {
-			char *ptr = strchr(value, '.');
-			if (ptr != NULL && ptr[1] != '\0') {
-			    ptr = value;
-			    while (*ptr == '.' ||
-				   isdigit(UCH(*ptr)))
-				ptr++;
-			    if (*ptr != '\0') {
-				CTRACE((tfp,
-	       "LYProcessSetCookies: Adding lead dot for domain value '%s'\n",
-					    value));
-				StrAllocCopy(cur_cookie->domain, ".");
-				StrAllocCat(cur_cookie->domain, value);
-			    } else {
-				StrAllocCopy(cur_cookie->domain, value);
-			    }
-			} else {
-			    StrAllocCopy(cur_cookie->domain, value);
-			}
-		    } else {
-			StrAllocCopy(cur_cookie->domain, value);
-		    }
-		    length += strlen(cur_cookie->domain);
-		    cur_cookie->flags |= COOKIE_FLAG_DOMAIN_SET;
-		}
-	    } else if (len == 4 && !strncasecomp(attr_start, "path", 4)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat path. - FM
-		     */
-		    !(cur_cookie->flags & COOKIE_FLAG_PATH_SET)) {
-		    length -= strlen(cur_cookie->path);
-		    StrAllocCopy(cur_cookie->path, value);
-		    length += (cur_cookie->pathlen = strlen(cur_cookie->path));
-		    cur_cookie->flags |= COOKIE_FLAG_PATH_SET;
-		}
-	    } else if (len == 4 && !strncasecomp(attr_start, "port", 4)) {
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat port. - FM
-		     */
-		    cur_cookie->PortList == NULL) {
-		    char *cp = value;
-		    while ((*cp != '\0') &&
-			   (isdigit(UCH(*cp)) ||
-			    *cp == ',' || *cp == ' ')) {
-			cp++;
-		    }
-		    if (*cp == '\0' && !port_matches(port, value)) {
-			invalidport = TRUE;
-			known_attr = YES;
-		    } else if (*cp == '\0') {
-			StrAllocCopy(cur_cookie->PortList, value);
-			length += strlen(cur_cookie->PortList);
-			known_attr = YES;
-		    } else {
-			known_attr = NO;
-		    }
-		} else if (cur_cookie != NULL) {
-		    /*
-		     *	Don't process a repeat port. - FM
-		     */
-		    if (cur_cookie->PortList == NULL) {
-			HTSprintf0(&(cur_cookie->PortList), "%d", port);
-			length += strlen(cur_cookie->PortList);
-		    }
-		    known_attr = YES;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "version", 7)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat version. - FM
-		     */
-		    cur_cookie->version < 1) {
-		    int temp = strtol(value, NULL, 10);
-		    if (errno != -ERANGE) {
-			cur_cookie->version = temp;
-		    }
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "max-age", 7)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat max-age. - FM
-		     */
-		    !MaxAgeAttrSet) {
-		    int temp = strtol(value, NULL, 10);
-		    cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
-		    if (errno == -ERANGE) {
-			cur_cookie->expires = (time_t)0;
-		    } else {
-			cur_cookie->expires = (time(NULL) + temp);
-			CTRACE((tfp, "LYSetCookie: expires %ld, %s",
-				    (long) cur_cookie->expires,
-				    ctime(&cur_cookie->expires)));
-		    }
-		    MaxAgeAttrSet = TRUE;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "expires", 7)) {
-		/*
-		 *  Convert an 'expires' attribute value if we haven't
-		 *  received a 'max-age'.  Note that 'expires' should not
-		 *  be used in Version 1 cookies, but it might be used for
-		 *  "backward compatibility", and, in turn, ill-informed
-		 *  people surely would start using it instead of, rather
-		 *  than in addition to, 'max-age'. - FM
-		 */
-		known_attr = YES;
-		if ((cur_cookie != NULL && !MaxAgeAttrSet) &&
-		     !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) {
-		    if (value) {
-			cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
-			cur_cookie->expires = LYmktime(value, FALSE);
-			if (cur_cookie->expires > 0) {
-			    CTRACE((tfp, "LYSetCookie: expires %ld, %s",
-					(long) cur_cookie->expires,
-					ctime(&cur_cookie->expires)));
-			}
-		    }
-		}
-	    }
+	    char *value = alloc_attr_value(value_start, value_end);
+
+	    parse_flags = parse_attribute (parse_flags,
+					   cur_cookie,
+					   &cookie_len,
+					   attr_start,
+					   (attr_end - attr_start),
+					   value,
+					   address,
+					   hostname,
+					   port);
 
 	    /*
-	     *	If none of the above comparisons succeeded, and we have
-	     *	a value, then we have an unknown pair of the form 'foo=bar',
-	     *	which means it's time to create a new cookie.  If we don't
-	     *	have a non-zero-length value, assume it's an error or a
-	     *	new, unknown attribute which doesn't take a value, and
-	     *	ignore it. - FM
-	     */
-	    /* if (!known_attr && value_end > value_start) */
-
-	    /* Is there any reason we don't want to accept cookies with
-	     * no value?  This seems to be needed for sites that reset a
-	     * cookie by nulling out the value.  If this causes problems,
-	     * we can go back to the original behavior above.  - BJP
-	     *
-	     * Presence of value is now needed (indicated normally by '='),
-	     * but it can now be an empty string. - kw 1999-06-24
+	     * Presence of value is needed (indicated normally by '='),
+	     * but it can be an empty string. - kw 1999-06-24
 	     */
-	    if (!known_attr && value && value_end >= value_start) {
+	    if (!(parse_flags & FLAGS_KNOWN_ATTR)
+	      && value
+	      && value_end >= value_start) {
 		/*
 		 *  If we've started a cookie, and it's not too big,
 		 *  save it in the CombinedCookies list. - FM
 		 */
-		if (length <= max_cookies_buffer && cur_cookie != NULL &&
-		    !invalidport) {
+		if (cookie_len <= max_cookies_buffer
+		 && cur_cookie != NULL
+		 && !(parse_flags & FLAGS_INVALID_PORT)) {
 		    /*
 		     *	Assume version 1 if not set to that or higher. - FM
 		     */
@@ -1318,10 +1344,10 @@ PRIVATE void LYProcessSetCookies ARGS6(
 				(cur_cookie->value ?
 				 cur_cookie->value : "[no value]")));
 		    CTRACE((tfp,
-			   invalidport ?
+			   (parse_flags & FLAGS_INVALID_PORT) ?
 			   "                     due to excessive length!\n"
 			 : "                     due to invalid port!\n"));
-		    if (invalidport) {
+		    if (parse_flags & FLAGS_INVALID_PORT) {
 			NumCookies --;
 		    }
 		    freeCookie(cur_cookie);
@@ -1331,19 +1357,18 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		 *  Start a new cookie. - FM
 		 */
 		cur_cookie = newCookie();
-		invalidport = FALSE;
-		length = 0;
+		cookie_len = 0;
 		NumCookies++;
 		MemAllocCopy(&(cur_cookie->name), attr_start, attr_end);
-		length += strlen(cur_cookie->name);
+		cookie_len += strlen(cur_cookie->name);
 		MemAllocCopy(&(cur_cookie->value), value_start, value_end);
-		length += strlen(cur_cookie->value);
+		cookie_len += strlen(cur_cookie->value);
 		StrAllocCopy(cur_cookie->domain, hostname);
-		length += strlen(cur_cookie->domain);
+		cookie_len += strlen(cur_cookie->domain);
 		StrAllocCopy(cur_cookie->path, path);
-		length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+		cookie_len += (cur_cookie->pathlen = strlen(cur_cookie->path));
 		cur_cookie->port = port;
-		MaxAgeAttrSet = FALSE;
+		parse_flags = 0;
 		cur_cookie->quoted = TRUE;
 	    }
 	    FREE(value);
@@ -1355,19 +1380,19 @@ PRIVATE void LYProcessSetCookies ARGS6(
      *	if we are within the length limit. - FM
      */
     if (NumCookies <= max_cookies_domain
-     && length <= max_cookies_buffer
-     && cur_cookie != NULL && !invalidport) {
+     && cookie_len <= max_cookies_buffer
+     && cur_cookie != NULL && !(parse_flags & FLAGS_INVALID_PORT)) {
 	if (cur_cookie->version < 1) {
 	    cur_cookie->version = 1;
 	}
 	HTList_appendObject(CombinedCookies, cur_cookie);
-    } else if (cur_cookie != NULL && !invalidport) {
+    } else if (cur_cookie != NULL && !(parse_flags & FLAGS_INVALID_PORT)) {
 	CTRACE((tfp, "LYProcessSetCookies: Rejecting Set-Cookie2: %s=%s\n",
 		    (cur_cookie->name ? cur_cookie->name : "[no name]"),
 		    (cur_cookie->value ? cur_cookie->value : "[no value]")));
 	CTRACE((tfp, "                     due to excessive %s%s%s\n",
-		    (length > max_cookies_buffer ? "length" : ""),
-		    (length > max_cookies_buffer &&
+		    (cookie_len > max_cookies_buffer ? "length" : ""),
+		    (cookie_len > max_cookies_buffer &&
 		     NumCookies > max_cookies_domain
 			? " and "
 			: ""),
@@ -1388,7 +1413,7 @@ PRIVATE void LYProcessSetCookies ARGS6(
      *	Process the Set-Cookie header, if no non-zero-length Set-Cookie2
      *	header was present. - FM
      */
-    length = 0;
+    cookie_len = 0;
     NumCookies = 0;
     cur_cookie = NULL;
     p = ((SetCookie && !(SetCookie2 && *SetCookie2)) ? SetCookie : "");
@@ -1572,241 +1597,31 @@ PRIVATE void LYProcessSetCookies ARGS6(
 	 *  Now, we can handle this attribute/value pair.
 	 */
 	if (attr_end > attr_start) {
-	    int len = (attr_end - attr_start);
-	    BOOLEAN known_attr = NO;
-	    char *value = NULL;
-
-	    if (value_start && value_end >= value_start) {
-		/*
-		 * Presence of value is now needed (indicated normally by '=')
-		 * to start a cookie, but it can now be an empty string.
-		 * - kw 1999-06-24
-		 */
-		int value_len = (value_end - value_start);
-
-		if (value_len > max_cookies_buffer) {
-		    value_len = max_cookies_buffer;
-		}
-		value = typecallocn(char, value_len + 1);
-		if (value == NULL)
-		    outofmem(__FILE__, "LYProcessSetCookies");
-		LYstrncpy(value, value_start, value_len);
-	    }
-	    if (len == 6 && !strncasecomp(attr_start, "secure", 6)) {
-		if (value == NULL) {
-		    known_attr = YES;
-		    if (cur_cookie != NULL) {
-			cur_cookie->flags |= COOKIE_FLAG_SECURE;
-		    }
-		} else {
-		    /*
-		     *	If secure has a value, assume someone
-		     *	misused it as cookie name. - FM
-		     */
-		    known_attr = NO;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "discard", 7)) {
-		if (value == NULL) {
-		    known_attr = YES;
-		    if (cur_cookie != NULL) {
-			cur_cookie->flags |= COOKIE_FLAG_DISCARD;
-		    }
-		} else {
-		    /*
-		     *	If discard has a value, assume someone
-		     *	used it as a cookie name. - FM
-		     */
-		    known_attr = NO;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "comment", 7)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat comment. - FM
-		     */
-		    cur_cookie->comment == NULL) {
-		    StrAllocCopy(cur_cookie->comment, value);
-		    length += strlen(cur_cookie->comment);
-		}
-	    } else if (len == 10 && !strncasecomp(attr_start,
-						  "commentURL", 10)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat commentURL. - FM
-		     */
-		    cur_cookie->commentURL == NULL) {
-		    /*
-		     *	We should get only absolute URLs as
-		     *	values, but will resolve versus the
-		     *	request's URL just in case. - FM
-		     */
-		    cur_cookie->commentURL = HTParse(value,
-						     address,
-						     PARSE_ALL);
-		    /*
-		     *	Accept only URLs for http or https servers. - FM
-		     */
-		    if ((url_type = is_url(cur_cookie->commentURL)) &&
-			(url_type == HTTP_URL_TYPE ||
-			 url_type == HTTPS_URL_TYPE)) {
-			length += strlen(cur_cookie->commentURL);
-		    } else {
-			CTRACE((tfp, "LYProcessSetCookies: Rejecting commentURL value '%s'\n",
-				    cur_cookie->commentURL));
-			FREE(cur_cookie->commentURL);
-		    }
-		}
-	    } else if (len == 6 && !strncasecomp(attr_start, "domain", 6)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat domain. - FM
-		     */
-		    !(cur_cookie->flags & COOKIE_FLAG_DOMAIN_SET)) {
-		    length -= strlen(cur_cookie->domain);
-		    /*
-		     *	If the value does not have a lead dot,
-		     *	but does have an embedded dot, and is
-		     *	not an exact match to the hostname, nor
-		     *	is a numeric IP address, add a lead dot.
-		     *	Otherwise, use the value as is. - FM
-		     *	(domains - case insensitive).
-		     */
-		    if (value[0] != '.' && value[0] != '\0' &&
-			value[1] != '\0' && strcasecomp(value, hostname)) {
-			char *ptr = strchr(value, '.');
-			if (ptr != NULL && ptr[1] != '\0') {
-			    ptr = value;
-			    while (*ptr == '.' ||
-				   isdigit(UCH(*ptr)))
-				ptr++;
-			    if (*ptr != '\0') {
-				CTRACE((tfp,
-	       "LYProcessSetCookies: Adding lead dot for domain value '%s'\n",
-					    value));
-				StrAllocCopy(cur_cookie->domain, ".");
-				StrAllocCat(cur_cookie->domain, value);
-			    } else {
-				StrAllocCopy(cur_cookie->domain, value);
-			    }
-			} else {
-			    StrAllocCopy(cur_cookie->domain, value);
-			}
-		    } else {
-			StrAllocCopy(cur_cookie->domain, value);
-		    }
-		    length += strlen(cur_cookie->domain);
-		    cur_cookie->flags |= COOKIE_FLAG_DOMAIN_SET;
-		}
-	    } else if (len == 4 && !strncasecomp(attr_start, "path", 4)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat path. - FM
-		     */
-		    !(cur_cookie->flags & COOKIE_FLAG_PATH_SET)) {
-		    length -= strlen(cur_cookie->path);
-		    StrAllocCopy(cur_cookie->path, value);
-		    length += (cur_cookie->pathlen = strlen(cur_cookie->path));
-		    cur_cookie->flags |= COOKIE_FLAG_PATH_SET;
-		}
-	    } else if (len == 4 && !strncasecomp(attr_start, "port", 4)) {
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat port. - FM
-		     */
-		    cur_cookie->PortList == NULL) {
-		    char *cp = value;
-		    while ((*cp != '\0') &&
-			   (isdigit(UCH(*cp)) ||
-			    *cp == ',' || *cp == ' ')) {
-			cp++;
-		    }
-		    if (*cp == '\0' && port_matches(port, value)) {
-			StrAllocCopy(cur_cookie->PortList, value);
-			length += strlen(cur_cookie->PortList);
-			known_attr = YES;
-		    } else {
-			known_attr = NO;
-		    }
-		} else if (cur_cookie != NULL) {
-		    /*
-		     *	Don't process a repeat port. - FM
-		     */
-		    if (cur_cookie->PortList == NULL) {
-			HTSprintf0(&(cur_cookie->PortList), "%d", port);
-			length += strlen(cur_cookie->PortList);
-		    }
-		    known_attr = YES;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "version", 7)) {
-		known_attr = YES;
-		if (cur_cookie != NULL && value &&
-		    /*
-		     *	Don't process a repeat version. - FM
-		     */
-		    cur_cookie->version < 1) {
-		    int temp = strtol(value, NULL, 10);
-		    if (errno != -ERANGE) {
-			cur_cookie->version = temp;
-		    }
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "max-age", 7)) {
-		known_attr = YES;
-		if ((cur_cookie != NULL) && !MaxAgeAttrSet && value) {
-		    int temp = strtol(value, NULL, 10);
-		    cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
-		    if (errno == -ERANGE) {
-			cur_cookie->expires = (time_t)0;
-		    } else {
-			cur_cookie->expires = (time(NULL) + temp);
-		    }
-		    MaxAgeAttrSet = TRUE;
-		}
-	    } else if (len == 7 && !strncasecomp(attr_start, "expires", 7)) {
-		/*
-		 *  Convert an 'expires' attribute value if we haven't
-		 *  received a 'max-age'.  Note that 'expires' should not
-		 *  be used in Version 1 cookies, but it might be used for
-		 *  "backward compatibility", and, in turn, ill-informed
-		 *  people surely would start using it instead of, rather
-		 *  than in addition to, 'max-age'. - FM
-		 */
-		known_attr = YES;
-		if ((cur_cookie != NULL) && !(MaxAgeAttrSet) &&
-		    !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) {
-		    if (value) {
-			cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
-			cur_cookie->expires = LYmktime(value, FALSE);
-		    }
-		}
-	    }
+	    char *value = alloc_attr_value(value_start, value_end);
+
+	    parse_flags = parse_attribute (parse_flags,
+					   cur_cookie,
+					   &cookie_len,
+					   attr_start,
+					   (attr_end - attr_start),
+					   value,
+					   address,
+					   hostname,
+					   port);
 
 	    /*
-	     *	If none of the above comparisons succeeded, and we have
-	     *	a value, then we have an unknown pair of the form 'foo=bar',
-	     *	which means it's time to create a new cookie.  If we don't
-	     *	have a non-zero-length value, assume it's an error or a
-	     *	new, unknown attribute which doesn't take a value, and
-	     *	ignore it. - FM
-	     */
-	    /* if (!known_attr && value_end > value_start) */
-
-	    /* Is there any reason we don't want to accept cookies with
-	     * no value?  This seems to be needed for sites that reset a
-	     * cookie by nulling out the value.  If this causes problems,
-	     * we can go back to the original behavior above.  - BJP
-	     *
-	     * Presence of value is now needed (indicated normally by '='),
-	     * but it can now be an empty string. - kw 1999-06-24
+	     * Presence of value is needed (indicated normally by '='),
+	     * but it can be an empty string. - kw 1999-06-24
 	     */
-	    if (!known_attr && value && value_end >= value_start) {
+	    if (!(parse_flags & FLAGS_KNOWN_ATTR)
+	      && value
+	      && value_end >= value_start) {
 		/*
 		 *  If we've started a cookie, and it's not too big,
 		 *  save it in the CombinedCookies list. - FM
 		 */
-		if (length <= max_cookies_buffer && cur_cookie != NULL) {
+		if (cookie_len <= max_cookies_buffer
+		 && cur_cookie != NULL) {
 		    /*
 		     *	If we had a Set-Cookie2 header, make sure
 		     *	the version is at least 1, and mark it for
@@ -1833,17 +1648,18 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		 *  Start a new cookie. - FM
 		 */
 		cur_cookie = newCookie();
-		length = 0;
+		NumCookies++;
+		cookie_len = 0;
 		MemAllocCopy(&(cur_cookie->name), attr_start, attr_end);
-		length += strlen(cur_cookie->name);
+		cookie_len += strlen(cur_cookie->name);
 		MemAllocCopy(&(cur_cookie->value), value_start, value_end);
-		length += strlen(cur_cookie->value);
+		cookie_len += strlen(cur_cookie->value);
 		StrAllocCopy(cur_cookie->domain, hostname);
-		length += strlen(cur_cookie->domain);
+		cookie_len += strlen(cur_cookie->domain);
 		StrAllocCopy(cur_cookie->path, path);
-		length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+		cookie_len += (cur_cookie->pathlen = strlen(cur_cookie->path));
 		cur_cookie->port = port;
-		MaxAgeAttrSet = FALSE;
+		parse_flags = 0;
 		cur_cookie->quoted = Quoted;
 		Quoted = FALSE;
 	    }
@@ -1854,7 +1670,7 @@ PRIVATE void LYProcessSetCookies ARGS6(
     /*
      *	Handle the final Set-Cookie cookie if within length limit. - FM
      */
-    if (NumCookies <= max_cookies_domain && length <= max_cookies_buffer && cur_cookie != NULL) {
+    if (NumCookies <= max_cookies_domain && cookie_len <= max_cookies_buffer && cur_cookie != NULL) {
 	if (SetCookie2 != NULL) {
 	    if (cur_cookie->version < 1) {
 		cur_cookie->version = 1;
@@ -1867,8 +1683,8 @@ PRIVATE void LYProcessSetCookies ARGS6(
 		    (cur_cookie->name ? cur_cookie->name : "[no name]"),
 		    (cur_cookie->value ? cur_cookie->value : "[no value]")));
 	CTRACE((tfp, "                     due to excessive %s%s%s\n",
-		    (length > max_cookies_buffer ? "length" : ""),
-		    (length > max_cookies_buffer && NumCookies > max_cookies_domain ? " and " : ""),
+		    (cookie_len > max_cookies_buffer ? "length" : ""),
+		    (cookie_len > max_cookies_buffer && NumCookies > max_cookies_domain ? " and " : ""),
 		    (NumCookies > max_cookies_domain ? "number!\n" : "!\n")));
 	freeCookie(cur_cookie);
 	cur_cookie = NULL;
@@ -1987,7 +1803,7 @@ PUBLIC void LYSetCookie ARGS3(
 **  Entry function from creating a Cookie: request header
 **  if needed. - AK & FM
 */
-PUBLIC char * LYCookie ARGS4(
+PUBLIC char * LYAddCookieHeader ARGS4(
 	char *,		hostname,
 	char *,		path,
 	int,		port,
@@ -2013,17 +1829,15 @@ PUBLIC char * LYCookie ARGS4(
 	if (de != NULL) {
 	    if (!HTList_isEmpty(de->cookie_list)) {
 		/*
-		 *  Scan the domain's cookie_list for
-		 *  any cookies we should include in
-		 *  our request header.
+		 * Scan the domain's cookie_list for any cookies we should
+		 * include in our request header.
 		 */
 		header = scan_cookie_sublist(hostname, path, port,
 					     de->cookie_list, header, secure);
 	    } else if (de->bv == QUERY_USER && de->invcheck_bv == DEFAULT_INVCHECK_BV) {
 		/*
-		 *  No cookies in this domain, and no default
-		 *  accept/reject choice was set by the user,
-		 *  so delete the domain. - FM
+		 * No cookies in this domain, and no default accept/reject
+		 * choice was set by the user, so delete the domain.  - FM
 		 */
 		FREE(de->domain);
 		HTList_delete(de->cookie_list);
@@ -2345,203 +2159,185 @@ PRIVATE int LYHandleCookies ARGS4 (
 	/*
 	 *  Seek the domain in the domain_list structure. - FM
 	 */
-	for (dl = domain_list; dl != NULL; dl = dl->next) {
-	    de = dl->object;
-	    if (!(de && de->domain))
-		/*
-		 *  First object in the list always is empty. - FM
-		 */
-		continue;
-	    if (!strcasecomp(domain, de->domain)) {
-		FREE(domain);
+	if ((de = find_domain_entry(domain)) != NULL) {
+	    FREE(domain);
+	    /*
+	     *  We found the domain.  Check
+	     *  whether a lynxID is present. - FM
+	     */
+	    if (lynxID) {
 		/*
-		 *  We found the domain.  Check
-		 *  whether a lynxID is present. - FM
+		 *	Seek and delete the cookie with this lynxID
+		 *	in the domain's cookie list. - FM
 		 */
-		if (lynxID) {
-		    /*
-		     *	Seek and delete the cookie with this lynxID
-		     *	in the domain's cookie list. - FM
-		     */
-		    for (cl = de->cookie_list; cl != NULL; cl = cl->next) {
-			if ((co = (cookie *)cl->object) == NULL)
-			    /*
-			     *	First object is always empty. - FM
-			     */
-			    continue;
-			if (!strcmp(lynxID, co->lynxID)) {
+		for (cl = de->cookie_list; cl != NULL; cl = cl->next) {
+		    if ((co = (cookie *)cl->object) == NULL)
+			/*
+			 *	First object is always empty. - FM
+			 */
+			continue;
+		    if (!strcmp(lynxID, co->lynxID)) {
+			/*
+			 *	We found the cookie.
+			 *	Delete it if confirmed. - FM
+			 */
+			if (HTConfirm(DELETE_COOKIE_CONFIRMATION) == FALSE)
+			{
+			    FREE(lynxID);
+			    HTNoDataOK = 1;
+			    return(HT_NO_DATA);
+			}
+			HTList_removeObject(de->cookie_list, co);
+			freeCookie(co);
+			co = NULL;
+			total_cookies--;
+			if ((de->bv == QUERY_USER &&
+			     HTList_isEmpty(de->cookie_list)) &&
+			    HTConfirm(DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
 			    /*
-			     *	We found the cookie.
-			     *	Delete it if confirmed. - FM
+			     *  No more cookies in this domain, no
+			     *  default accept/reject choice was set
+			     *  by the user, and got confirmation on
+			     *  deleting the domain, so do it. - FM
 			     */
-			    if (HTConfirm(DELETE_COOKIE_CONFIRMATION) == FALSE)
-			    {
-				FREE(lynxID);
-				HTNoDataOK = 1;
-				return(HT_NO_DATA);
-			    }
-			    HTList_removeObject(de->cookie_list, co);
-			    freeCookie(co);
-			    co = NULL;
-			    total_cookies--;
-			    if ((de->bv == QUERY_USER &&
-				 HTList_isEmpty(de->cookie_list)) &&
-				HTConfirm(DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
-				/*
-				 *  No more cookies in this domain, no
-				 *  default accept/reject choice was set
-				 *  by the user, and got confirmation on
-				 *  deleting the domain, so do it. - FM
-				 */
-				FREE(de->domain);
-				HTList_delete(de->cookie_list);
-				de->cookie_list = NULL;
-				HTList_removeObject(domain_list, de);
-				FREE(de);
-				HTProgress(DOMAIN_EATEN);
-			    } else {
-				HTProgress(COOKIE_EATEN);
-			    }
-			    LYSleepMsg();
-			    HTNoDataOK = 1;
-			    break;
+			    FREE(de->domain);
+			    HTList_delete(de->cookie_list);
+			    de->cookie_list = NULL;
+			    HTList_removeObject(domain_list, de);
+			    FREE(de);
+			    HTProgress(DOMAIN_EATEN);
+			} else {
+			    HTProgress(COOKIE_EATEN);
 			}
+			LYSleepMsg();
+			HTNoDataOK = 1;
+			break;
 		    }
+		}
+	    } else {
+		/*
+		 * Prompt whether to delete all of the cookies in this domain,
+		 * or the domain if no cookies in it, or to change its 'allow'
+		 * setting, or to cancel, and then act on the user's response. 
+		 * - FM
+		 */
+		if (HTList_isEmpty(de->cookie_list)) {
+		    _statusline(DELETE_DOMAIN_SET_ALLOW_OR_CANCEL);
 		} else {
-		    /*
-		     *	Prompt whether to delete all of the cookies in
-		     *	this domain, or the domain if no cookies in it,
-		     *	or to change its 'allow' setting, or to cancel,
-		     *	and then act on the user's response. - FM
-		     */
-		    if (HTList_isEmpty(de->cookie_list)) {
-			_statusline(DELETE_DOMAIN_SET_ALLOW_OR_CANCEL);
-		    } else {
-			_statusline(DELETE_COOKIES_SET_ALLOW_OR_CANCEL);
-		    }
-		    HTNoDataOK = 1;
-		    while (1) {
-			ch = LYgetch_single();
+		    _statusline(DELETE_COOKIES_SET_ALLOW_OR_CANCEL);
+		}
+		HTNoDataOK = 1;
+		while (1) {
+		    ch = LYgetch_single();
 #ifdef VMS
-			if (HadVMSInterrupt) {
-			    HadVMSInterrupt = FALSE;
-			    ch = 'C';
-			}
+		    if (HadVMSInterrupt) {
+			HadVMSInterrupt = FALSE;
+			ch = 'C';
+		    }
 #endif /* VMS */
-			switch(ch) {
-			    case 'A':
-				/*
-				 *  Set to accept all cookies
-				 *  from this domain. - FM
-				 */
-				de->bv = ACCEPT_ALWAYS;
-				HTUserMsg2(ALWAYS_ALLOWING_COOKIES,
-					      de->domain);
-				return(HT_NO_DATA);
-
-			    case 'C':
-				/*
-				 *  Cancelled. - FM
-				 */
-			      reject:
-				HTUserMsg(CANCELLED);
-				return(HT_NO_DATA);
-
-			    case 'D':
-				if (HTList_isEmpty(de->cookie_list)) {
-				    /*
-				     *	We had an empty domain, so we
-				     *	were asked to delete it. - FM
-				     */
-				    FREE(de->domain);
-				    HTList_delete(de->cookie_list);
-				    de->cookie_list = NULL;
-				    HTList_removeObject(domain_list, de);
-				    FREE(de);
-				    HTProgress(DOMAIN_EATEN);
-				    LYSleepMsg();
-				    break;
-				}
+		    switch(ch) {
+		    case 'A':
+			/*
+			 * Set to accept all cookies from this domain.  - FM
+			 */
+			de->bv = ACCEPT_ALWAYS;
+			HTUserMsg2(ALWAYS_ALLOWING_COOKIES, de->domain);
+			return(HT_NO_DATA);
+
+		    case 'C':
+			/*
+			 * Cancelled.  - FM
+			 */
+		      reject:
+			HTUserMsg(CANCELLED);
+			return(HT_NO_DATA);
+
+		    case 'D':
+			if (HTList_isEmpty(de->cookie_list)) {
+			    /*
+			     * We had an empty domain, so we were asked to
+			     * delete it.  - FM
+			     */
+			    FREE(de->domain);
+			    HTList_delete(de->cookie_list);
+			    de->cookie_list = NULL;
+			    HTList_removeObject(domain_list, de);
+			    FREE(de);
+			    HTProgress(DOMAIN_EATEN);
+			    LYSleepMsg();
+			    break;
+			}
 Delete_all_cookies_in_domain:
-				/*
-				 *  Delete all cookies in this domain. - FM
-				 */
-				cl = de->cookie_list;
-				while (cl) {
-				    next = cl->next;
-				    co = cl->object;
-				    if (co) {
-					HTList_removeObject(de->cookie_list,
-							    co);
-					freeCookie(co);
-					co = NULL;
-					total_cookies--;
-				    }
-				    cl = next;
-				}
-				HTProgress(DOMAIN_COOKIES_EATEN);
-				LYSleepMsg();
-				/*
-				 *  If a default accept/reject
-				 *  choice is set, we're done. - FM
-				 */
-				if (de->bv != QUERY_USER)
-				    return(HT_NO_DATA);
-				/*
-				 *  Check whether to delete
-				 *  the empty domain. - FM
-				 */
-				if(HTConfirm(
-					DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
-				    FREE(de->domain);
-				    HTList_delete(de->cookie_list);
-				    de->cookie_list = NULL;
-				    HTList_removeObject(domain_list, de);
-				    FREE(de);
-				    HTProgress(DOMAIN_EATEN);
-				    LYSleepMsg();
-				}
-				break;
-
-			    case 'P':
-				/*
-				 *  Set to prompt for cookie acceptance
-				 *  from this domain. - FM
-				 */
-				de->bv = QUERY_USER;
-				HTUserMsg2(PROMPTING_TO_ALLOW_COOKIES,
-					   de->domain);
-				return(HT_NO_DATA);
-
-			    case 'V':
-				/*
-				 *  Set to reject all cookies
-				 *  from this domain. - FM
-				 */
-				de->bv = REJECT_ALWAYS;
-				HTUserMsg2(NEVER_ALLOWING_COOKIES,
-					   de->domain);
-				if ((!HTList_isEmpty(de->cookie_list)) &&
-				    HTConfirm(DELETE_ALL_COOKIES_IN_DOMAIN))
-				    goto Delete_all_cookies_in_domain;
-				return(HT_NO_DATA);
-
-			    default:
-				if (LYCharIsINTERRUPT(ch))
-				    goto reject;
-				continue;
+			/*
+			 * Delete all cookies in this domain.  - FM
+			 */
+			cl = de->cookie_list;
+			while (cl) {
+			    next = cl->next;
+			    co = cl->object;
+			    if (co) {
+				HTList_removeObject(de->cookie_list, co);
+				freeCookie(co);
+				co = NULL;
+				total_cookies--;
+			    }
+			    cl = next;
+			}
+			HTProgress(DOMAIN_COOKIES_EATEN);
+			LYSleepMsg();
+			/*
+			 * If a default accept/reject choice is set, we're
+			 * done.  - FM
+			 */
+			if (de->bv != QUERY_USER)
+			    return(HT_NO_DATA);
+			/*
+			 * Check whether to delete the empty domain.  - FM
+			 */
+			if (HTConfirm(DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
+			    FREE(de->domain);
+			    HTList_delete(de->cookie_list);
+			    de->cookie_list = NULL;
+			    HTList_removeObject(domain_list, de);
+			    FREE(de);
+			    HTProgress(DOMAIN_EATEN);
+			    LYSleepMsg();
 			}
 			break;
+
+		    case 'P':
+			/*
+			 * Set to prompt for cookie acceptance from this
+			 * domain.  - FM
+			 */
+			de->bv = QUERY_USER;
+			HTUserMsg2(PROMPTING_TO_ALLOW_COOKIES, de->domain);
+			return(HT_NO_DATA);
+
+		    case 'V':
+			/*
+			 * Set to reject all cookies from this domain.  - FM
+			 */
+			de->bv = REJECT_ALWAYS;
+			HTUserMsg2(NEVER_ALLOWING_COOKIES, de->domain);
+			if ((!HTList_isEmpty(de->cookie_list)) &&
+			    HTConfirm(DELETE_ALL_COOKIES_IN_DOMAIN))
+			    goto Delete_all_cookies_in_domain;
+			return(HT_NO_DATA);
+
+		    default:
+			if (LYCharIsINTERRUPT(ch))
+			    goto reject;
+			continue;
 		    }
+		    break;
 		}
-		break;
 	    }
 	}
 	if (HTList_isEmpty(domain_list)) {
 	    /*
-	     *	There are no more domains left.
-	     *	Don't delete the domain_list, otherwise
-	     *  atexit may be called multiple times. - kw
+	     * There are no more domains left.  Don't delete the domain_list,
+	     * otherwise atexit may be called multiple times.  - kw
 	     */
 	    HTProgress(ALL_COOKIES_EATEN);
 	    LYSleepMsg();
@@ -2552,11 +2348,10 @@ Delete_all_cookies_in_domain:
     }
 
     /*
-     *	If we get to here, it was a LYNXCOOKIE:/ URL
-     *	for creating and displaying the Cookie Jar Page,
-     *	or we didn't find the domain or cookie in a
-     *	deletion request.  Set up an HTML stream and
-     *	return an updated Cookie Jar Page. - FM
+     * If we get to here, it was a LYNXCOOKIE:/ URL for creating and displaying
+     * the Cookie Jar Page, or we didn't find the domain or cookie in a
+     * deletion request.  Set up an HTML stream and return an updated Cookie
+     * Jar Page.  - FM
      */
     target = HTStreamStack(format_in,
 			   format_out,
@@ -2570,8 +2365,8 @@ Delete_all_cookies_in_domain:
     }
 
     /*
-     *	Load HTML strings into buf and pass buf
-     *	to the target for parsing and rendering. - FM
+     * Load HTML strings into buf and pass buf to the target for parsing and
+     * rendering.  - FM
      */
 #define PUTS(buf)    (*target->isa->put_block)(target, buf, strlen(buf))
 
@@ -2607,15 +2402,15 @@ Delete_all_cookies_in_domain:
 		      de->domain, de->domain, de->domain);
 	PUTS(buf);
 	switch (de->bv) {
-	    case (ACCEPT_ALWAYS):
-		HTSprintf0(&buf, COOKIES_ALWAYS_ALLOWED);
-		break;
-	    case (REJECT_ALWAYS):
-		HTSprintf0(&buf, COOKIES_NEVER_ALLOWED);
-		break;
-	    case (QUERY_USER):
-		HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT);
-		break;
+	case (ACCEPT_ALWAYS):
+	    HTSprintf0(&buf, COOKIES_ALWAYS_ALLOWED);
+	    break;
+	case (REJECT_ALWAYS):
+	    HTSprintf0(&buf, COOKIES_NEVER_ALLOWED);
+	    break;
+	case (QUERY_USER):
+	    HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT);
+	    break;
 	}
 	PUTS(buf);
 	HTSprintf0(&buf, "\n");
@@ -2745,17 +2540,14 @@ Delete_all_cookies_in_domain:
 **      invcheck behavior, as well as accept/reject behavior. - BJP
 */
 
-PUBLIC void cookie_domain_flag_set ARGS2(
+PRIVATE void cookie_domain_flag_set ARGS2(
 	char *,		domainstr,
 	int,		flag)
 {
     domain_entry *de = NULL;
-    domain_entry *de2 = NULL;
-    HTList *hl = NULL;
     char **str = typecalloc(char *);
     char *dstr = NULL;
     char *strsmall = NULL;
-    int isexisting = FALSE;
 
     if (str == NULL) {
 	HTAlwaysAlert(gettext("Internal"),
@@ -2764,10 +2556,8 @@ PUBLIC void cookie_domain_flag_set ARGS2(
     }
 
     /*
-     * Is this the first domain we're handling?  If so, initialize
-     * domain_list.
+     * Is this the first domain we're handling?  If so, initialize domain_list.
      */
-
     if (domain_list == NULL) {
 #ifdef LY_FIND_LEAKS
 	atexit(LYCookieJar_free);
@@ -2789,67 +2579,53 @@ PUBLIC void cookie_domain_flag_set ARGS2(
 
 	/*
 	 * Check the list of existing domains to see if this is a
-	 * re-setting of an already existing domains -- if so, just
+	 * re-setting of an already existing domain -- if so, just
 	 * change the behavior, if not, create a new domain entry.
 	 */
 
-	for (hl = domain_list; hl != NULL; hl = hl->next) {
-	    de2 = (domain_entry *)hl->object;
-	    if ((de2 != NULL && de2->domain != NULL) &&
-		!strcasecomp(strsmall, de2->domain)) {
-			isexisting = TRUE;
-			break;
-	    } else {
-		isexisting = FALSE;
-	    }
-	}
-
-	if(!isexisting) {
+	if ((de = find_domain_entry(strsmall)) == NULL) {
 	    de = typecalloc(domain_entry);
-
 	    if (de == NULL)
 		    outofmem(__FILE__, "cookie_domain_flag_set");
 
+	    de->bv = ACCEPT_ALWAYS;
+	    de->invcheck_bv = INVCHECK_QUERY;
+
 	    switch(flag) {
-		case (FLAG_ACCEPT_ALWAYS): de->bv = ACCEPT_ALWAYS;
-					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
-					   break;
-		case (FLAG_REJECT_ALWAYS): de->bv = REJECT_ALWAYS;
-					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
-					   break;
-		case (FLAG_QUERY_USER):    de->bv = QUERY_USER;
-					   de->invcheck_bv = DEFAULT_INVCHECK_BV;
-					   break;
-		case (FLAG_INVCHECK_QUERY): de->invcheck_bv = INVCHECK_QUERY;
-					    de->bv = QUERY_USER;
-					    break;
-		case (FLAG_INVCHECK_STRICT): de->invcheck_bv = INVCHECK_STRICT;
-					     de->bv = QUERY_USER;
-					    break;
-		case (FLAG_INVCHECK_LOOSE): de->invcheck_bv = INVCHECK_LOOSE;
-					    de->bv = QUERY_USER;
-					    break;
+	    case (FLAG_ACCEPT_ALWAYS):	de->invcheck_bv = DEFAULT_INVCHECK_BV;
+					break;
+	    case (FLAG_REJECT_ALWAYS):	de->invcheck_bv = DEFAULT_INVCHECK_BV;
+					break;
+	    case (FLAG_QUERY_USER):	de->invcheck_bv = DEFAULT_INVCHECK_BV;
+					break;
+	    case (FLAG_INVCHECK_QUERY): de->bv = QUERY_USER;
+					break;
+	    case (FLAG_INVCHECK_STRICT): de->bv = QUERY_USER;
+					break;
+	    case (FLAG_INVCHECK_LOOSE): de->bv = QUERY_USER;
+					break;
 	    }
 
 	    StrAllocCopy(de->domain, strsmall);
 	    de->cookie_list = HTList_new();
 	    HTList_appendObject(domain_list, de);
-	} else {
-	    switch(flag) {
-		case (FLAG_ACCEPT_ALWAYS): de2->bv = ACCEPT_ALWAYS;
-					   break;
-		case (FLAG_REJECT_ALWAYS): de2->bv = REJECT_ALWAYS;
-					   break;
-		case (FLAG_QUERY_USER): de2->bv = QUERY_USER;
-					   break;
-		case (FLAG_INVCHECK_QUERY): de2->invcheck_bv = INVCHECK_QUERY;
-					   break;
-		case (FLAG_INVCHECK_STRICT): de2->invcheck_bv = INVCHECK_STRICT;
-					   break;
-		case (FLAG_INVCHECK_LOOSE): de2->invcheck_bv = INVCHECK_LOOSE;
-					   break;
-	    }
 	}
+	switch(flag) {
+	case (FLAG_ACCEPT_ALWAYS):	de->bv = ACCEPT_ALWAYS;
+					break;
+	case (FLAG_REJECT_ALWAYS):	de->bv = REJECT_ALWAYS;
+					break;
+	case (FLAG_QUERY_USER):		de->bv = QUERY_USER;
+					break;
+	case (FLAG_INVCHECK_QUERY):	de->invcheck_bv = INVCHECK_QUERY;
+					break;
+	case (FLAG_INVCHECK_STRICT):    de->invcheck_bv = INVCHECK_STRICT;
+					break;
+	case (FLAG_INVCHECK_LOOSE):	de->invcheck_bv = INVCHECK_LOOSE;
+					break;
+	}
+	CTRACE((tfp, "cookie_domain_flag_set (%s, bv=%d, invcheck_bv=%d)\n",
+		     strsmall, de->bv, de->invcheck_bv));
     }
 
     FREE(strsmall);