~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to src/cookies.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-06-26 16:46:25 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050626164625-jjcde8hyztx7xq7o
Tags: 1.10-2
* wget-fix_error--save-headers patch from upstream
  (closes: Bug#314728)
* don't pattern-match server redirects patch from upstream
  (closes: Bug#163243)
* correct de.po typos
  (closes: Bug#313883)
* wget-E_html_behind_file_counting fix problem with adding the
  numbers after the html extension
* updated Standards-Version: to 3.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
file, but you are not obligated to do so.  If you do not wish to do
28
28
so, delete this exception statement from your version.  */
29
29
 
30
 
/* Written by Hrvoje Niksic.  Parts are loosely inspired by cookie
31
 
   code submitted by Tomasz Wegrzanowski.
32
 
 
33
 
   Ideas for future work:
34
 
 
35
 
   * Implement limits on cookie-related sizes, such as max. cookie
36
 
     size, max. number of cookies, etc.
37
 
 
38
 
   * Add more "cookie jar" methods, such as methods to iterate over
39
 
     stored cookies, to clear temporary cookies, to perform
40
 
     intelligent auto-saving, etc.
41
 
 
42
 
   * Support `Set-Cookie2' and `Cookie2' headers?  Does anyone really
43
 
     use them?  */
 
30
/* Written by Hrvoje Niksic.  Parts are loosely inspired by the
 
31
   cookie patch submitted by Tomasz Wegrzanowski.
 
32
 
 
33
   This implements the client-side cookie support, as specified
 
34
   (loosely) by Netscape's "preliminary specification", currently
 
35
   available at:
 
36
 
 
37
       http://wp.netscape.com/newsref/std/cookie_spec.html
 
38
 
 
39
   rfc2109 is not supported because of its incompatibilities with the
 
40
   above widely-used specification.  rfc2965 is entirely ignored,
 
41
   since popular client software doesn't implement it, and even the
 
42
   sites that do send Set-Cookie2 also emit Set-Cookie for
 
43
   compatibility.  */
44
44
 
45
45
#include <config.h>
46
46
 
90
90
struct cookie_jar *
91
91
cookie_jar_new (void)
92
92
{
93
 
  struct cookie_jar *jar = xmalloc (sizeof (struct cookie_jar));
 
93
  struct cookie_jar *jar = xnew (struct cookie_jar);
94
94
  jar->chains = make_nocase_string_hash_table (0);
95
95
  jar->cookie_count = 0;
96
96
  return jar;
108
108
                                   whole. */
109
109
 
110
110
  int permanent;                /* whether the cookie should outlive
111
 
                                   the session */
112
 
  time_t expiry_time;           /* time when the cookie expires */
 
111
                                   the session. */
 
112
  time_t expiry_time;           /* time when the cookie expires, 0
 
113
                                   means undetermined. */
113
114
 
114
115
  int discard_requested;        /* whether cookie was created to
115
116
                                   request discarding another
116
 
                                   cookie */
 
117
                                   cookie. */
117
118
 
118
119
  char *attr;                   /* cookie attribute name */
119
120
  char *value;                  /* cookie attribute value */
123
124
};
124
125
 
125
126
#define PORT_ANY (-1)
126
 
#define COOKIE_EXPIRED_P(c) ((c)->expiry_time != 0 && (c)->expiry_time < cookies_now)
127
127
 
128
128
/* Allocate and return a new, empty cookie structure. */
129
129
 
130
130
static struct cookie *
131
131
cookie_new (void)
132
132
{
133
 
  struct cookie *cookie = xmalloc (sizeof (struct cookie));
134
 
  memset (cookie, '\0', sizeof (struct cookie));
 
133
  struct cookie *cookie = xnew0 (struct cookie);
135
134
 
136
 
  /* Both cookie->permanent and cookie->expiry_time are now 0.  By
137
 
     default, we assume that the cookie is non-permanent and valid
138
 
     until the end of the session.  */
 
135
  /* Both cookie->permanent and cookie->expiry_time are now 0.  This
 
136
     means that the cookie doesn't expire, but is only valid for this
 
137
     session (i.e. not written out to disk).  */
139
138
 
140
139
  cookie->port = PORT_ANY;
141
140
  return cookie;
142
141
}
143
142
 
 
143
/* Non-zero if the cookie has expired.  Assumes cookies_now has been
 
144
   set by one of the entry point functions.  */
 
145
 
 
146
static int
 
147
cookie_expired_p (const struct cookie *c)
 
148
{
 
149
  return c->expiry_time != 0 && c->expiry_time < cookies_now;
 
150
}
 
151
 
144
152
/* Deallocate COOKIE and its components. */
145
153
 
146
154
static void
147
155
delete_cookie (struct cookie *cookie)
148
156
{
149
 
  FREE_MAYBE (cookie->domain);
150
 
  FREE_MAYBE (cookie->path);
151
 
  FREE_MAYBE (cookie->attr);
152
 
  FREE_MAYBE (cookie->value);
 
157
  xfree_null (cookie->domain);
 
158
  xfree_null (cookie->path);
 
159
  xfree_null (cookie->attr);
 
160
  xfree_null (cookie->value);
153
161
  xfree (cookie);
154
162
}
155
163
 
253
261
  hash_table_put (jar->chains, chain_key, cookie);
254
262
  ++jar->cookie_count;
255
263
 
256
 
  DEBUGP (("\nStored cookie %s %d%s %s %s %d %s %s %s\n",
257
 
           cookie->domain, cookie->port,
258
 
           cookie->port == PORT_ANY ? " (ANY)" : "",
259
 
           cookie->path,
260
 
           cookie->permanent ? "permanent" : "nonpermanent",
261
 
           cookie->secure,
262
 
           cookie->expiry_time
263
 
           ? asctime (localtime (&cookie->expiry_time)) : "<undefined>",
264
 
           cookie->attr, cookie->value));
 
264
#ifdef ENABLE_DEBUG
 
265
  if (opt.debug)
 
266
    {
 
267
      time_t exptime = cookie->expiry_time;
 
268
      DEBUGP (("\nStored cookie %s %d%s %s <%s> <%s> [expiry %s] %s %s\n",
 
269
               cookie->domain, cookie->port,
 
270
               cookie->port == PORT_ANY ? " (ANY)" : "",
 
271
               cookie->path,
 
272
               cookie->permanent ? "permanent" : "session",
 
273
               cookie->secure ? "secure" : "insecure",
 
274
               cookie->expiry_time ? datetime_str (&exptime) : "none",
 
275
               cookie->attr, cookie->value));
 
276
    }
 
277
#endif
265
278
}
266
279
 
267
280
/* Discard a cookie matching COOKIE's domain, port, path, and
353
366
    {
354
367
      if (!VALUE_NON_EMPTY)
355
368
        return 0;
356
 
      FREE_MAYBE (cookie->domain);
 
369
      xfree_null (cookie->domain);
357
370
      /* Strictly speaking, we should set cookie->domain_exact if the
358
371
         domain doesn't begin with a dot.  But many sites set the
359
372
         domain to "foo.com" and expect "subhost.foo.com" to get the
367
380
    {
368
381
      if (!VALUE_NON_EMPTY)
369
382
        return 0;
370
 
      FREE_MAYBE (cookie->path);
 
383
      xfree_null (cookie->path);
371
384
      cookie->path = strdupdelim (value_b, value_e);
372
385
      return 1;
373
386
    }
381
394
      BOUNDED_TO_ALLOCA (value_b, value_e, value_copy);
382
395
 
383
396
      expires = http_atotm (value_copy);
384
 
      if (expires != -1)
 
397
      if (expires != (time_t) -1)
385
398
        {
386
399
          cookie->permanent = 1;
387
 
          cookie->expiry_time = (time_t)expires;
 
400
          cookie->expiry_time = expires;
388
401
        }
389
402
      else
390
 
        /* Error in expiration spec.  Assume default (cookie valid for
391
 
           this session.)  */
 
403
        /* Error in expiration spec.  Assume default (cookie doesn't
 
404
           expire, but valid only for this session.)  */
392
405
        ;
393
406
 
394
407
      /* According to netscape's specification, expiry time in the
603
616
                    char *name;
604
617
                    BOUNDED_TO_ALLOCA (name_b, name_e, name);
605
618
                    logprintf (LOG_NOTQUIET,
606
 
                               _("Error in Set-Cookie, field `%s'"), name);
 
619
                               _("Error in Set-Cookie, field `%s'"),
 
620
                               escnonprint (name));
607
621
                  }
608
622
                state = S_ERROR;
609
623
                break;
627
641
  if (!silent)
628
642
    logprintf (LOG_NOTQUIET,
629
643
               _("Syntax error in Set-Cookie: %s at position %d.\n"),
630
 
               sc, p - sc);
 
644
               escnonprint (sc), p - sc);
631
645
  return NULL;
632
646
}
633
647
 
650
664
 
651
665
/* Check whether ADDR matches <digits>.<digits>.<digits>.<digits>.
652
666
 
653
 
  We don't want to call network functions like inet_addr() because all
654
 
  we need is a check, preferrably one that is small, fast, and
655
 
  well-defined.  */
 
667
   We don't want to call network functions like inet_addr() because
 
668
   all we need is a check, preferrably one that is small, fast, and
 
669
   well-defined.  */
656
670
 
657
671
static int
658
672
numeric_address_p (const char *addr)
770
784
      {
771
785
        int i;
772
786
        int known_toplevel = 0;
773
 
        static char *known_toplevel_domains[] = {
 
787
        static const char *known_toplevel_domains[] = {
774
788
          ".com", ".edu", ".net", ".org", ".gov", ".mil", ".int"
775
789
        };
776
790
        for (i = 0; i < countof (known_toplevel_domains); i++)
819
833
   depending on the contents.  */
820
834
 
821
835
void
822
 
cookie_jar_process_set_cookie (struct cookie_jar *jar,
823
 
                               const char *host, int port,
824
 
                               const char *path, const char *set_cookie)
 
836
cookie_handle_set_cookie (struct cookie_jar *jar,
 
837
                          const char *host, int port,
 
838
                          const char *path, const char *set_cookie)
825
839
{
826
840
  struct cookie *cookie;
827
841
  cookies_now = time (NULL);
835
849
  if (!cookie->domain)
836
850
    {
837
851
    copy_domain:
 
852
      /* If the domain was not provided, we use the one we're talking
 
853
         to, and set exact match.  */
838
854
      cookie->domain = xstrdup (host);
839
 
      cookie->port = port;
 
855
      cookie->domain_exact = 1;
 
856
      /* Set the port, but only if it's non-default. */
 
857
      if (port != 80 && port != 443)
 
858
        cookie->port = port;
840
859
    }
841
860
  else
842
861
    {
844
863
        {
845
864
          logprintf (LOG_NOTQUIET,
846
865
                     "Cookie coming from %s attempted to set domain to %s\n",
847
 
                     host, cookie->domain);
 
866
                     escnonprint (host), escnonprint (cookie->domain));
848
867
          xfree (cookie->domain);
849
868
          goto copy_domain;
850
869
        }
851
870
    }
852
871
 
853
872
  if (!cookie->path)
854
 
    cookie->path = xstrdup (path);
 
873
    {
 
874
      /* The cookie doesn't set path: set it to the URL path, sans the
 
875
         file part ("/dir/file" truncated to "/dir/").  */
 
876
      char *trailing_slash = strrchr (path, '/');
 
877
      if (trailing_slash)
 
878
        cookie->path = strdupdelim (path, trailing_slash + 1);
 
879
      else
 
880
        /* no slash in the string -- can this even happen? */
 
881
        cookie->path = xstrdup (path);
 
882
    }
855
883
  else
856
884
    {
 
885
      /* The cookie sets its own path; verify that it is legal. */
857
886
      if (!check_path_match (cookie->path, path))
858
887
        {
859
888
          DEBUGP (("Attempt to fake the path: %s, %s\n",
862
891
        }
863
892
    }
864
893
 
 
894
  /* Now store the cookie, or discard an existing cookie, if
 
895
     discarding was requested.  */
 
896
 
865
897
  if (cookie->discard_requested)
866
898
    {
867
899
      discard_matching_cookie (jar, cookie);
879
911
/* Support for sending out cookies in HTTP requests, based on
880
912
   previously stored cookies.  Entry point is
881
913
   `build_cookies_request'.  */
 
914
   
 
915
/* Return a count of how many times CHR occurs in STRING. */
 
916
 
 
917
static int
 
918
count_char (const char *string, char chr)
 
919
{
 
920
  const char *p;
 
921
  int count = 0;
 
922
  for (p = string; *p; p++)
 
923
    if (*p == chr)
 
924
      ++count;
 
925
  return count;
 
926
}
882
927
 
883
928
/* Find the cookie chains whose domains match HOST and store them to
884
929
   DEST.
970
1015
{
971
1016
  int pg;
972
1017
 
973
 
  if (COOKIE_EXPIRED_P (cookie))
 
1018
  if (cookie_expired_p (cookie))
974
1019
    /* Ignore stale cookies.  Don't bother unchaining the cookie at
975
1020
       this point -- Wget is a relatively short-lived application, and
976
1021
       stale cookies will not be saved by `save_cookies'.  On the
1098
1143
   generated, NULL is returned.  */
1099
1144
 
1100
1145
char *
1101
 
cookie_jar_generate_cookie_header (struct cookie_jar *jar, const char *host,
1102
 
                                   int port, const char *path,
1103
 
                                   int connection_secure_p)
 
1146
cookie_header (struct cookie_jar *jar, const char *host,
 
1147
               int port, const char *path, int secflag)
1104
1148
{
1105
1149
  struct cookie **chains;
1106
1150
  int chain_count;
1133
1177
  count = 0;
1134
1178
  for (i = 0; i < chain_count; i++)
1135
1179
    for (cookie = chains[i]; cookie; cookie = cookie->next)
1136
 
      if (cookie_matches_url (cookie, host, port, path, connection_secure_p,
1137
 
                              NULL))
 
1180
      if (cookie_matches_url (cookie, host, port, path, secflag, NULL))
1138
1181
        ++count;
1139
1182
  if (!count)
1140
1183
    return NULL;                /* no cookies matched */
1149
1192
    for (cookie = chains[i]; cookie; cookie = cookie->next)
1150
1193
      {
1151
1194
        int pg;
1152
 
        if (!cookie_matches_url (cookie, host, port, path,
1153
 
                                 connection_secure_p, &pg))
 
1195
        if (!cookie_matches_url (cookie, host, port, path, secflag, &pg))
1154
1196
          continue;
1155
1197
        outgoing[ocnt].cookie = cookie;
1156
1198
        outgoing[ocnt].domain_goodness = strlen (cookie->domain);
1177
1219
    }
1178
1220
 
1179
1221
  /* Allocate output buffer:
1180
 
     "Cookie: "       -- 8
1181
1222
     name=value pairs -- result_size
1182
1223
     "; " separators  -- (count - 1) * 2
1183
 
     \r\n line ending -- 2
1184
1224
     \0 terminator    -- 1 */
1185
 
  result_size = 8 + result_size + (count - 1) * 2 + 2 + 1;
 
1225
  result_size = result_size + (count - 1) * 2 + 1;
1186
1226
  result = xmalloc (result_size);
1187
1227
  pos = 0;
1188
 
  strcpy (result, "Cookie: ");
1189
 
  pos += 8;
1190
1228
  for (i = 0; i < count; i++)
1191
1229
    {
1192
1230
      struct cookie *c = outgoing[i].cookie;
1204
1242
          result[pos++] = ' ';
1205
1243
        }
1206
1244
    }
1207
 
  result[pos++] = '\r';
1208
 
  result[pos++] = '\n';
1209
1245
  result[pos++] = '\0';
1210
1246
  assert (pos == result_size);
1211
1247
  return result;
1357
1393
         malloced.)  */
1358
1394
      *expires_e = '\0';
1359
1395
      sscanf (expires_b, "%lf", &expiry);
1360
 
      if (expiry < cookies_now)
1361
 
        /* ignore stale cookie. */
1362
 
        goto abort;
1363
 
      cookie->expiry_time = expiry;
1364
1396
 
1365
 
      /* If the cookie has survived being saved into an external file,
1366
 
         it is obviously permanent.  */
1367
 
      cookie->permanent = 1;
 
1397
      if (expiry == 0)
 
1398
        {
 
1399
          /* EXPIRY can be 0 for session cookies saved because the
 
1400
             user specified `--keep-session-cookies' in the past.
 
1401
             They remain session cookies, and will be saved only if
 
1402
             the user has specified `keep-session-cookies' again.  */
 
1403
        }
 
1404
      else
 
1405
        {
 
1406
          if (expiry < cookies_now)
 
1407
            goto abort_cookie;  /* ignore stale cookie. */
 
1408
          cookie->expiry_time = expiry;
 
1409
          cookie->permanent = 1;
 
1410
        }
1368
1411
 
1369
1412
      store_cookie (jar, cookie);
1370
1413
 
1371
1414
    next:
1372
1415
      continue;
1373
1416
 
1374
 
    abort:
 
1417
    abort_cookie:
1375
1418
      delete_cookie (cookie);
1376
1419
    }
1377
1420
  fclose (fp);
1389
1432
  struct cookie *cookie = (struct cookie *)value;
1390
1433
  for (; cookie; cookie = cookie->next)
1391
1434
    {
1392
 
      if (!cookie->permanent)
 
1435
      if (!cookie->permanent && !opt.keep_session_cookies)
1393
1436
        continue;
1394
 
      if (COOKIE_EXPIRED_P (cookie))
 
1437
      if (cookie_expired_p (cookie))
1395
1438
        continue;
1396
1439
      if (!cookie->domain_exact)
1397
1440
        fputc ('.', fp);
1429
1472
    }
1430
1473
 
1431
1474
  fputs ("# HTTP cookie file.\n", fp);
1432
 
  fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (NULL));
 
1475
  fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (&cookies_now));
1433
1476
  fputs ("# Edit at your own risk.\n\n", fp);
1434
1477
 
1435
1478
  hash_table_map (jar->chains, save_cookies_mapper, fp);
1437
1480
  if (ferror (fp))
1438
1481
    logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
1439
1482
               file, strerror (errno));
1440
 
 
1441
1483
  if (fclose (fp) < 0)
1442
1484
    logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
1443
1485
               file, strerror (errno));