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