]> sjero.net Git - wget/blob - src/cookies.c
[svn] Added support for cookies.
[wget] / src / cookies.c
1 /* Support for cookies.
2    Copyright (C) 2001 Free Software Foundation, Inc.
3
4 This file is part of Wget.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /* Written by Hrvoje Niksic.  Parts are loosely inspired by cookie
21    code submitted by Tomasz Wegrzanowski.  */
22
23 #include <config.h>
24
25 #include <stdio.h>
26 #ifdef HAVE_STRING_H
27 # include <string.h>
28 #else
29 # include <strings.h>
30 #endif
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <errno.h>
34
35 #include "wget.h"
36 #include "utils.h"
37 #include "hash.h"
38 #include "url.h"
39 #include "cookies.h"
40
41 /* Hash table that maps domain names to cookie chains. */
42
43 static struct hash_table *cookies_hash_table;
44
45 /* This should be set by entry points in this file, so the low-level
46    functions don't need to call time() all the time.  */
47
48 static time_t cookies_now;
49 \f
50 /* Definition of `struct cookie' and the most basic functions. */
51
52 struct cookie {
53   char *domain;                 /* domain of the cookie */
54   int port;                     /* port number */
55   char *path;                   /* path prefix of the cookie */
56   int secure;                   /* whether cookie should be
57                                    transmitted over non-https
58                                    connections. */
59   int permanent;                /* whether the cookie should outlive
60                                    the session */
61   unsigned long expiry_time;    /* time when the cookie expires */
62   int discard_requested;        /* whether cookie was created to
63                                    request discarding another
64                                    cookie */
65
66   char *attr;                   /* cookie attribute name */
67   char *value;                  /* cookie attribute value */
68
69   struct cookie *next;          /* used for chaining of cookies in the
70                                    same domain. */
71 };
72
73 /* Allocate and return a new, empty cookie structure. */
74
75 static struct cookie *
76 cookie_new (void)
77 {
78   struct cookie *cookie = xmalloc (sizeof (struct cookie));
79   memset (cookie, '\0', sizeof (struct cookie));
80
81   /* If we don't know better, assume cookie is non-permanent and valid
82      for the entire session. */
83   cookie->expiry_time = ~0UL;
84
85   /* Assume default port. */
86   cookie->port = 80;
87
88   return cookie;
89 }
90
91 /* Deallocate COOKIE and its components. */
92
93 static void
94 delete_cookie (struct cookie *cookie)
95 {
96   FREE_MAYBE (cookie->domain);
97   FREE_MAYBE (cookie->path);
98   FREE_MAYBE (cookie->attr);
99   FREE_MAYBE (cookie->value);
100   xfree (cookie);
101 }
102 \f
103 /* Functions for cookie-specific hash tables.  These are regular hash
104    tables, but with case-insensitive test and hash functions.  */
105
106 /* Like string_hash, but produces the same results regardless of the
107    case.  */
108
109 static unsigned long
110 unsigned_string_hash (const void *sv)
111 {
112   unsigned int h = 0;
113   unsigned const char *x = (unsigned const char *) sv;
114
115   while (*x)
116     {
117       unsigned int g;
118       unsigned char c = TOLOWER (*x);
119       h = (h << 4) + c;
120       if ((g = h & 0xf0000000) != 0)
121         h = (h ^ (g >> 24)) ^ g;
122       ++x;
123     }
124
125   return h;
126 }
127
128 /* Front-end to strcasecmp. */
129
130 static int
131 unsigned_string_cmp (const void *s1, const void *s2)
132 {
133   return !strcasecmp ((const char *)s1, (const char *)s2);
134 }
135
136 /* Like make_string_hash_table, but uses unsigned_string_hash and
137    unsigned_string_cmp.  */
138
139 static struct hash_table *
140 make_unsigned_string_hash_table (int initial_size)
141 {
142   return hash_table_new (initial_size,
143                          unsigned_string_hash, unsigned_string_cmp);
144 }
145
146 /* Write "HOST:PORT" to RESULT.  RESULT should be a pointer, and the
147   memory for the contents is allocated on the stack.  Useful for
148   creating HOST:PORT strings, which are the keys in the hash
149   table.  */
150
151 #define SET_HOSTPORT(host, port, result) do {           \
152   int HP_len = strlen (host);                           \
153   result = alloca (HP_len + 1 + numdigit (port) + 1);   \
154   memcpy (result, host, HP_len);                        \
155   result[HP_len] = ':';                                 \
156   long_to_string (result + HP_len + 1, port);           \
157 } while (0)
158
159 /* Find cookie chain that corresponds to DOMAIN (exact) and PORT.  */
160
161 static struct cookie *
162 find_cookie_chain_exact (const char *domain, int port)
163 {
164   char *key;
165   if (!cookies_hash_table)
166     return NULL;
167   SET_HOSTPORT (domain, port, key);
168   return hash_table_get (cookies_hash_table, key);
169 }
170 \f
171 /* Functions for storing cookies.
172
173    All cookies can be referenced through cookies_hash_table.  The key
174    in that table is the domain name, and the value is a linked list of
175    all cookies from that domain.  Every new cookie is placed on the
176    head of the list.  */
177
178 /* Find and return the cookie whose domain, path, and attribute name
179    correspond to COOKIE.  If found, PREVPTR will point to the location
180    of the cookie previous in chain, or NULL if the found cookie is the
181    head of a chain.
182
183    If no matching cookie is found, return NULL. */
184
185 static struct cookie *
186 find_matching_cookie (struct cookie *cookie, struct cookie **prevptr)
187 {
188   struct cookie *chain, *prev;
189
190   if (!cookies_hash_table)
191     goto nomatch;
192
193   chain = find_cookie_chain_exact (cookie->domain, cookie->port);
194   if (!chain)
195     goto nomatch;
196
197   prev = NULL;
198   for (; chain; prev = chain, chain = chain->next)
199     if (!strcmp (cookie->path, chain->path)
200         && !strcmp (cookie->attr, chain->attr))
201       {
202         *prevptr = prev;
203         return chain;
204       }
205
206  nomatch:
207   *prevptr = NULL;
208   return NULL;
209 }
210
211 /* Store COOKIE to memory.
212
213    This is done by placing COOKIE at the head of its chain.  However,
214    if COOKIE matches a cookie already in memory, as determined by
215    find_matching_cookie, the old cookie is unlinked and destroyed.
216
217    The key of each chain's hash table entry is allocated only the
218    first time; next hash_table_put's reuse the same key.  */
219
220 static void
221 store_cookie (struct cookie *cookie)
222 {
223   struct cookie *chain_head;
224   char *hostport;
225   char *chain_key;
226
227   if (!cookies_hash_table)
228     /* If the hash table is not initialized, do so now, because we'll
229        need to store things.  */
230     cookies_hash_table = make_unsigned_string_hash_table (0);
231
232   /* Initialize hash table key.  */
233   SET_HOSTPORT (cookie->domain, cookie->port, hostport);
234
235   if (hash_table_get_pair (cookies_hash_table, hostport,
236                            &chain_key, &chain_head))
237     {
238       /* There already exists a chain of cookies with this exact
239          domain.  We need to check for duplicates -- if an existing
240          cookie exactly matches our domain, path and name, we replace
241          it.  */
242       struct cookie *prev;
243       struct cookie *victim = find_matching_cookie (cookie, &prev);
244
245       if (victim)
246         {
247           /* Remove VICTIM from the chain.  COOKIE will be placed at
248              the head. */
249           if (prev)
250             {
251               prev->next = victim->next;
252               cookie->next = chain_head;
253             }
254           else
255             {
256               /* prev is NULL; apparently VICTIM was at the head of
257                  the chain.  This place will be taken by COOKIE, so
258                  all we need to do is:  */
259               cookie->next = victim->next;
260             }
261           delete_cookie (victim);
262           DEBUGP (("Deleted old cookie (to be replaced.)\n"));
263         }
264       else
265         cookie->next = chain_head;
266     }
267   else
268     {
269       /* We are now creating the chain.  Allocate the string that will
270          be used as a key.  It is unsafe to use cookie->domain for
271          that, because it might get deallocated by the above code at
272          some point later.  */
273       cookie->next = NULL;
274       chain_key = xstrdup (hostport);
275     }
276
277   hash_table_put (cookies_hash_table, chain_key, cookie);
278
279   DEBUGP (("\nStored cookie %s %d %s %d %s %s %s\n",
280            cookie->domain, cookie->port, cookie->path, cookie->secure,
281            asctime (localtime ((time_t *)&cookie->expiry_time)),
282            cookie->attr, cookie->value));
283 }
284
285 /* Discard a cookie matching COOKIE's domain, path, and attribute
286    name.  This gets called when we encounter a cookie whose expiry
287    date is in the past, or whose max-age is set to 0.  The former
288    corresponds to netscape cookie spec, while the latter is specified
289    by rfc2109.  */
290
291 static void
292 discard_matching_cookie (struct cookie *cookie)
293 {
294   struct cookie *prev, *victim;
295
296   if (!cookies_hash_table
297       || !hash_table_count (cookies_hash_table))
298     /* No elements == nothing to discard. */
299     return;
300
301   victim = find_matching_cookie (cookie, &prev);
302   if (victim)
303     {
304       if (prev)
305         /* Simply unchain the victim. */
306         prev->next = victim->next;
307       else
308         {
309           /* VICTIM was head of its chain.  We need to place a new
310              cookie at the head.  */
311
312           char *hostport;
313           char *chain_key = NULL;
314           int res;
315
316           SET_HOSTPORT (victim->domain, victim->port, hostport);
317           res = hash_table_get_pair (cookies_hash_table, hostport,
318                                      &chain_key, NULL);
319           assert (res != 0);
320           if (!victim->next)
321             {
322               /* VICTIM was the only cookie in the chain.  Destroy the
323                  chain and deallocate the chain key.  */
324
325               hash_table_remove (cookies_hash_table, hostport);
326               xfree (chain_key);
327             }
328           else
329             hash_table_put (cookies_hash_table, chain_key, victim->next);
330         }
331       delete_cookie (victim);
332       DEBUGP (("Discarded old cookie.\n"));
333     }
334 }
335 \f
336 /* Functions for parsing the `Set-Cookie' header, and creating new
337    cookies from the wire.  */
338
339
340 #define NAME_IS(string_literal)                                 \
341   BOUNDED_EQUAL_NO_CASE (name_b, name_e, string_literal)
342
343 #define VALUE_EXISTS (value_b && value_e)
344
345 #define VALUE_NON_EMPTY (VALUE_EXISTS && (value_b != value_e))
346
347 /* Update the appropriate cookie field.  [name_b, name_e) are expected
348    to delimit the attribute name, while [value_b, value_e) (optional)
349    should delimit the attribute value.
350
351    When called the first time, it will set the cookie's attribute name
352    and value.  After that, it will check the attribute name for
353    special fields such as `domain', `path', etc.  Where appropriate,
354    it will parse the values of the fields it recognizes and fill the
355    corresponding fields in COOKIE.
356
357    Returns 1 on success.  Returns zero in case a syntax error is
358    found; such a cookie should be discarded.  */
359
360 static int
361 update_cookie_field (struct cookie *cookie,
362                      const char *name_b, const char *name_e,
363                      const char *value_b, const char *value_e)
364 {
365   assert (name_b != NULL && name_e != NULL);
366
367   if (!cookie->attr)
368     {
369       if (!VALUE_EXISTS)
370         return 0;
371       cookie->attr = strdupdelim (name_b, name_e);
372       cookie->value = strdupdelim (value_b, value_e);
373       return 1;
374     }
375
376   if (NAME_IS ("domain"))
377     {
378       if (!VALUE_NON_EMPTY)
379         return 0;
380       FREE_MAYBE (cookie->domain);
381       cookie->domain = strdupdelim (value_b, value_e);
382       return 1;
383     }
384   else if (NAME_IS ("path"))
385     {
386       if (!VALUE_NON_EMPTY)
387         return 0;
388       FREE_MAYBE (cookie->path);
389       cookie->path = strdupdelim (value_b, value_e);
390       return 1;
391     }
392   else if (NAME_IS ("expires"))
393     {
394       char *value_copy;
395       time_t expires;
396
397       if (!VALUE_NON_EMPTY)
398         return 0;
399       BOUNDED_TO_ALLOCA (value_b, value_e, value_copy);
400
401       expires = http_atotm (value_copy);
402       if (expires != -1)
403         {
404           cookie->permanent = 1;
405           cookie->expiry_time = (unsigned long)expires;
406         }
407       else
408         /* Error in expiration spec.  Assume default (cookie valid for
409            this session.)  #### Should we return 0 and invalidate the
410            cookie?  */
411         ;
412
413       /* According to netscape's specification, expiry time in the
414          past means that discarding of a matching cookie is
415          requested.  */
416       if (cookie->expiry_time < cookies_now)
417         cookie->discard_requested = 1;
418
419       return 1;
420     }
421   else if (NAME_IS ("max-age"))
422     {
423       double maxage = -1;
424       char *value_copy;
425
426       if (!VALUE_NON_EMPTY)
427         return 0;
428       BOUNDED_TO_ALLOCA (value_b, value_e, value_copy);
429
430       sscanf (value_copy, "%lf", &maxage);
431       if (maxage == -1)
432         /* something is wrong. */
433         return 0;
434       cookie->permanent = 1;
435       cookie->expiry_time = (unsigned long)cookies_now + (unsigned long)maxage;
436
437       /* According to rfc2109, a cookie with max-age of 0 means that
438          discarding of a matching cookie is requested.  */
439       if (maxage == 0)
440         cookie->discard_requested = 1;
441
442       return 1;
443     }
444   else if (NAME_IS ("secure"))
445     {
446       /* ignore value completely */
447       cookie->secure = 1;
448       return 1;
449     }
450   else
451     /* Unrecognized attribute; ignore it. */
452     return 1;
453 }
454
455 #undef NAME_IS
456
457 /* Returns non-zero for characters that are legal in the name of an
458    attribute.  */
459
460 #define ATTR_NAME_CHAR(c) (ISALNUM (c) || (c) == '-' || (c) == '_')
461
462 /* Fetch the next character without doing anything special if CH gets
463    set to 0.  (The code executed next is expected to handle it.)  */
464
465 #define FETCH1(ch, ptr) do {                    \
466   ch = *ptr++;                                  \
467 } while (0)
468
469 /* Like FETCH1, but jumps to `eof' label if CH gets set to 0.  */
470
471 #define FETCH(ch, ptr) do {             \
472   FETCH1 (ch, ptr);                     \
473   if (!ch)                              \
474     goto eof;                           \
475 } while (0)
476
477 /* Parse the contents of the `Set-Cookie' header.  The header looks
478    like this:
479
480    name1=value1; name2=value2; ...
481
482    Trailing semicolon is optional; spaces are allowed between all
483    tokens.  Additionally, values may be quoted.
484
485    A new cookie is returned upon success, NULL otherwise.  The
486    function `update_cookie_field' is used to update the fields of the
487    newly created cookie structure.  */
488
489 static struct cookie *
490 parse_set_cookies (const char *sc)
491 {
492   struct cookie *cookie = cookie_new ();
493
494   enum { S_NAME_PRE, S_NAME, S_NAME_POST,
495          S_VALUE_PRE, S_VALUE, S_VALUE_TRAILSPACE_MAYBE,
496          S_QUOTED_VALUE, S_QUOTED_VALUE_POST,
497          S_ATTR_ACTION,
498          S_DONE, S_ERROR } state = S_NAME_PRE;
499
500   const char *p = sc;
501   char c;
502
503   const char *name_b  = NULL, *name_e  = NULL;
504   const char *value_b = NULL, *value_e = NULL;
505
506   FETCH (c, p);
507
508   while (state != S_DONE && state != S_ERROR)
509     {
510       switch (state)
511         {
512         case S_NAME_PRE:
513           if (ISSPACE (c))
514             FETCH (c, p);
515           else if (ATTR_NAME_CHAR (c))
516             {
517               name_b = p - 1;
518               FETCH1 (c, p);
519               state = S_NAME;
520             }
521           else
522             /* empty attr name not allowed */
523             state = S_ERROR;
524           break;
525         case S_NAME:
526           if (ATTR_NAME_CHAR (c))
527             FETCH1 (c, p);
528           else if (!c || c == ';' || c == '=' || ISSPACE (c))
529             {
530               name_e = p - 1;
531               state = S_NAME_POST;
532             }
533           else
534             state = S_ERROR;
535           break;
536         case S_NAME_POST:
537           if (ISSPACE (c))
538             FETCH1 (c, p);
539           else if (!c || c == ';')
540             {
541               value_b = value_e = NULL;
542               state = S_ATTR_ACTION;
543             }
544           else if (c == '=')
545             {
546               FETCH1 (c, p);
547               state = S_VALUE_PRE;
548             }
549           else
550             state = S_ERROR;
551           break;
552         case S_VALUE_PRE:
553           if (ISSPACE (c))
554             FETCH1 (c, p);
555           else if (c == '"')
556             {
557               value_b = p;
558               FETCH (c, p);
559               state = S_QUOTED_VALUE;
560             }
561           else if (c == ';' || c == '\0')
562             {
563               value_b = value_e = p - 1;
564               state = S_ATTR_ACTION;
565             }
566           else
567             {
568               value_b = p - 1;
569               value_e = NULL;
570               state = S_VALUE;
571             }
572           break;
573         case S_VALUE:
574           if (c == ';' || c == '\0')
575             {
576               if (!value_e)
577                 value_e = p - 1;
578               state = S_ATTR_ACTION;
579             }
580           else if (ISSPACE (c))
581             {
582               value_e = p - 1;
583               FETCH1 (c, p);
584               state = S_VALUE_TRAILSPACE_MAYBE;
585             }
586           else
587             {
588               value_e = NULL;   /* no trailing space */
589               FETCH1 (c, p);
590             }
591           break;
592         case S_VALUE_TRAILSPACE_MAYBE:
593           if (ISSPACE (c))
594             FETCH1 (c, p);
595           else
596             state = S_VALUE;
597           break;
598         case S_QUOTED_VALUE:
599           if (c == '"')
600             {
601               value_e = p - 1;
602               FETCH1 (c, p);
603               state = S_QUOTED_VALUE_POST;
604             }
605           else
606             FETCH (c, p);
607           break;
608         case S_QUOTED_VALUE_POST:
609           if (c == ';' || !c)
610             state = S_ATTR_ACTION;
611           else if (ISSPACE (c))
612             FETCH1 (c, p);
613           else
614             state = S_ERROR;
615           break;
616         case S_ATTR_ACTION:
617           {
618             int legal = update_cookie_field (cookie, name_b, name_e,
619                                              value_b, value_e);
620             if (!legal)
621               {
622                 char *name;
623                 BOUNDED_TO_ALLOCA (name_b, name_e, name);
624                 logprintf (LOG_NOTQUIET,
625                            _("Error in Set-Cookie, field `%s'"), name);
626                 state = S_ERROR;
627                 break;
628               }
629
630             if (c)
631               FETCH1 (c, p);
632             if (!c)
633               state = S_DONE;
634             else
635               state = S_NAME_PRE;
636           }
637           break;
638         case S_DONE:
639         case S_ERROR:
640           /* handled by loop condition */
641           break;
642         }
643     }
644   if (state == S_DONE)
645     return cookie;
646
647   delete_cookie (cookie);
648   if (state == S_ERROR)
649     logprintf (LOG_NOTQUIET, _("Error in Set-Cookie, at character `%c'.\n"), c);
650   else
651     abort ();
652   return NULL;
653
654  eof:
655   delete_cookie (cookie);
656   logprintf (LOG_NOTQUIET,
657              _("Error in Set-Cookie: premature end of string.\n"));
658   return NULL;
659 }
660 \f
661 /* Sanity checks.  These are important, otherwise it is possible for
662    mailcious attackers to destroy important cookie information and/or
663    violate your privacy.  */
664
665
666 #define REQUIRE_DIGITS(p) do {                  \
667   if (!ISDIGIT (*p))                            \
668     return 0;                                   \
669   for (++p; ISDIGIT (*p); p++)                  \
670     ;                                           \
671 } while (0)
672
673 #define REQUIRE_DOT(p) do {                     \
674   if (*p++ != '.')                              \
675     return 0;                                   \
676 } while (0)
677
678 /* Check whether ADDR matches <digits>.<digits>.<digits>.<digits>.
679
680   We don't want to call network functions like inet_addr() because all
681   we need is a check, preferrably one that is small, fast, and
682   well-defined.  */
683
684 static int
685 numeric_address_p (const char *addr)
686 {
687   const char *p = addr;
688
689   REQUIRE_DIGITS (p);           /* A */
690   REQUIRE_DOT (p);              /* . */
691   REQUIRE_DIGITS (p);           /* B */
692   REQUIRE_DOT (p);              /* . */
693   REQUIRE_DIGITS (p);           /* C */
694   REQUIRE_DOT (p);              /* . */
695   REQUIRE_DIGITS (p);           /* D */
696
697   if (*p != '\0')
698     return 0;
699   return 1;
700 }
701
702 /* Check whether COOKIE_DOMAIN is an appropriate domain for HOST.
703    This check is compliant with rfc2109.  */
704
705 static int
706 check_domain_match (const char *cookie_domain, const char *host)
707 {
708   int i, headlen;
709   const char *tail;
710
711   /* Numeric address requires exact match.  It also requires HOST to
712      be an IP address.  I suppose we *could* resolve HOST with
713      store_hostaddress (it would hit the hash table), but rfc2109
714      doesn't require it, and it doesn't seem very useful, so we
715      don't.  */
716   if (numeric_address_p (cookie_domain))
717     return !strcmp (cookie_domain, host);
718
719   /* The domain must contain at least one embedded dot. */
720   {
721     const char *rest = cookie_domain;
722     int len = strlen (rest);
723     if (*rest == '.')
724       ++rest, --len;            /* ignore first dot */
725     if (len <= 0)
726       return 0;
727     if (rest[len - 1] == '.')
728       --len;                    /* ignore last dot */
729
730     if (!memchr (rest, '.', len))
731       /* No dots. */
732       return 0;
733   }
734
735   /* For the sake of efficiency, check for exact match first. */
736   if (!strcasecmp (cookie_domain, host))
737     return 1;
738
739   /* In rfc2109 terminology, HOST needs domain-match COOKIE_DOMAIN.
740      This means that COOKIE_DOMAIN needs to start with `.' and be an
741      FQDN, and that HOST must end with COOKIE_DOMAIN.  */
742   if (*cookie_domain != '.')
743     return 0;
744
745   /* Two proceed, we need to examine two parts of HOST: its head and
746      its tail.  Head and tail are defined in terms of the length of
747      the domain, like this:
748
749        HHHHTTTTTTTTTTTTTTT  <- host
750            DDDDDDDDDDDDDDD  <- domain
751
752      That is, "head" is the part of the host before (dlen - hlen), and
753      "tail" is what follows.
754
755      For the domain to match, two conditions need to be true:
756
757      1. Tail must equal DOMAIN.
758      2. Head must not contain an embedded dot.  */
759
760   headlen = strlen (host) - strlen (cookie_domain);
761
762   if (headlen <= 0)
763     /* DOMAIN must be a proper subset of HOST. */
764     return 0;
765   tail = host + headlen;
766
767   /* (1) */
768   if (strcasecmp (tail, cookie_domain))
769     return 0;
770
771   /* Test (2) is not part of the "domain-match" itself, but is
772      recommended by rfc2109 for reasons of privacy.  */
773
774   /* (2) */
775   if (memchr (host, '.', headlen))
776     return 0;
777
778   return 1;
779 }
780
781 static int path_matches PARAMS ((const char *, const char *));
782
783 /* Check whether PATH begins with COOKIE_PATH. */
784
785 static int
786 check_path_match (const char *cookie_path, const char *path)
787 {
788   return path_matches (path, cookie_path);
789 }
790 \f
791 /* Parse the `Set-Cookie' header and, if the cookie is legal, store it
792    to memory.  */
793
794 int
795 set_cookie_header_cb (const char *hdr, void *closure)
796 {
797   struct urlinfo *u = (struct urlinfo *)closure;
798   struct cookie *cookie;
799
800   cookies_now = time (NULL);
801
802   cookie = parse_set_cookies (hdr);
803   if (!cookie)
804     goto out;
805
806   /* Sanitize parts of cookie. */
807
808   if (!cookie->domain)
809     cookie->domain = xstrdup (u->host);
810   else
811     {
812       if (!check_domain_match (cookie->domain, u->host))
813         {
814           DEBUGP (("Attempt to fake the domain: %s, %s\n",
815                    cookie->domain, u->host));
816           goto out;
817         }
818     }
819   if (!cookie->path)
820     cookie->path = xstrdup (u->path);
821   else
822     {
823       if (!check_path_match (cookie->path, u->path))
824         {
825           DEBUGP (("Attempt to fake the path: %s, %s\n",
826                    cookie->path, u->path));
827           goto out;
828         }
829     }
830
831   cookie->port = u->port;
832
833   if (cookie->discard_requested)
834     {
835       discard_matching_cookie (cookie);
836       delete_cookie (cookie);
837       return 1;
838     }
839
840   store_cookie (cookie);
841   return 1;
842
843  out:
844   if (cookie)
845     delete_cookie (cookie);
846   return 1;
847 }
848 \f
849 /* Support for sending out cookies in HTTP requests, based on
850    previously stored cookies.  Entry point is
851    `build_cookies_request'.  */
852
853
854 /* Count how many times CHR occurs in STRING. */
855
856 static int
857 count_char (const char *string, char chr)
858 {
859   const char *p;
860   int count = 0;
861   for (p = string; *p; p++)
862     if (*p == chr)
863       ++count;
864   return count;
865 }
866
867 /* Return the head of the cookie chain that matches HOST.  */
868
869 static struct cookie *
870 find_cookie_chain (const char *host, int port)
871 {
872   int dot_count;
873   char *hash_key;
874   struct cookie *chain = NULL;
875
876   if (!cookies_hash_table)
877     return NULL;
878
879   SET_HOSTPORT (host, port, hash_key);
880
881   /* Exact match. */
882   chain = hash_table_get (cookies_hash_table, hash_key);
883   if (chain)
884     return chain;
885
886   dot_count = count_char (host, '.');
887
888   /* Match less and less specific domains.  For instance, given
889      fly.srk.fer.hr, we match .srk.fer.hr, then .fer.hr.  */
890   while (dot_count-- > 1)
891     {
892       /* Note: we operate directly on hash_key (in form host:port)
893          because we don't want to allocate new hash keys in a
894          loop.  */
895       char *p = strchr (hash_key, '.');
896       assert (p != NULL);
897       chain = hash_table_get (cookies_hash_table, p);
898       if (chain)
899         return chain;
900       hash_key = p + 1;
901     }
902   return NULL;
903 }
904
905 /* If FULL_PATH begins with PREFIX, return the length of PREFIX, zero
906    otherwise.  */
907
908 static int
909 path_matches (const char *full_path, const char *prefix)
910 {
911   int len = strlen (prefix);
912   if (strncmp (full_path, prefix, len))
913     /* FULL_PATH doesn't begin with PREFIX. */
914     return 0;
915
916   /* Length of PREFIX determines the quality of the match. */
917   return len;
918 }
919
920 struct weighed_cookie {
921   struct cookie *cookie;
922   int path_goodness;
923 };
924
925 static int
926 goodness_comparator (const void *p1, const void *p2)
927 {
928   struct weighed_cookie *wc1 = (struct weighed_cookie *)p1;
929   struct weighed_cookie *wc2 = (struct weighed_cookie *)p2;
930   /* It's goodness2-goodness1 because we want a sort in *decreasing*
931      order of goodness. */
932   return wc2->path_goodness - wc1->path_goodness;
933 }
934
935 /* Build a `Cookies' header for a request that goes to HOST:PORT and
936    requests PATH from the server.  Memory is allocated by `malloc',
937    and the caller is responsible for freeing it.  If no cookies
938    pertain to this request, i.e. no cookie header should be generated,
939    NULL is returned.  */
940
941 char *
942 build_cookies_request (const char *host, int port, const char *path,
943                        int connection_secure_p)
944 {
945   struct cookie *chain = find_cookie_chain (host, port);
946   struct cookie *cookie;
947   struct weighed_cookie *outgoing;
948   int count, i;
949   char *result;
950   int result_size, pos;
951
952   if (!chain)
953     return NULL;
954
955   cookies_now = time (NULL);
956
957   /* Count the number of cookies whose path matches. */
958   count = 0;
959   result_size = 0;
960   for (cookie = chain; cookie; cookie = cookie->next)
961     {
962       if (cookie->expiry_time < cookies_now)
963         /* Ignore stale cookies.  There is no need to unchain the
964            cookie at this point -- Wget is a relatively short-lived
965            application, and stale cookies will not be saved by
966            `save_cookies'.  */
967         continue;
968       if (cookie->secure && !connection_secure_p)
969         /* Don't transmit secure cookies over an insecure
970            connection.  */
971         continue;
972       if (path_matches (path, cookie->path))
973         {
974           ++count;
975           /* name=value */
976           result_size += strlen (cookie->attr) + 1 + strlen (cookie->value);
977         }
978     }
979   if (!count)
980     return NULL;
981
982   /* Allocate the array. */
983   outgoing = alloca (count * sizeof (struct weighed_cookie));
984   i = 0;
985   for (cookie = chain; cookie; cookie = cookie->next)
986     {
987       int goodness;
988       /* #### These two if's are repeated verbatim from the loop
989          above.  Should I put them in a separate function?  */
990       if (cookie->expiry_time < cookies_now)
991         continue;
992       if (cookie->secure && !connection_secure_p)
993         /* Don't transmit secure cookies over an insecure
994            connection.  */
995         continue;
996       goodness = path_matches (path, cookie->path);
997       if (!goodness)
998         continue;
999       outgoing[i].cookie = cookie;
1000       outgoing[i].path_goodness = goodness;
1001       ++i;
1002     }
1003   assert (i == count);
1004
1005   /* Sort the array so that paths that match our path better come
1006      first. */
1007   qsort (outgoing, count, sizeof (struct weighed_cookie), goodness_comparator);
1008
1009   /* Allocate output buffer:
1010      "Cookie: "       -- 8
1011      name=value pairs -- result_size
1012      "; " separators  -- (count - 1) * 2
1013      \r\n line ending -- 2
1014      \0 terminator    -- 1 */
1015   result_size = 8 + result_size + (count - 1) * 2 + 2 + 1;
1016   result = xmalloc (result_size);
1017   pos = 0;
1018   strcpy (result, "Cookie: ");
1019   pos += 8;
1020   for (i = 0; i < count; i++)
1021     {
1022       struct cookie *c = outgoing[i].cookie;
1023       int namlen = strlen (c->attr);
1024       int vallen = strlen (c->value);
1025
1026       memcpy (result + pos, c->attr, namlen);
1027       pos += namlen;
1028       result[pos++] = '=';
1029       memcpy (result + pos, c->value, vallen);
1030       pos += vallen;
1031       if (i < count - 1)
1032         {
1033           result[pos++] = ';';
1034           result[pos++] = ' ';
1035         }
1036     }
1037   result[pos++] = '\r';
1038   result[pos++] = '\n';
1039   result[pos++] = '\0';
1040   assert (pos == result_size);
1041   return result;
1042 }
1043 \f
1044 /* Support for loading and saving cookies.  The format used for
1045    loading and saving roughly matches the format of `cookies.txt' file
1046    used by Netscape and Mozilla, at least the Unix versions.  The
1047    format goes like this:
1048
1049        DOMAIN DOMAIN-FLAG PATH SECURE-FLAG TIMESTAMP ATTR-NAME ATTR-VALUE
1050
1051      DOMAIN      -- cookie domain, optionally followed by :PORT
1052      DOMAIN-FLAG -- whether all hosts in the domain match
1053      PATH        -- cookie path
1054      SECURE-FLAG -- whether cookie requires secure connection
1055      TIMESTAMP   -- expiry timestamp, number of seconds since epoch
1056      ATTR-NAME   -- name of the cookie attribute
1057      ATTR-VALUE  -- value of the cookie attribute (empty if absent)
1058
1059    The fields are separated by TABs (but Wget's loader recognizes any
1060    whitespace).  All fields are mandatory, except for ATTR-VALUE.  The
1061    `-FLAG' fields are boolean, their legal values being "TRUE" and
1062    "FALSE'.  Empty lines, lines consisting of whitespace only, and
1063    comment lines (beginning with # optionally preceded by whitespace)
1064    are ignored.
1065
1066    Example line from cookies.txt (split in two lines for readability):
1067
1068        .google.com      TRUE    /       FALSE   2147368447      \
1069        PREF     ID=34bb47565bbcd47b:LD=en:NR=20:TM=985172580:LM=985739012
1070
1071    DOMAIN-FLAG is currently not honored by Wget.  The cookies whose
1072    domain begins with `.' are treated as if DOMAIN-FLAG were true,
1073    while all other cookies are treated as if it were FALSE. */
1074
1075
1076 /* If the region [B, E) ends with :<digits>, parse the number, return
1077    it, and store new boundary (location of the `:') to DOMAIN_E_PTR.
1078    If port is not specified, return 0.  */
1079
1080 static int
1081 domain_port (const char *domain_b, const char *domain_e,
1082              const char **domain_e_ptr)
1083 {
1084   int port = 0;
1085   const char *p;
1086   const char *colon = memchr (domain_b, ':', domain_e - domain_b);
1087   if (!colon)
1088     return 0;
1089   for (p = colon + 1; p < domain_e && ISDIGIT (*p); p++)
1090     port = 10 * port + (*p - '0');
1091   if (p < domain_e)
1092     /* Garbage following port number. */
1093     return 0;
1094   *domain_e_ptr = colon;
1095   return port;
1096 }
1097
1098 #define SKIP_WS(p) do {                         \
1099   while (*p && ISSPACE (*p))                    \
1100     ++p;                                        \
1101 } while (0)
1102
1103 #define MARK_WORD(p, b, e) do {                 \
1104   SKIP_WS (p);                                  \
1105   b = p;                                        \
1106   /* skip non-ws */                             \
1107   while (*p && !ISSPACE (*p))                   \
1108     ++p;                                        \
1109   e = p;                                        \
1110   if (b == e)                                   \
1111     goto next;                                  \
1112 } while (0)
1113
1114 /* Load cookies from FILE.  */
1115
1116 void
1117 load_cookies (const char *file)
1118 {
1119   char *line;
1120   FILE *fp = fopen (file, "r");
1121   if (!fp)
1122     {
1123       logprintf (LOG_NOTQUIET, "Cannot open cookies file `%s': %s\n",
1124                  file, strerror (errno));
1125       return;
1126     }
1127   cookies_now = time (NULL);
1128
1129   for (; ((line = read_whole_line (fp)) != NULL); xfree (line))
1130     {
1131       struct cookie *cookie;
1132       char *p = line;
1133
1134       int port;
1135
1136       char *domain_b  = NULL, *domain_e  = NULL;
1137       char *ignore_b  = NULL, *ignore_e  = NULL;
1138       char *path_b    = NULL, *path_e    = NULL;
1139       char *secure_b  = NULL, *secure_e  = NULL;
1140       char *expires_b = NULL, *expires_e = NULL;
1141       char *name_b    = NULL, *name_e    = NULL;
1142       char *value_b   = NULL, *value_e   = NULL;
1143
1144       SKIP_WS (p);
1145
1146       if (!*p || *p == '#')
1147         /* empty line */
1148         continue;
1149
1150       MARK_WORD (p, domain_b,  domain_e);
1151       MARK_WORD (p, ignore_b,  ignore_e);
1152       MARK_WORD (p, path_b,    path_e);
1153       MARK_WORD (p, secure_b,  secure_e);
1154       MARK_WORD (p, expires_b, expires_e);
1155       MARK_WORD (p, name_b,    name_e);
1156
1157       /* Don't use MARK_WORD for value because it may contain
1158          whitespace itself.  Instead, . */
1159       MARK_WORD (p, value_b,   value_e);
1160
1161       cookie = cookie_new ();
1162
1163       cookie->attr    = strdupdelim (name_b, name_e);
1164       cookie->value   = strdupdelim (value_b, value_e);
1165       cookie->path    = strdupdelim (path_b, path_e);
1166
1167       if (BOUNDED_EQUAL (secure_b, secure_e, "TRUE"))
1168         cookie->secure = 1;
1169
1170       /* DOMAIN needs special treatment because we might need to
1171          extract the port.  */
1172       port = domain_port (domain_b, domain_e, (const char **)&domain_e);
1173       if (port)
1174         cookie->port = port;
1175       else
1176         cookie->port = cookie->secure ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
1177
1178       cookie->domain  = strdupdelim (domain_b, domain_e);
1179
1180       /* Don't use MARK_WORD for value because it may contain
1181          whitespace itself.  Instead, set name_e to the end of line,
1182          modulo trailing space (which includes the NL separator.) */
1183       SKIP_WS (p);
1184       name_b = p;
1185       name_e = p + strlen (p);
1186       while (name_e >= name_b && ISSPACE (*name_e))
1187         --name_e;
1188       if (name_b == name_e)
1189         /* Hmm, should we check for empty value?  I guess that's
1190            legal, so I leave it.  */
1191         ;
1192
1193       /* safe default in case EXPIRES field is garbled. */
1194       cookie->expiry_time = cookies_now - 1;
1195
1196       /* I don't like changing the line, but it's completely safe.
1197          (line is malloced.)  */
1198       *expires_e = '\0';
1199       sscanf (expires_b, "%lu", &cookie->expiry_time);
1200       if (cookie->expiry_time < cookies_now)
1201         /* ignore stale cookie. */
1202         goto abort;
1203       cookie->permanent = 1;
1204
1205       store_cookie (cookie);
1206
1207     next:
1208       continue;
1209
1210     abort:
1211       delete_cookie (cookie);
1212     }
1213   fclose (fp);
1214 }
1215
1216 /* Mapper for save_cookies callable by hash_table_map.  VALUE points
1217    to the head in a chain of cookies.  The function prints the entire
1218    chain.  */
1219
1220 static int
1221 save_cookies_mapper (void *key, void *value, void *arg)
1222 {
1223   FILE *fp = (FILE *)arg;
1224   char *domain = (char *)key;
1225   struct cookie *chain = (struct cookie *)value;
1226   for (; chain; chain = chain->next)
1227     {
1228       if (!chain->permanent)
1229         continue;
1230       if (chain->expiry_time < cookies_now)
1231         continue;
1232       fprintf (fp, "%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
1233                domain, *domain == '.' ? "TRUE" : "FALSE",
1234                chain->path, chain->secure ? "TRUE" : "FALSE",
1235                chain->expiry_time,
1236                chain->attr, chain->value);
1237       if (ferror (fp))
1238         return 1;               /* stop mapping */
1239     }
1240   return 0;
1241 }
1242
1243 /* Save cookies, in format described above, to FILE. */
1244
1245 void
1246 save_cookies (const char *file)
1247 {
1248   FILE *fp;
1249
1250   if (!cookies_hash_table
1251       || !hash_table_count (cookies_hash_table))
1252     /* no cookies stored; nothing to do. */
1253     return;
1254
1255   cookies_now = time (NULL);
1256
1257   fp = fopen (file, "w");
1258   if (!fp)
1259     {
1260       logprintf (LOG_NOTQUIET, _("Cannot open cookies file `%s': %s\n"),
1261                  file, strerror (errno));
1262       return;
1263     }
1264
1265   fputs ("# HTTP cookie file.\n", fp);
1266   fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (NULL));
1267   fputs ("# Edit at your own risk.\n\n", fp);
1268
1269   hash_table_map (cookies_hash_table, save_cookies_mapper, fp);
1270
1271   if (ferror (fp))
1272     logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
1273                file, strerror (errno));
1274
1275   if (fclose (fp) < 0)
1276     logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
1277                file, strerror (errno));
1278 }
1279 \f
1280 static int
1281 delete_cookie_chain_mapper (void *value, void *key, void *arg_ignored)
1282 {
1283   char *chain_key = (char *)value;
1284   struct cookie *chain = (struct cookie *)key;
1285
1286   /* Remove the chain from the table and free the key. */
1287   hash_table_remove (cookies_hash_table, chain_key);
1288   xfree (chain_key);
1289
1290   /* Then delete all the cookies in the chain. */
1291   while (chain)
1292     {
1293       struct cookie *next = chain->next;
1294       delete_cookie (chain);
1295       chain = next;
1296     }
1297
1298   /* Keep mapping. */
1299   return 0;
1300 }
1301
1302 /* Clean up cookie-related data. */
1303
1304 void
1305 cookies_cleanup (void)
1306 {
1307   if (!cookies_hash_table)
1308     return;
1309   hash_table_map (cookies_hash_table, delete_cookie_chain_mapper, NULL);
1310   hash_table_destroy (cookies_hash_table);
1311   cookies_hash_table = NULL;
1312 }