cookie.c (18108B)
1 /* $Id$ */ 2 3 /* 4 * References for version 0 cookie: 5 * [NETACAPE] http://www.netscape.com/newsref/std/cookie_spec.html 6 * 7 * References for version 1 cookie: 8 * [RFC 2109] http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt 9 * [DRAFT 12] http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-12.txt 10 */ 11 12 #include "fm.h" 13 #include "html.h" 14 15 #ifdef USE_COOKIE 16 #include <time.h> 17 #include "local.h" 18 #include "regex.h" 19 #include "myctype.h" 20 21 static int is_saved = 1; 22 23 #define contain_no_dots(p, ep) (total_dot_number((p),(ep),1)==0) 24 25 static int 26 total_dot_number(char *p, char *ep, int max_count) 27 { 28 int count = 0; 29 if (!ep) 30 ep = p + strlen(p); 31 32 for (; p < ep && count < max_count; p++) { 33 if (*p == '.') 34 count++; 35 } 36 return count; 37 } 38 39 40 static char * 41 domain_match(char *host, char *domain) 42 { 43 int m0, m1; 44 45 /* [RFC 2109] s. 2, "domain-match", case 1 46 * (both are IP and identical) 47 */ 48 regexCompile("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+", 0); 49 m0 = regexMatch(host, -1, 1); 50 m1 = regexMatch(domain, -1, 1); 51 if (m0 && m1) { 52 if (strcasecmp(host, domain) == 0) 53 return host; 54 } 55 else if (!m0 && !m1) { 56 int offset; 57 char *domain_p; 58 /* 59 * "." match all domains (w3m only), 60 * and ".local" match local domains ([DRAFT 12] s. 2) 61 */ 62 if (strcasecmp(domain, ".") == 0 || strcasecmp(domain, ".local") == 0) { 63 offset = strlen(host); 64 domain_p = &host[offset]; 65 if (domain[1] == '\0' || contain_no_dots(host, domain_p)) 66 return domain_p; 67 } 68 /* 69 * special case for domainName = .hostName 70 * see nsCookieService.cpp in Firefox. 71 */ 72 else if (domain[0] == '.' && strcasecmp(host, &domain[1]) == 0) { 73 return host; 74 } 75 /* [RFC 2109] s. 2, cases 2, 3 */ 76 else { 77 offset = (domain[0] != '.') ? 0 : strlen(host) - strlen(domain); 78 domain_p = &host[offset]; 79 if (offset >= 0 && strcasecmp(domain_p, domain) == 0) 80 return domain_p; 81 } 82 } 83 return NULL; 84 } 85 86 87 static struct portlist * 88 make_portlist(Str port) 89 { 90 struct portlist *first = NULL, *pl; 91 char *p; 92 Str tmp = Strnew(); 93 94 p = port->ptr; 95 while (*p) { 96 while (*p && !IS_DIGIT(*p)) 97 p++; 98 Strclear(tmp); 99 while (*p && IS_DIGIT(*p)) 100 Strcat_char(tmp, *(p++)); 101 if (tmp->length == 0) 102 break; 103 pl = New(struct portlist); 104 pl->port = atoi(tmp->ptr); 105 pl->next = first; 106 first = pl; 107 } 108 return first; 109 } 110 111 static Str 112 portlist2str(struct portlist *first) 113 { 114 struct portlist *pl; 115 Str tmp; 116 117 tmp = Sprintf("%d", first->port); 118 for (pl = first->next; pl; pl = pl->next) 119 Strcat(tmp, Sprintf(", %d", pl->port)); 120 return tmp; 121 } 122 123 static int 124 port_match(struct portlist *first, int port) 125 { 126 struct portlist *pl; 127 128 for (pl = first; pl; pl = pl->next) { 129 if (pl->port == port) 130 return 1; 131 } 132 return 0; 133 } 134 135 static void 136 check_expired_cookies(void) 137 { 138 struct cookie *p, *p1; 139 time_t now = time(NULL); 140 141 if (!First_cookie) 142 return; 143 144 if (First_cookie->expires != (time_t) - 1 && First_cookie->expires < now) { 145 if (!(First_cookie->flag & COO_DISCARD)) 146 is_saved = 0; 147 First_cookie = First_cookie->next; 148 } 149 150 for (p = First_cookie; p && p->next; p = p1) { 151 p1 = p->next; 152 if (p1->expires != (time_t) - 1 && p1->expires < now) { 153 if (!(p1->flag & COO_DISCARD)) 154 is_saved = 0; 155 p->next = p1->next; 156 p1 = p; 157 } 158 } 159 } 160 161 static Str 162 make_cookie(struct cookie *cookie) 163 { 164 Str tmp = Strdup(cookie->name); 165 Strcat_char(tmp, '='); 166 Strcat(tmp, cookie->value); 167 return tmp; 168 } 169 170 static int 171 match_cookie(ParsedURL *pu, struct cookie *cookie, char *domainname) 172 { 173 if (!domainname) 174 return 0; 175 176 if (!domain_match(domainname, cookie->domain->ptr)) 177 return 0; 178 if (strncmp(cookie->path->ptr, pu->file, cookie->path->length) != 0) 179 return 0; 180 #ifdef USE_SSL 181 if (cookie->flag & COO_SECURE && pu->scheme != SCM_HTTPS) 182 return 0; 183 #else /* not USE_SSL */ 184 if (cookie->flag & COO_SECURE) 185 return 0; 186 #endif /* not USE_SSL */ 187 if (cookie->portl && !port_match(cookie->portl, pu->port)) 188 return 0; 189 190 return 1; 191 } 192 193 struct cookie * 194 get_cookie_info(Str domain, Str path, Str name) 195 { 196 struct cookie *p; 197 198 for (p = First_cookie; p; p = p->next) { 199 if (Strcasecmp(p->domain, domain) == 0 && 200 Strcmp(p->path, path) == 0 && Strcasecmp(p->name, name) == 0) 201 return p; 202 } 203 return NULL; 204 } 205 206 Str 207 find_cookie(ParsedURL *pu) 208 { 209 Str tmp; 210 struct cookie *p, *p1, *fco = NULL; 211 int version = 0; 212 char *fq_domainname, *domainname; 213 214 fq_domainname = FQDN(pu->host); 215 check_expired_cookies(); 216 for (p = First_cookie; p; p = p->next) { 217 domainname = (p->version == 0) ? fq_domainname : pu->host; 218 if (p->flag & COO_USE && match_cookie(pu, p, domainname)) { 219 for (p1 = fco; p1 && Strcasecmp(p1->name, p->name); 220 p1 = p1->next) ; 221 if (p1) 222 continue; 223 p1 = New(struct cookie); 224 bcopy(p, p1, sizeof(struct cookie)); 225 p1->next = fco; 226 fco = p1; 227 if (p1->version > version) 228 version = p1->version; 229 } 230 } 231 232 if (!fco) 233 return NULL; 234 235 tmp = Strnew(); 236 if (version > 0) 237 Strcat(tmp, Sprintf("$Version=\"%d\"; ", version)); 238 239 Strcat(tmp, make_cookie(fco)); 240 for (p1 = fco->next; p1; p1 = p1->next) { 241 Strcat_charp(tmp, "; "); 242 Strcat(tmp, make_cookie(p1)); 243 if (version > 0) { 244 if (p1->flag & COO_PATH) 245 Strcat(tmp, Sprintf("; $Path=\"%s\"", p1->path->ptr)); 246 if (p1->flag & COO_DOMAIN) 247 Strcat(tmp, Sprintf("; $Domain=\"%s\"", p1->domain->ptr)); 248 if (p1->portl) 249 Strcat(tmp, 250 Sprintf("; $Port=\"%s\"", portlist2str(p1->portl))); 251 } 252 } 253 return tmp; 254 } 255 256 char *special_domain[] = { 257 ".com", ".edu", ".gov", ".mil", ".net", ".org", ".int", NULL 258 }; 259 260 int 261 check_avoid_wrong_number_of_dots_domain( Str domain ) 262 { 263 TextListItem *tl; 264 int avoid_wrong_number_of_dots_domain = FALSE; 265 266 if (Cookie_avoid_wrong_number_of_dots_domains && 267 Cookie_avoid_wrong_number_of_dots_domains->nitem > 0) { 268 for (tl = Cookie_avoid_wrong_number_of_dots_domains->first; 269 tl != NULL; tl = tl->next) { 270 if (domain_match(domain->ptr, tl->ptr)) { 271 avoid_wrong_number_of_dots_domain = TRUE; 272 break; 273 } 274 } 275 } 276 277 if (avoid_wrong_number_of_dots_domain == TRUE) { 278 return TRUE; 279 } else { 280 return FALSE; 281 } 282 } 283 284 int 285 add_cookie(ParsedURL *pu, Str name, Str value, 286 time_t expires, Str domain, Str path, 287 int flag, Str comment, int version, Str port, Str commentURL) 288 { 289 struct cookie *p; 290 char *domainname = (version == 0) ? FQDN(pu->host) : pu->host; 291 Str odomain = domain, opath = path; 292 struct portlist *portlist = NULL; 293 int use_security = !(flag & COO_OVERRIDE); 294 295 #define COOKIE_ERROR(err) if(!((err) & COO_OVERRIDE_OK) || use_security) return (err) 296 297 #ifdef DEBUG 298 fprintf(stderr, "host: [%s, %s] %d\n", pu->host, pu->file, flag); 299 fprintf(stderr, "cookie: [%s=%s]\n", name->ptr, value->ptr); 300 fprintf(stderr, "expires: [%s]\n", asctime(gmtime(&expires))); 301 if (domain) 302 fprintf(stderr, "domain: [%s]\n", domain->ptr); 303 if (path) 304 fprintf(stderr, "path: [%s]\n", path->ptr); 305 fprintf(stderr, "version: [%d]\n", version); 306 if (port) 307 fprintf(stderr, "port: [%s]\n", port->ptr); 308 #endif /* DEBUG */ 309 /* [RFC 2109] s. 4.3.2 case 2; but this (no request-host) shouldn't happen */ 310 if (!domainname) 311 return COO_ENODOT; 312 313 if (domain) { 314 char *dp; 315 /* [DRAFT 12] s. 4.2.2 (does not apply in the case that 316 * host name is the same as domain attribute for version 0 317 * cookie) 318 * I think that this rule has almost the same effect as the 319 * tail match of [NETSCAPE]. 320 */ 321 if (domain->ptr[0] != '.' && 322 (version > 0 || strcasecmp(domainname, domain->ptr) != 0)) 323 domain = Sprintf(".%s", domain->ptr); 324 325 if (version == 0) { 326 /* [NETSCAPE] rule */ 327 int n = total_dot_number(domain->ptr, 328 domain->ptr + domain->length, 329 3); 330 if (n < 2) { 331 if (! check_avoid_wrong_number_of_dots_domain(domain)) { 332 COOKIE_ERROR(COO_ESPECIAL); 333 } 334 } 335 else if (n == 2) { 336 char **sdomain; 337 int ok = 0; 338 for (sdomain = special_domain; !ok && *sdomain; sdomain++) { 339 int offset = domain->length - strlen(*sdomain); 340 if (offset >= 0 && 341 strcasecmp(*sdomain, &domain->ptr[offset]) == 0) 342 ok = 1; 343 } 344 if (!ok && ! check_avoid_wrong_number_of_dots_domain(domain)) { 345 COOKIE_ERROR(COO_ESPECIAL); 346 } 347 } 348 } 349 else { 350 /* [DRAFT 12] s. 4.3.2 case 2 */ 351 if (strcasecmp(domain->ptr, ".local") != 0 && 352 contain_no_dots(&domain->ptr[1], &domain->ptr[domain->length])) 353 COOKIE_ERROR(COO_ENODOT); 354 } 355 356 /* [RFC 2109] s. 4.3.2 case 3 */ 357 if (!(dp = domain_match(domainname, domain->ptr))) 358 COOKIE_ERROR(COO_EDOM); 359 /* [RFC 2409] s. 4.3.2 case 4 */ 360 /* Invariant: dp contains matched domain */ 361 if (version > 0 && !contain_no_dots(domainname, dp)) 362 COOKIE_ERROR(COO_EBADHOST); 363 } 364 if (path) { 365 /* [RFC 2109] s. 4.3.2 case 1 */ 366 if (version > 0 && strncmp(path->ptr, pu->file, path->length) != 0) 367 COOKIE_ERROR(COO_EPATH); 368 } 369 if (port) { 370 /* [DRAFT 12] s. 4.3.2 case 5 */ 371 portlist = make_portlist(port); 372 if (portlist && !port_match(portlist, pu->port)) 373 COOKIE_ERROR(COO_EPORT); 374 } 375 376 if (!domain) 377 domain = Strnew_charp(domainname); 378 if (!path) { 379 path = Strnew_charp(pu->file); 380 while (path->length > 0 && Strlastchar(path) != '/') 381 Strshrink(path, 1); 382 if (Strlastchar(path) == '/') 383 Strshrink(path, 1); 384 } 385 386 p = get_cookie_info(domain, path, name); 387 if (!p) { 388 p = New(struct cookie); 389 p->flag = 0; 390 if (default_use_cookie) 391 p->flag |= COO_USE; 392 p->next = First_cookie; 393 First_cookie = p; 394 } 395 396 copyParsedURL(&p->url, pu); 397 p->name = name; 398 p->value = value; 399 p->expires = expires; 400 p->domain = domain; 401 p->path = path; 402 p->comment = comment; 403 p->version = version; 404 p->portl = portlist; 405 p->commentURL = commentURL; 406 407 if (flag & COO_SECURE) 408 p->flag |= COO_SECURE; 409 else 410 p->flag &= ~COO_SECURE; 411 if (odomain) 412 p->flag |= COO_DOMAIN; 413 else 414 p->flag &= ~COO_DOMAIN; 415 if (opath) 416 p->flag |= COO_PATH; 417 else 418 p->flag &= ~COO_PATH; 419 if (flag & COO_DISCARD || p->expires == (time_t) - 1) { 420 p->flag |= COO_DISCARD; 421 } 422 else { 423 p->flag &= ~COO_DISCARD; 424 is_saved = 0; 425 } 426 427 check_expired_cookies(); 428 return 0; 429 } 430 431 struct cookie * 432 nth_cookie(int n) 433 { 434 struct cookie *p; 435 int i; 436 for (p = First_cookie, i = 0; p; p = p->next, i++) { 437 if (i == n) 438 return p; 439 } 440 return NULL; 441 } 442 443 #define str2charp(str) ((str)? (str)->ptr : "") 444 445 void 446 save_cookies(void) 447 { 448 struct cookie *p; 449 char *cookie_file; 450 FILE *fp; 451 452 check_expired_cookies(); 453 454 if (!First_cookie || is_saved || no_rc_dir) 455 return; 456 457 cookie_file = rcFile(COOKIE_FILE); 458 if (!(fp = fopen(cookie_file, "w"))) 459 return; 460 461 for (p = First_cookie; p; p = p->next) { 462 if (!(p->flag & COO_USE) || p->flag & COO_DISCARD) 463 continue; 464 fprintf(fp, "%s\t%s\t%s\t%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\n", 465 parsedURL2Str(&p->url)->ptr, 466 p->name->ptr, p->value->ptr, p->expires, 467 p->domain->ptr, p->path->ptr, p->flag, 468 p->version, str2charp(p->comment), 469 (p->portl) ? portlist2str(p->portl)->ptr : "", 470 str2charp(p->commentURL)); 471 } 472 fclose(fp); 473 chmod(cookie_file, S_IRUSR | S_IWUSR); 474 } 475 476 static Str 477 readcol(char **p) 478 { 479 Str tmp = Strnew(); 480 while (**p && **p != '\n' && **p != '\r' && **p != '\t') 481 Strcat_char(tmp, *((*p)++)); 482 if (**p == '\t') 483 (*p)++; 484 return tmp; 485 } 486 487 void 488 load_cookies(void) 489 { 490 struct cookie *cookie, *p; 491 FILE *fp; 492 Str line; 493 char *str; 494 495 if (!(fp = fopen(rcFile(COOKIE_FILE), "r"))) 496 return; 497 498 if (First_cookie) { 499 for (p = First_cookie; p->next; p = p->next) ; 500 } 501 else { 502 p = NULL; 503 } 504 for (;;) { 505 line = Strfgets(fp); 506 507 if (line->length == 0) 508 break; 509 str = line->ptr; 510 cookie = New(struct cookie); 511 cookie->next = NULL; 512 cookie->flag = 0; 513 cookie->version = 0; 514 cookie->expires = (time_t) - 1; 515 cookie->comment = NULL; 516 cookie->portl = NULL; 517 cookie->commentURL = NULL; 518 parseURL(readcol(&str)->ptr, &cookie->url, NULL); 519 if (!*str) 520 return; 521 cookie->name = readcol(&str); 522 if (!*str) 523 return; 524 cookie->value = readcol(&str); 525 if (!*str) 526 return; 527 cookie->expires = (time_t) atol(readcol(&str)->ptr); 528 if (!*str) 529 return; 530 cookie->domain = readcol(&str); 531 if (!*str) 532 return; 533 cookie->path = readcol(&str); 534 if (!*str) 535 return; 536 cookie->flag = atoi(readcol(&str)->ptr); 537 if (!*str) 538 return; 539 cookie->version = atoi(readcol(&str)->ptr); 540 if (!*str) 541 return; 542 cookie->comment = readcol(&str); 543 if (cookie->comment->length == 0) 544 cookie->comment = NULL; 545 if (!*str) 546 return; 547 cookie->portl = make_portlist(readcol(&str)); 548 if (!*str) 549 return; 550 cookie->commentURL = readcol(&str); 551 if (cookie->commentURL->length == 0) 552 cookie->commentURL = NULL; 553 554 if (p) 555 p->next = cookie; 556 else 557 First_cookie = cookie; 558 p = cookie; 559 } 560 561 fclose(fp); 562 } 563 564 void 565 initCookie(void) 566 { 567 load_cookies(); 568 check_expired_cookies(); 569 } 570 571 Buffer * 572 cookie_list_panel(void) 573 { 574 /* FIXME: gettextize? */ 575 Str src = Strnew_charp("<html><head><title>Cookies</title></head>" 576 "<body><center><b>Cookies</b></center>" 577 "<p><form method=internal action=cookie>"); 578 struct cookie *p; 579 int i; 580 char *tmp, tmp2[80]; 581 582 if (!use_cookie || !First_cookie) 583 return NULL; 584 585 Strcat_charp(src, "<ol>"); 586 for (p = First_cookie, i = 0; p; p = p->next, i++) { 587 tmp = html_quote(parsedURL2Str(&p->url)->ptr); 588 if (p->expires != (time_t) - 1) { 589 #ifdef HAVE_STRFTIME 590 strftime(tmp2, 80, "%a, %d %b %Y %H:%M:%S GMT", 591 gmtime(&p->expires)); 592 #else /* not HAVE_STRFTIME */ 593 struct tm *gmt; 594 static char *dow[] = { 595 "Sun ", "Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat " 596 }; 597 static char *month[] = { 598 "Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ", 599 "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " 600 }; 601 gmt = gmtime(&p->expires); 602 strcpy(tmp2, dow[gmt->tm_wday]); 603 sprintf(&tmp2[4], "%02d ", gmt->tm_mday); 604 strcpy(&tmp2[7], month[gmt->tm_mon]); 605 if (gmt->tm_year < 1900) 606 sprintf(&tmp2[11], "%04d %02d:%02d:%02d GMT", 607 (gmt->tm_year) + 1900, gmt->tm_hour, gmt->tm_min, 608 gmt->tm_sec); 609 else 610 sprintf(&tmp2[11], "%04d %02d:%02d:%02d GMT", 611 gmt->tm_year, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); 612 #endif /* not HAVE_STRFTIME */ 613 } 614 else 615 tmp2[0] = '\0'; 616 Strcat_charp(src, "<li>"); 617 Strcat_charp(src, "<h1><a href=\""); 618 Strcat_charp(src, tmp); 619 Strcat_charp(src, "\">"); 620 Strcat_charp(src, tmp); 621 Strcat_charp(src, "</a></h1>"); 622 623 Strcat_charp(src, "<table cellpadding=0>"); 624 if (!(p->flag & COO_SECURE)) { 625 Strcat_charp(src, "<tr><td width=\"80\"><b>Cookie:</b></td><td>"); 626 Strcat_charp(src, html_quote(make_cookie(p)->ptr)); 627 Strcat_charp(src, "</td></tr>"); 628 } 629 if (p->comment) { 630 Strcat_charp(src, "<tr><td width=\"80\"><b>Comment:</b></td><td>"); 631 Strcat_charp(src, html_quote(p->comment->ptr)); 632 Strcat_charp(src, "</td></tr>"); 633 } 634 if (p->commentURL) { 635 Strcat_charp(src, 636 "<tr><td width=\"80\"><b>CommentURL:</b></td><td>"); 637 Strcat_charp(src, "<a href=\""); 638 Strcat_charp(src, html_quote(p->commentURL->ptr)); 639 Strcat_charp(src, "\">"); 640 Strcat_charp(src, html_quote(p->commentURL->ptr)); 641 Strcat_charp(src, "</a>"); 642 Strcat_charp(src, "</td></tr>"); 643 } 644 if (tmp2[0]) { 645 Strcat_charp(src, "<tr><td width=\"80\"><b>Expires:</b></td><td>"); 646 Strcat_charp(src, tmp2); 647 if (p->flag & COO_DISCARD) 648 Strcat_charp(src, " (Discard)"); 649 Strcat_charp(src, "</td></tr>"); 650 } 651 Strcat_charp(src, "<tr><td width=\"80\"><b>Version:</b></td><td>"); 652 Strcat_charp(src, Sprintf("%d", p->version)->ptr); 653 Strcat_charp(src, "</td></tr><tr><td>"); 654 if (p->domain) { 655 Strcat_charp(src, "<tr><td width=\"80\"><b>Domain:</b></td><td>"); 656 Strcat_charp(src, html_quote(p->domain->ptr)); 657 Strcat_charp(src, "</td></tr>"); 658 } 659 if (p->path) { 660 Strcat_charp(src, "<tr><td width=\"80\"><b>Path:</b></td><td>"); 661 Strcat_charp(src, html_quote(p->path->ptr)); 662 Strcat_charp(src, "</td></tr>"); 663 } 664 if (p->portl) { 665 Strcat_charp(src, "<tr><td width=\"80\"><b>Port:</b></td><td>"); 666 Strcat_charp(src, html_quote(portlist2str(p->portl)->ptr)); 667 Strcat_charp(src, "</td></tr>"); 668 } 669 Strcat_charp(src, "<tr><td width=\"80\"><b>Secure:</b></td><td>"); 670 Strcat_charp(src, (p->flag & COO_SECURE) ? "Yes" : "No"); 671 Strcat_charp(src, "</td></tr><tr><td>"); 672 673 Strcat(src, Sprintf("<tr><td width=\"80\"><b>Use:</b></td><td>" 674 "<input type=radio name=\"%d\" value=1%s>Yes" 675 " " 676 "<input type=radio name=\"%d\" value=0%s>No", 677 i, (p->flag & COO_USE) ? " checked" : "", 678 i, (!(p->flag & COO_USE)) ? " checked" : "")); 679 Strcat_charp(src, 680 "</td></tr><tr><td><input type=submit value=\"OK\"></table><p>"); 681 } 682 Strcat_charp(src, "</ol></form></body></html>"); 683 return loadHTMLString(src); 684 } 685 686 void 687 set_cookie_flag(struct parsed_tagarg *arg) 688 { 689 int n, v; 690 struct cookie *p; 691 692 while (arg) { 693 if (arg->arg && *arg->arg && arg->value && *arg->value) { 694 n = atoi(arg->arg); 695 v = atoi(arg->value); 696 if ((p = nth_cookie(n)) != NULL) { 697 if (v && !(p->flag & COO_USE)) 698 p->flag |= COO_USE; 699 else if (!v && p->flag & COO_USE) 700 p->flag &= ~COO_USE; 701 if (!(p->flag & COO_DISCARD)) 702 is_saved = 0; 703 } 704 } 705 arg = arg->next; 706 } 707 backBf(); 708 } 709 710 int 711 check_cookie_accept_domain(char *domain) 712 { 713 TextListItem *tl; 714 715 if (domain == NULL) 716 return 0; 717 718 if (Cookie_accept_domains && Cookie_accept_domains->nitem > 0) { 719 for (tl = Cookie_accept_domains->first; tl != NULL; tl = tl->next) { 720 if (domain_match(domain, tl->ptr)) 721 return 1; 722 } 723 } 724 if (Cookie_reject_domains && Cookie_reject_domains->nitem > 0) { 725 for (tl = Cookie_reject_domains->first; tl != NULL; tl = tl->next) { 726 if (domain_match(domain, tl->ptr)) 727 return 0; 728 } 729 } 730 return 1; 731 } 732 #endif /* USE_COOKIE */