]> sjero.net Git - wget/blob - src/http.c
[svn] Applied contributed patch.
[wget] / src / http.c
1 /* HTTP support.
2    Copyright (C) 1995, 1996, 1997, 1998 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
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU 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 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #ifdef HAVE_STRING_H
26 # include <string.h>
27 #else
28 # include <strings.h>
29 #endif
30 #include <ctype.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #include <assert.h>
35 #include <errno.h>
36 #if TIME_WITH_SYS_TIME
37 # include <sys/time.h>
38 # include <time.h>
39 #else
40 # if HAVE_SYS_TIME_H
41 #  include <sys/time.h>
42 # else
43 #  include <time.h>
44 # endif
45 #endif
46
47 #ifdef WINDOWS
48 # include <winsock.h>
49 #endif
50
51 #include "wget.h"
52 #include "utils.h"
53 #include "url.h"
54 #include "host.h"
55 #include "rbuf.h"
56 #include "retr.h"
57 #include "headers.h"
58 #include "connect.h"
59 #include "fnmatch.h"
60 #include "netrc.h"
61 #if USE_DIGEST
62 # include "md5.h"
63 #endif
64
65 extern char *version_string;
66
67 #ifndef errno
68 extern int errno;
69 #endif
70 #ifndef h_errno
71 extern int h_errno;
72 #endif
73 \f
74
75 #define TEXTHTML_S "text/html"
76 #define HTTP_ACCEPT "*/*"
77
78 /* Some status code validation macros: */
79 #define H_20X(x)        (((x) >= 200) && ((x) < 300))
80 #define H_PARTIAL(x)    ((x) == HTTP_STATUS_PARTIAL_CONTENTS)
81 #define H_REDIRECTED(x) (((x) == HTTP_STATUS_MOVED_PERMANENTLY) \
82                          || ((x) == HTTP_STATUS_MOVED_TEMPORARILY))
83
84 /* HTTP/1.0 status codes from RFC1945, provided for reference.  */
85 /* Successful 2xx.  */
86 #define HTTP_STATUS_OK                  200
87 #define HTTP_STATUS_CREATED             201
88 #define HTTP_STATUS_ACCEPTED            202
89 #define HTTP_STATUS_NO_CONTENT          204
90 #define HTTP_STATUS_PARTIAL_CONTENTS    206
91
92 /* Redirection 3xx.  */
93 #define HTTP_STATUS_MULTIPLE_CHOICES    300
94 #define HTTP_STATUS_MOVED_PERMANENTLY   301
95 #define HTTP_STATUS_MOVED_TEMPORARILY   302
96 #define HTTP_STATUS_NOT_MODIFIED        304
97
98 /* Client error 4xx.  */
99 #define HTTP_STATUS_BAD_REQUEST         400
100 #define HTTP_STATUS_UNAUTHORIZED        401
101 #define HTTP_STATUS_FORBIDDEN           403
102 #define HTTP_STATUS_NOT_FOUND           404
103
104 /* Server errors 5xx.  */
105 #define HTTP_STATUS_INTERNAL            500
106 #define HTTP_STATUS_NOT_IMPLEMENTED     501
107 #define HTTP_STATUS_BAD_GATEWAY         502
108 #define HTTP_STATUS_UNAVAILABLE         503
109
110 \f
111 /* Parse the HTTP status line, which is of format:
112
113    HTTP-Version SP Status-Code SP Reason-Phrase
114
115    The function returns the status-code, or -1 if the status line is
116    malformed.  The pointer to reason-phrase is returned in RP.  */
117 static int
118 parse_http_status_line (const char *line, const char **reason_phrase_ptr)
119 {
120   /* (the variables must not be named `major' and `minor', because
121      that breaks compilation with SunOS4 cc.)  */
122   int mjr, mnr, statcode;
123   const char *p;
124
125   *reason_phrase_ptr = NULL;
126
127   /* The standard format of HTTP-Version is: `HTTP/X.Y', where X is
128      major version, and Y is minor version.  */
129   if (strncmp (line, "HTTP/", 5) != 0)
130     return -1;
131   line += 5;
132
133   /* Calculate major HTTP version.  */
134   p = line;
135   for (mjr = 0; ISDIGIT (*line); line++)
136     mjr = 10 * mjr + (*line - '0');
137   if (*line != '.' || p == line)
138     return -1;
139   ++line;
140
141   /* Calculate minor HTTP version.  */
142   p = line;
143   for (mnr = 0; ISDIGIT (*line); line++)
144     mnr = 10 * mnr + (*line - '0');
145   if (*line != ' ' || p == line)
146     return -1;
147   /* Wget will accept only 1.0 and higher HTTP-versions.  The value of
148      minor version can be safely ignored.  */
149   if (mjr < 1)
150     return -1;
151   ++line;
152
153   /* Calculate status code.  */
154   if (!(ISDIGIT (*line) && ISDIGIT (line[1]) && ISDIGIT (line[2])))
155     return -1;
156   statcode = 100 * (*line - '0') + 10 * (line[1] - '0') + (line[2] - '0');
157
158   /* Set up the reason phrase pointer.  */
159   line += 3;
160   /* RFC2068 requires SPC here, but we allow the string to finish
161      here, in case no reason-phrase is present.  */
162   if (*line != ' ')
163     {
164       if (!*line)
165         *reason_phrase_ptr = line;
166       else
167         return -1;
168     }
169   else
170     *reason_phrase_ptr = line + 1;
171
172   return statcode;
173 }
174 \f
175 /* Functions to be used as arguments to header_process(): */
176
177 struct http_process_range_closure {
178   long first_byte_pos;
179   long last_byte_pos;
180   long entity_length;
181 };
182
183 /* Parse the `Content-Range' header and extract the information it
184    contains.  Returns 1 if successful, -1 otherwise.  */
185 static int
186 http_process_range (const char *hdr, void *arg)
187 {
188   struct http_process_range_closure *closure
189     = (struct http_process_range_closure *)arg;
190   long num;
191
192   /* Certain versions of Nutscape proxy server send out
193      `Content-Length' without "bytes" specifier, which is a breach of
194      RFC2068 (as well as the HTTP/1.1 draft which was current at the
195      time).  But hell, I must support it...  */
196   if (!strncasecmp (hdr, "bytes", 5))
197     {
198       hdr += 5;
199       hdr += skip_lws (hdr);
200       if (!*hdr)
201         return 0;
202     }
203   if (!ISDIGIT (*hdr))
204     return 0;
205   for (num = 0; ISDIGIT (*hdr); hdr++)
206     num = 10 * num + (*hdr - '0');
207   if (*hdr != '-' || !ISDIGIT (*(hdr + 1)))
208     return 0;
209   closure->first_byte_pos = num;
210   ++hdr;
211   for (num = 0; ISDIGIT (*hdr); hdr++)
212     num = 10 * num + (*hdr - '0');
213   if (*hdr != '/' || !ISDIGIT (*(hdr + 1)))
214     return 0;
215   closure->last_byte_pos = num;
216   ++hdr;
217   for (num = 0; ISDIGIT (*hdr); hdr++)
218     num = 10 * num + (*hdr - '0');
219   closure->entity_length = num;
220   return 1;
221 }
222
223 /* Place 1 to ARG if the HDR contains the word "none", 0 otherwise.
224    Used for `Accept-Ranges'.  */
225 static int
226 http_process_none (const char *hdr, void *arg)
227 {
228   int *where = (int *)arg;
229
230   if (strstr (hdr, "none"))
231     *where = 1;
232   else
233     *where = 0;
234   return 1;
235 }
236
237 /* Place the malloc-ed copy of HDR hdr, to the first `;' to ARG.  */
238 static int
239 http_process_type (const char *hdr, void *arg)
240 {
241   char **result = (char **)arg;
242   char *p;
243
244   *result = xstrdup (hdr);
245   p = strrchr (hdr, ';');
246   if (p)
247     {
248       int len = p - hdr;
249       *result = (char *)xmalloc (len + 1);
250       memcpy (*result, hdr, len);
251       (*result)[len] = '\0';
252     }
253   else
254     *result = xstrdup (hdr);
255   return 1;
256 }
257
258 \f
259 struct http_stat
260 {
261   long len;                     /* received length */
262   long contlen;                 /* expected length */
263   long restval;                 /* the restart value */
264   int res;                      /* the result of last read */
265   char *newloc;                 /* new location (redirection) */
266   char *remote_time;            /* remote time-stamp string */
267   char *error;                  /* textual HTTP error */
268   int statcode;                 /* status code */
269   long dltime;                  /* time of the download */
270 };
271
272 /* Free the elements of hstat X.  */
273 #define FREEHSTAT(x) do                                 \
274 {                                                       \
275   FREE_MAYBE ((x).newloc);                              \
276   FREE_MAYBE ((x).remote_time);                         \
277   FREE_MAYBE ((x).error);                               \
278   (x).newloc = (x).remote_time = (x).error = NULL;      \
279 } while (0)
280
281 static char *create_authorization_line PARAMS ((const char *, const char *,
282                                                 const char *, const char *,
283                                                 const char *));
284 static char *basic_authentication_encode PARAMS ((const char *, const char *,
285                                                   const char *));
286 static int known_authentication_scheme_p PARAMS ((const char *));
287
288 static time_t http_atotm PARAMS ((char *));
289
290 /* Retrieve a document through HTTP protocol.  It recognizes status
291    code, and correctly handles redirections.  It closes the network
292    socket.  If it receives an error from the functions below it, it
293    will print it if there is enough information to do so (almost
294    always), returning the error to the caller (i.e. http_loop).
295
296    Various HTTP parameters are stored to hs.  Although it parses the
297    response code correctly, it is not used in a sane way.  The caller
298    can do that, though.
299
300    If u->proxy is non-NULL, the URL u will be taken as a proxy URL,
301    and u->proxy->url will be given to the proxy server (bad naming,
302    I'm afraid).  */
303 static uerr_t
304 gethttp (struct urlinfo *u, struct http_stat *hs, int *dt)
305 {
306   char *request, *type, *command, *path;
307   char *user, *passwd;
308   char *pragma_h, *referer, *useragent, *range, *wwwauth, *remhost;
309   char *authenticate_h;
310   char *proxyauth;
311   char *all_headers;
312   char *host_port;
313   int host_port_len;
314   int sock, hcount, num_written, all_length, remport, statcode;
315   long contlen, contrange;
316   struct urlinfo *ou;
317   uerr_t err;
318   FILE *fp;
319   int auth_tried_already;
320   struct rbuf rbuf;
321
322   /* Let the others worry about local filename...  */
323   if (!(*dt & HEAD_ONLY))
324     assert (u->local != NULL);
325
326   authenticate_h = 0;
327   auth_tried_already = 0;
328
329  again:
330   /* We need to come back here when the initial attempt to retrieve
331      without authorization header fails.  */
332
333   /* Initialize certain elements of struct hstat.  */
334   hs->len = 0L;
335   hs->contlen = -1;
336   hs->res = -1;
337   hs->newloc = NULL;
338   hs->remote_time = NULL;
339   hs->error = NULL;
340
341   /* Which structure to use to retrieve the original URL data.  */
342   if (u->proxy)
343     ou = u->proxy;
344   else
345     ou = u;
346
347   /* First: establish the connection.  */
348   logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
349   err = make_connection (&sock, u->host, u->port);
350   switch (err)
351     {
352     case HOSTERR:
353       logputs (LOG_VERBOSE, "\n");
354       logprintf (LOG_NOTQUIET, "%s: %s.\n", u->host, herrmsg (h_errno));
355       return HOSTERR;
356       break;
357     case CONSOCKERR:
358       logputs (LOG_VERBOSE, "\n");
359       logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
360       return CONSOCKERR;
361       break;
362     case CONREFUSED:
363       logputs (LOG_VERBOSE, "\n");
364       logprintf (LOG_NOTQUIET,
365                  _("Connection to %s:%hu refused.\n"), u->host, u->port);
366       CLOSE (sock);
367       return CONREFUSED;
368     case CONERROR:
369       logputs (LOG_VERBOSE, "\n");
370       logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
371       CLOSE (sock);
372       return CONERROR;
373       break;
374     case NOCONERROR:
375       /* Everything is fine!  */
376       logputs (LOG_VERBOSE, _("connected!\n"));
377       break;
378     default:
379       abort ();
380       break;
381     } /* switch */
382
383   if (u->proxy)
384     path = u->proxy->url;
385   else
386     path = u->path;
387   command = (*dt & HEAD_ONLY) ? "HEAD" : "GET";
388   referer = NULL;
389   if (ou->referer)
390     {
391       referer = (char *)alloca (9 + strlen (ou->referer) + 3);
392       sprintf (referer, "Referer: %s\r\n", ou->referer);
393     }
394   if (*dt & SEND_NOCACHE)
395     pragma_h = "Pragma: no-cache\r\n";
396   else
397     pragma_h = "";
398   if (hs->restval)
399     {
400       range = (char *)alloca (13 + numdigit (hs->restval) + 4);
401       /* #### Gag me!  Some servers (e.g. WebSitePro) have been known
402          to misinterpret the following `Range' format, and return the
403          document as multipart/x-byte-ranges MIME type!
404
405          #### TODO: Interpret MIME types, recognize bullshits similar
406          the one described above, and deal with them!  */
407       sprintf (range, "Range: bytes=%ld-\r\n", hs->restval);
408     }
409   else
410     range = NULL;
411   if (opt.useragent)
412     STRDUP_ALLOCA (useragent, opt.useragent);
413   else
414     {
415       useragent = (char *)alloca (10 + strlen (version_string));
416       sprintf (useragent, "Wget/%s", version_string);
417     }
418   /* Construct the authentication, if userid is present.  */
419   user = ou->user;
420   passwd = ou->passwd;
421   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 0);
422   user = user ? user : opt.http_user;
423   passwd = passwd ? passwd : opt.http_passwd;
424
425   wwwauth = NULL;
426   if (authenticate_h && user && passwd)
427     {
428       wwwauth = create_authorization_line (authenticate_h, user, passwd,
429                                            command, ou->path);
430     }
431
432   proxyauth = NULL;
433   if (u->proxy)
434     {
435       char *proxy_user, *proxy_passwd;
436       /* For normal username and password, URL components override
437          command-line/wgetrc parameters.  With proxy authentication,
438          it's the reverse, because proxy URLs are normally the
439          "permanent" ones, so command-line args should take
440          precedence.  */
441       if (opt.proxy_user && opt.proxy_passwd)
442         {
443           proxy_user = opt.proxy_user;
444           proxy_passwd = opt.proxy_passwd;
445         }
446       else
447         {
448           proxy_user = u->user;
449           proxy_passwd = u->passwd;
450         }
451       /* #### This is junky.  Can't the proxy request, say, `Digest'
452          authentication?  */
453       if (proxy_user && proxy_passwd)
454         proxyauth = basic_authentication_encode (proxy_user, proxy_passwd,
455                                                  "Proxy-Authorization");
456     }
457   remhost = ou->host;
458   remport = ou->port;
459
460   if (remport == 80) {
461       host_port = NULL; host_port_len = 0;
462   }
463   else {
464       host_port = (char *)alloca (numdigit (remport) + 2);
465       host_port_len = sprintf (host_port, ":%d", remport);
466   }
467
468   /* Allocate the memory for the request.  */
469   request = (char *)alloca (strlen (command) + strlen (path)
470                             + strlen (useragent)
471                             + strlen (remhost) + host_port_len
472                             + strlen (HTTP_ACCEPT)
473                             + (referer ? strlen (referer) : 0)
474                             + (wwwauth ? strlen (wwwauth) : 0)
475                             + (proxyauth ? strlen (proxyauth) : 0)
476                             + (range ? strlen (range) : 0)
477                             + strlen (pragma_h)
478                             + (opt.user_header ? strlen (opt.user_header) : 0)
479                             + 64);
480   /* Construct the request.  */
481   sprintf (request, "\
482 %s %s HTTP/1.0\r\n\
483 User-Agent: %s\r\n\
484 Host: %s%s\r\n\
485 Accept: %s\r\n\
486 %s%s%s%s%s%s\r\n",
487           command, path, useragent, remhost, host_port ? host_port : "",
488           HTTP_ACCEPT, referer ? referer : "",
489           wwwauth ? wwwauth : "", 
490           proxyauth ? proxyauth : "", 
491           range ? range : "",
492           pragma_h, 
493           opt.user_header ? opt.user_header : "");
494   DEBUGP (("---request begin---\n%s---request end---\n", request));
495    /* Free the temporary memory.  */
496   FREE_MAYBE (wwwauth);
497   FREE_MAYBE (proxyauth);
498
499   /* Send the request to server.  */
500   num_written = iwrite (sock, request, strlen (request));
501   if (num_written < 0)
502     {
503       logputs (LOG_VERBOSE, _("Failed writing HTTP request.\n"));
504       free (request);
505       CLOSE (sock);
506       return WRITEFAILED;
507     }
508   logprintf (LOG_VERBOSE, _("%s request sent, awaiting response... "),
509              u->proxy ? "Proxy" : "HTTP");
510   contlen = contrange = -1;
511   type = NULL;
512   statcode = -1;
513   *dt &= ~RETROKF;
514
515   /* Before reading anything, initialize the rbuf.  */
516   rbuf_initialize (&rbuf, sock);
517
518   all_headers = NULL;
519   all_length = 0;
520   /* Header-fetching loop.  */
521   hcount = 0;
522   while (1)
523     {
524       char *hdr;
525       int status;
526
527       ++hcount;
528       /* Get the header.  */
529       status = header_get (&rbuf, &hdr,
530                            /* Disallow continuations for status line.  */
531                            (hcount == 1 ? HG_NO_CONTINUATIONS : HG_NONE));
532
533       /* Check for errors.  */
534       if (status == HG_EOF && *hdr)
535         {
536           /* This used to be an unconditional error, but that was
537              somewhat controversial, because of a large number of
538              broken CGI's that happily "forget" to send the second EOL
539              before closing the connection of a HEAD request.
540
541              So, the deal is to check whether the header is empty
542              (*hdr is zero if it is); if yes, it means that the
543              previous header was fully retrieved, and that -- most
544              probably -- the request is complete.  "...be liberal in
545              what you accept."  Oh boy.  */
546           logputs (LOG_VERBOSE, "\n");
547           logputs (LOG_NOTQUIET, _("End of file while parsing headers.\n"));
548           free (hdr);
549           FREE_MAYBE (type);
550           FREE_MAYBE (hs->newloc);
551           FREE_MAYBE (all_headers);
552           CLOSE (sock);
553           return HEOF;
554         }
555       else if (status == HG_ERROR)
556         {
557           logputs (LOG_VERBOSE, "\n");
558           logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),
559                      strerror (errno));
560           free (hdr);
561           FREE_MAYBE (type);
562           FREE_MAYBE (hs->newloc);
563           FREE_MAYBE (all_headers);
564           CLOSE (sock);
565           return HERR;
566         }
567
568       /* If the headers are to be saved to a file later, save them to
569          memory now.  */
570       if (opt.save_headers)
571         {
572           int lh = strlen (hdr);
573           all_headers = (char *)xrealloc (all_headers, all_length + lh + 2);
574           memcpy (all_headers + all_length, hdr, lh);
575           all_length += lh;
576           all_headers[all_length++] = '\n';
577           all_headers[all_length] = '\0';
578         }
579
580       /* Print the header if requested.  */
581       if (opt.server_response && hcount != 1)
582         logprintf (LOG_VERBOSE, "\n%d %s", hcount, hdr);
583
584       /* Check for status line.  */
585       if (hcount == 1)
586         {
587           const char *error;
588           /* Parse the first line of server response.  */
589           statcode = parse_http_status_line (hdr, &error);
590           hs->statcode = statcode;
591           /* Store the descriptive response.  */
592           if (statcode == -1) /* malformed response */
593             {
594               /* A common reason for "malformed response" error is the
595                  case when no data was actually received.  Handle this
596                  special case.  */
597               if (!*hdr)
598                 hs->error = xstrdup (_("No data received"));
599               else
600                 hs->error = xstrdup (_("Malformed status line"));
601               free (hdr);
602               break;
603             }
604           else if (!*error)
605             hs->error = xstrdup (_("(no description)"));
606           else
607             hs->error = xstrdup (error);
608
609           if ((statcode != -1)
610 #ifdef DEBUG
611               && !opt.debug
612 #endif
613               )
614             logprintf (LOG_VERBOSE, "%d %s", statcode, error);
615
616           goto done_header;
617         }
618
619       /* Exit on empty header.  */
620       if (!*hdr)
621         {
622           free (hdr);
623           break;
624         }
625
626       /* Try getting content-length.  */
627       if (contlen == -1 && !opt.ignore_length)
628         if (header_process (hdr, "Content-Length", header_extract_number,
629                             &contlen))
630           goto done_header;
631       /* Try getting content-type.  */
632       if (!type)
633         if (header_process (hdr, "Content-Type", http_process_type, &type))
634           goto done_header;
635       /* Try getting location.  */
636       if (!hs->newloc)
637         if (header_process (hdr, "Location", header_strdup, &hs->newloc))
638           goto done_header;
639       /* Try getting last-modified.  */
640       if (!hs->remote_time)
641         if (header_process (hdr, "Last-Modified", header_strdup,
642                             &hs->remote_time))
643           goto done_header;
644       /* Try getting www-authentication.  */
645       if (!authenticate_h)
646         if (header_process (hdr, "WWW-Authenticate", header_strdup,
647                             &authenticate_h))
648           goto done_header;
649       /* Check for accept-ranges header.  If it contains the word
650          `none', disable the ranges.  */
651       if (*dt & ACCEPTRANGES)
652         {
653           int nonep;
654           if (header_process (hdr, "Accept-Ranges", http_process_none, &nonep))
655             {
656               if (nonep)
657                 *dt &= ~ACCEPTRANGES;
658               goto done_header;
659             }
660         }
661       /* Try getting content-range.  */
662       if (contrange == -1)
663         {
664           struct http_process_range_closure closure;
665           if (header_process (hdr, "Content-Range", http_process_range, &closure))
666             {
667               contrange = closure.first_byte_pos;
668               goto done_header;
669             }
670         }
671     done_header:
672       free (hdr);
673     }
674
675   logputs (LOG_VERBOSE, "\n");
676
677   if ((statcode == HTTP_STATUS_UNAUTHORIZED)
678       && authenticate_h)
679     {
680       /* Authorization is required.  */
681       FREE_MAYBE (type);
682       type = NULL;
683       FREEHSTAT (*hs);
684       CLOSE (sock);
685       if (auth_tried_already)
686         {
687           /* If we have tried it already, then there is not point
688              retrying it.  */
689           logputs (LOG_NOTQUIET, _("Authorization failed.\n"));
690           free (authenticate_h);
691           return AUTHFAILED;
692         }
693       else if (!known_authentication_scheme_p (authenticate_h))
694         {
695           free (authenticate_h);
696           logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));
697           return AUTHFAILED;
698         }
699       else
700         {
701           auth_tried_already = 1;
702           goto again;
703         }
704     }
705   /* We do not need this anymore.  */
706   if (authenticate_h)
707     {
708       free (authenticate_h);
709       authenticate_h = NULL;
710     }
711
712   /* 20x responses are counted among successful by default.  */
713   if (H_20X (statcode))
714     *dt |= RETROKF;
715
716   if (type && !strncasecmp (type, TEXTHTML_S, strlen (TEXTHTML_S)))
717     *dt |= TEXTHTML;
718   else
719     /* We don't assume text/html by default.  */
720     *dt &= ~TEXTHTML;
721
722   if (contrange == -1)
723     hs->restval = 0;
724   else if (contrange != hs->restval ||
725            (H_PARTIAL (statcode) && contrange == -1))
726     {
727       /* This means the whole request was somehow misunderstood by the
728          server.  Bail out.  */
729       FREE_MAYBE (type);
730       FREE_MAYBE (hs->newloc);
731       FREE_MAYBE (all_headers);
732       CLOSE (sock);
733       return RANGEERR;
734     }
735
736   if (hs->restval)
737     {
738       if (contlen != -1)
739         contlen += contrange;
740       else
741         contrange = -1;        /* If conent-length was not sent,
742                                   content-range will be ignored.  */
743     }
744   hs->contlen = contlen;
745
746   /* Return if redirected.  */
747   if (H_REDIRECTED (statcode) || statcode == HTTP_STATUS_MULTIPLE_CHOICES)
748     {
749       /* RFC2068 says that in case of the 300 (multiple choices)
750          response, the server can output a preferred URL through
751          `Location' header; otherwise, the request should be treated
752          like GET.  So, if the location is set, it will be a
753          redirection; otherwise, just proceed normally.  */
754       if (statcode == HTTP_STATUS_MULTIPLE_CHOICES && !hs->newloc)
755         *dt |= RETROKF;
756       else
757         {
758           logprintf (LOG_VERBOSE,
759                      _("Location: %s%s\n"),
760                      hs->newloc ? hs->newloc : _("unspecified"),
761                      hs->newloc ? _(" [following]") : "");
762           CLOSE (sock);
763           FREE_MAYBE (type);
764           FREE_MAYBE (all_headers);
765           return NEWLOCATION;
766         }
767     }
768   if (opt.verbose)
769     {
770       if ((*dt & RETROKF) && !opt.server_response)
771         {
772           /* No need to print this output if the body won't be
773              downloaded at all, or if the original server response is
774              printed.  */
775           logputs (LOG_VERBOSE, _("Length: "));
776           if (contlen != -1)
777             {
778               logputs (LOG_VERBOSE, legible (contlen));
779               if (contrange != -1)
780                 logprintf (LOG_VERBOSE, _(" (%s to go)"),
781                            legible (contlen - contrange));
782             }
783           else
784             logputs (LOG_VERBOSE,
785                      opt.ignore_length ? _("ignored") : _("unspecified"));
786           if (type)
787             logprintf (LOG_VERBOSE, " [%s]\n", type);
788           else
789             logputs (LOG_VERBOSE, "\n");
790         }
791     }
792   FREE_MAYBE (type);
793   type = NULL;                  /* We don't need it any more.  */
794
795   /* Return if we have no intention of further downloading.  */
796   if (!(*dt & RETROKF) || (*dt & HEAD_ONLY))
797     {
798       /* In case someone cares to look...  */
799       hs->len = 0L;
800       hs->res = 0;
801       FREE_MAYBE (type);
802       FREE_MAYBE (all_headers);
803       CLOSE (sock);
804       return RETRFINISHED;
805     }
806
807   /* Open the local file.  */
808   if (!opt.dfp)
809     {
810       mkalldirs (u->local);
811       if (opt.backups)
812         rotate_backups (u->local);
813       fp = fopen (u->local, hs->restval ? "ab" : "wb");
814       if (!fp)
815         {
816           logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
817           CLOSE (sock);
818           FREE_MAYBE (all_headers);
819           return FOPENERR;
820         }
821     }
822   else                      /* opt.dfp */
823     fp = opt.dfp;
824
825   /* #### This confuses the code that checks for file size.  There
826      should be some overhead information.  */
827   if (opt.save_headers)
828     fwrite (all_headers, 1, all_length, fp);
829   reset_timer ();
830   /* Get the contents of the document.  */
831   hs->res = get_contents (sock, fp, &hs->len, hs->restval,
832                           (contlen != -1 ? contlen : 0),
833                           &rbuf);
834   hs->dltime = elapsed_time ();
835   if (!opt.dfp)
836     fclose (fp);
837   else
838     fflush (fp);
839   FREE_MAYBE (all_headers);
840   CLOSE (sock);
841   if (hs->res == -2)
842     return FWRITEERR;
843   return RETRFINISHED;
844 }
845
846 /* The genuine HTTP loop!  This is the part where the retrieval is
847    retried, and retried, and retried, and...  */
848 uerr_t
849 http_loop (struct urlinfo *u, char **newloc, int *dt)
850 {
851   static int first_retrieval = 1;
852
853   int count;
854   int local_dot_orig_file_exists = FALSE;
855   int use_ts, got_head = 0;     /* time-stamping info */
856   char *tms, *suf, *locf, *tmrate;
857   uerr_t err;
858   time_t tml = -1, tmr = -1;    /* local and remote time-stamps */
859   long local_size = 0;          /* the size of the local file */
860   struct http_stat hstat;       /* HTTP status */
861   struct stat st;
862
863   *newloc = NULL;
864
865   /* Warn on (likely bogus) wildcard usage in HTTP.  Don't use
866      has_wildcards_p because it would also warn on `?', and we know that
867      shows up in CGI paths a *lot*.  */
868   if (strchr (u->url, '*'))
869     logputs (LOG_VERBOSE, _("Warning: wildcards not supported in HTTP.\n"));
870
871   /* Determine the local filename.  */
872   if (!u->local)
873     u->local = url_filename (u->proxy ? u->proxy : u);
874
875   if (!opt.output_document)
876     locf = u->local;
877   else
878     locf = opt.output_document;
879
880   if (opt.noclobber && file_exists_p (u->local))
881     {
882       /* If opt.noclobber is turned on and file already exists, do not
883          retrieve the file */
884       logprintf (LOG_VERBOSE, _("\
885 File `%s' already there, will not retrieve.\n"), u->local);
886       /* If the file is there, we suppose it's retrieved OK.  */
887       *dt |= RETROKF;
888
889       /* #### Bogusness alert.  */
890       /* If its suffix is "html" or (yuck!) "htm", we suppose it's
891          text/html, a harmless lie.  */
892       if (((suf = suffix (u->local)) != NULL)
893           && (!strcmp (suf, "html") || !strcmp (suf, "htm")))
894         *dt |= TEXTHTML;
895       free (suf);
896       /* Another harmless lie: */
897       return RETROK;
898     }
899
900   use_ts = 0;
901   if (opt.timestamping)
902     {
903       boolean  local_file_exists = FALSE;
904
905       if (opt.backup_converted)
906         /* If -K is specified, we'll act on the assumption that it was specified
907            last time these files were downloaded as well, and instead of just
908            comparing local file X against server file X, we'll compare local
909            file X.orig (if extant, else X) against server file X.  If -K
910            _wasn't_ specified last time, or the server contains files called
911            *.orig, -N will be back to not operating correctly with -k. */
912         {
913           size_t filename_len = strlen(u->local);
914           char*  filename_plus_orig_suffix = malloc(filename_len +
915                                                     sizeof(".orig"));
916
917           /* Would a single s[n]printf() call be faster? */
918           strcpy(filename_plus_orig_suffix, u->local);
919           strcpy(filename_plus_orig_suffix + filename_len, ".orig");
920
921           /* Try to stat() the .orig file. */
922           if (stat(filename_plus_orig_suffix, &st) == 0)
923             {
924               local_file_exists = TRUE;
925               local_dot_orig_file_exists = TRUE;
926             }
927
928           free(filename_plus_orig_suffix);
929         }      
930
931       if (!local_dot_orig_file_exists)
932         /* Couldn't stat() <file>.orig, so try to stat() <file>. */
933         if (stat (u->local, &st) == 0)
934           local_file_exists = TRUE;
935
936       if (local_file_exists)
937         /* There was a local file, so we'll check later to see if the version
938            the server has is the same version we already have, allowing us to
939            skip a download. */
940         {
941           use_ts = 1;
942           tml = st.st_mtime;
943           local_size = st.st_size;
944           got_head = 0;
945         }
946     }
947   /* Reset the counter.  */
948   count = 0;
949   *dt = 0 | ACCEPTRANGES;
950   /* THE loop */
951   do
952     {
953       /* Increment the pass counter.  */
954       ++count;
955       /* Wait before the retrieval (unless this is the very first
956          retrieval).  */
957       if (!first_retrieval && opt.wait)
958         sleep (opt.wait);
959       if (first_retrieval)
960         first_retrieval = 0;
961       /* Get the current time string.  */
962       tms = time_str (NULL);
963       /* Print fetch message, if opt.verbose.  */
964       if (opt.verbose)
965         {
966           char *hurl = str_url (u->proxy ? u->proxy : u, 1);
967           char tmp[15];
968           strcpy (tmp, "        ");
969           if (count > 1)
970             sprintf (tmp, _("(try:%2d)"), count);
971           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
972                      tms, hurl, tmp, locf);
973 #ifdef WINDOWS
974           ws_changetitle (hurl, 1);
975 #endif
976           free (hurl);
977         }
978
979       /* Default document type is empty.  However, if spider mode is
980          on or time-stamping is employed, HEAD_ONLY commands is
981          encoded within *dt.  */
982       if (opt.spider || (use_ts && !got_head))
983         *dt |= HEAD_ONLY;
984       else
985         *dt &= ~HEAD_ONLY;
986       /* Assume no restarting.  */
987       hstat.restval = 0L;
988       /* Decide whether or not to restart.  */
989       if (((count > 1 && (*dt & ACCEPTRANGES)) || opt.always_rest)
990           && file_exists_p (u->local))
991         if (stat (u->local, &st) == 0)
992           hstat.restval = st.st_size;
993       /* Decide whether to send the no-cache directive.  */
994       if (u->proxy && (count > 1 || (opt.proxy_cache == 0)))
995         *dt |= SEND_NOCACHE;
996       else
997         *dt &= ~SEND_NOCACHE;
998
999       /* Try fetching the document, or at least its head.  :-) */
1000       err = gethttp (u, &hstat, dt);
1001       /* Time?  */
1002       tms = time_str (NULL);
1003       /* Get the new location (with or without the redirection).  */
1004       if (hstat.newloc)
1005         *newloc = xstrdup (hstat.newloc);
1006       switch (err)
1007         {
1008         case HERR: case HEOF: case CONSOCKERR: case CONCLOSED:
1009         case CONERROR: case READERR: case WRITEFAILED:
1010         case RANGEERR:
1011           /* Non-fatal errors continue executing the loop, which will
1012              bring them to "while" statement at the end, to judge
1013              whether the number of tries was exceeded.  */
1014           FREEHSTAT (hstat);
1015           printwhat (count, opt.ntry);
1016           continue;
1017           break;
1018         case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED:
1019           /* Fatal errors just return from the function.  */
1020           FREEHSTAT (hstat);
1021           return err;
1022           break;
1023         case FWRITEERR: case FOPENERR:
1024           /* Another fatal error.  */
1025           logputs (LOG_VERBOSE, "\n");
1026           logprintf (LOG_NOTQUIET, _("Cannot write to `%s' (%s).\n"),
1027                      u->local, strerror (errno));
1028           FREEHSTAT (hstat);
1029           return err;
1030           break;
1031         case NEWLOCATION:
1032           /* Return the new location to the caller.  */
1033           if (!hstat.newloc)
1034             {
1035               logprintf (LOG_NOTQUIET,
1036                          _("ERROR: Redirection (%d) without location.\n"),
1037                          hstat.statcode);
1038               return WRONGCODE;
1039             }
1040           FREEHSTAT (hstat);
1041           return NEWLOCATION;
1042           break;
1043         case RETRFINISHED:
1044           /* Deal with you later.  */
1045           break;
1046         default:
1047           /* All possibilities should have been exhausted.  */
1048           abort ();
1049         }
1050       if (!(*dt & RETROKF))
1051         {
1052           if (!opt.verbose)
1053             {
1054               /* #### Ugly ugly ugly! */
1055               char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1056               logprintf (LOG_NONVERBOSE, "%s:\n", hurl);
1057               free (hurl);
1058             }
1059           logprintf (LOG_NOTQUIET, _("%s ERROR %d: %s.\n"),
1060                      tms, hstat.statcode, hstat.error);
1061           logputs (LOG_VERBOSE, "\n");
1062           FREEHSTAT (hstat);
1063           return WRONGCODE;
1064         }
1065
1066       /* Did we get the time-stamp?  */
1067       if (!got_head)
1068         {
1069           if (opt.timestamping && !hstat.remote_time)
1070             {
1071               logputs (LOG_NOTQUIET, _("\
1072 Last-modified header missing -- time-stamps turned off.\n"));
1073             }
1074           else if (hstat.remote_time)
1075             {
1076               /* Convert the date-string into struct tm.  */
1077               tmr = http_atotm (hstat.remote_time);
1078               if (tmr == (time_t) (-1))
1079                 logputs (LOG_VERBOSE, _("\
1080 Last-modified header invalid -- time-stamp ignored.\n"));
1081             }
1082         }
1083
1084       /* The time-stamping section.  */
1085       if (use_ts)
1086         {
1087           got_head = 1;
1088           *dt &= ~HEAD_ONLY;
1089           use_ts = 0;           /* no more time-stamping */
1090           count = 0;            /* the retrieve count for HEAD is
1091                                    reset */
1092           if (hstat.remote_time && tmr != (time_t) (-1))
1093             {
1094               /* Now time-stamping can be used validly.  Time-stamping
1095                  means that if the sizes of the local and remote file
1096                  match, and local file is newer than the remote file,
1097                  it will not be retrieved.  Otherwise, the normal
1098                  download procedure is resumed.  */
1099               if (tml >= tmr &&
1100                   (hstat.contlen == -1 || local_size == hstat.contlen))
1101                 {
1102                   if (local_dot_orig_file_exists)
1103                     /* We can't collapse this down into just one logprintf()
1104                        call with a variable set to u->local or the .orig
1105                        filename because we have to malloc() space for the
1106                        latter, and because there are multiple returns above (a
1107                        coding style no-no by many measures, for reasons such as
1108                        this) we'd have to remember to free() the string at each
1109                        one to avoid a memory leak. */
1110                     logprintf (LOG_VERBOSE, _("\
1111 Server file no newer than local file `%s.orig' -- not retrieving.\n\n"),
1112                                u->local);
1113                   else
1114                     logprintf (LOG_VERBOSE, _("\
1115 Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
1116                   FREEHSTAT (hstat);
1117                   return RETROK;
1118                 }
1119               else if (tml >= tmr)
1120                 logprintf (LOG_VERBOSE, _("\
1121 The sizes do not match (local %ld) -- retrieving.\n"), local_size);
1122               else
1123                 logputs (LOG_VERBOSE,
1124                          _("Remote file is newer, retrieving.\n"));
1125             }
1126           FREEHSTAT (hstat);
1127           continue;
1128         }
1129       if (!opt.dfp
1130           && (tmr != (time_t) (-1))
1131           && !opt.spider
1132           && ((hstat.len == hstat.contlen) ||
1133               ((hstat.res == 0) &&
1134                ((hstat.contlen == -1) ||
1135                 (hstat.len >= hstat.contlen && !opt.kill_longer)))))
1136         {
1137           touch (u->local, tmr);
1138         }
1139       /* End of time-stamping section.  */
1140
1141       if (opt.spider)
1142         {
1143           logprintf (LOG_NOTQUIET, "%d %s\n\n", hstat.statcode, hstat.error);
1144           return RETROK;
1145         }
1146
1147       /* It is now safe to free the remainder of hstat, since the
1148          strings within it will no longer be used.  */
1149       FREEHSTAT (hstat);
1150
1151       tmrate = rate (hstat.len - hstat.restval, hstat.dltime);
1152
1153       if (hstat.len == hstat.contlen)
1154         {
1155           if (*dt & RETROKF)
1156             {
1157               logprintf (LOG_VERBOSE,
1158                          _("%s (%s) - `%s' saved [%ld/%ld]\n\n"),
1159                          tms, tmrate, locf, hstat.len, hstat.contlen);
1160               logprintf (LOG_NONVERBOSE,
1161                          "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n",
1162                          tms, u->url, hstat.len, hstat.contlen, locf, count);
1163             }
1164           ++opt.numurls;
1165           opt.downloaded += hstat.len;
1166           downloaded_file(ADD_FILE, locf);
1167           return RETROK;
1168         }
1169       else if (hstat.res == 0) /* No read error */
1170         {
1171           if (hstat.contlen == -1)  /* We don't know how much we were supposed
1172                                        to get, so assume we succeeded. */ 
1173             {
1174               if (*dt & RETROKF)
1175                 {
1176                   logprintf (LOG_VERBOSE,
1177                              _("%s (%s) - `%s' saved [%ld]\n\n"),
1178                              tms, tmrate, locf, hstat.len);
1179                   logprintf (LOG_NONVERBOSE,
1180                              "%s URL:%s [%ld] -> \"%s\" [%d]\n",
1181                              tms, u->url, hstat.len, locf, count);
1182                 }
1183               ++opt.numurls;
1184               opt.downloaded += hstat.len;
1185               downloaded_file(ADD_FILE, locf);
1186               return RETROK;
1187             }
1188           else if (hstat.len < hstat.contlen) /* meaning we lost the
1189                                                  connection too soon */
1190             {
1191               logprintf (LOG_VERBOSE,
1192                          _("%s (%s) - Connection closed at byte %ld. "),
1193                          tms, tmrate, hstat.len);
1194               printwhat (count, opt.ntry);
1195               continue;
1196             }
1197           else if (!opt.kill_longer) /* meaning we got more than expected */
1198             {
1199               logprintf (LOG_VERBOSE,
1200                          _("%s (%s) - `%s' saved [%ld/%ld])\n\n"),
1201                          tms, tmrate, locf, hstat.len, hstat.contlen);
1202               logprintf (LOG_NONVERBOSE,
1203                          "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n",
1204                          tms, u->url, hstat.len, hstat.contlen, locf, count);
1205               ++opt.numurls;
1206               opt.downloaded += hstat.len;
1207               downloaded_file(ADD_FILE, locf);
1208               return RETROK;
1209             }
1210           else                  /* the same, but not accepted */
1211             {
1212               logprintf (LOG_VERBOSE,
1213                          _("%s (%s) - Connection closed at byte %ld/%ld. "),
1214                          tms, tmrate, hstat.len, hstat.contlen);
1215               printwhat (count, opt.ntry);
1216               continue;
1217             }
1218         }
1219       else                      /* now hstat.res can only be -1 */
1220         {
1221           if (hstat.contlen == -1)
1222             {
1223               logprintf (LOG_VERBOSE,
1224                          _("%s (%s) - Read error at byte %ld (%s)."),
1225                          tms, tmrate, hstat.len, strerror (errno));
1226               printwhat (count, opt.ntry);
1227               continue;
1228             }
1229           else                  /* hstat.res == -1 and contlen is given */
1230             {
1231               logprintf (LOG_VERBOSE,
1232                          _("%s (%s) - Read error at byte %ld/%ld (%s). "),
1233                          tms, tmrate, hstat.len, hstat.contlen,
1234                          strerror (errno));
1235               printwhat (count, opt.ntry);
1236               continue;
1237             }
1238         }
1239       /* not reached */
1240       break;
1241     }
1242   while (!opt.ntry || (count < opt.ntry));
1243   return TRYLIMEXC;
1244 }
1245 \f
1246 /* Converts struct tm to time_t, assuming the data in tm is UTC rather
1247    than local timezone (mktime assumes the latter).
1248
1249    Contributed by Roger Beeman <beeman@cisco.com>, with the help of
1250    Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO.  */
1251 static time_t
1252 mktime_from_utc (struct tm *t)
1253 {
1254   time_t tl, tb;
1255
1256   tl = mktime (t);
1257   if (tl == -1)
1258     return -1;
1259   tb = mktime (gmtime (&tl));
1260   return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl)));
1261 }
1262
1263 /* Check whether the result of strptime() indicates success.
1264    strptime() returns the pointer to how far it got to in the string.
1265    The processing has been successful if the string is at `GMT' or
1266    `+X', or at the end of the string.
1267
1268    In extended regexp parlance, the function returns 1 if P matches
1269    "^ *(GMT|[+-][0-9]|$)", 0 otherwise.  P being NULL (a valid result of
1270    strptime()) is considered a failure and 0 is returned.  */
1271 static int
1272 check_end (char *p)
1273 {
1274   if (!p)
1275     return 0;
1276   while (ISSPACE (*p))
1277     ++p;
1278   if (!*p
1279       || (p[0] == 'G' && p[1] == 'M' && p[2] == 'T')
1280       || ((p[0] == '+' || p[1] == '-') && ISDIGIT (p[1])))
1281     return 1;
1282   else
1283     return 0;
1284 }
1285
1286 /* Convert TIME_STRING time to time_t.  TIME_STRING can be in any of
1287    the three formats RFC2068 allows the HTTP servers to emit --
1288    RFC1123-date, RFC850-date or asctime-date.  Timezones are ignored,
1289    and should be GMT.
1290
1291    We use strptime() to recognize various dates, which makes it a
1292    little bit slacker than the RFC1123/RFC850/asctime (e.g. it always
1293    allows shortened dates and months, one-digit days, etc.).  It also
1294    allows more than one space anywhere where the specs require one SP.
1295    The routine should probably be even more forgiving (as recommended
1296    by RFC2068), but I do not have the time to write one.
1297
1298    Return the computed time_t representation, or -1 if all the
1299    schemes fail.
1300
1301    Needless to say, what we *really* need here is something like
1302    Marcus Hennecke's atotm(), which is forgiving, fast, to-the-point,
1303    and does not use strptime().  atotm() is to be found in the sources
1304    of `phttpd', a little-known HTTP server written by Peter Erikson.  */
1305 static time_t
1306 http_atotm (char *time_string)
1307 {
1308   struct tm t;
1309
1310   /* Roger Beeman says: "This function dynamically allocates struct tm
1311      t, but does no initialization.  The only field that actually
1312      needs initialization is tm_isdst, since the others will be set by
1313      strptime.  Since strptime does not set tm_isdst, it will return
1314      the data structure with whatever data was in tm_isdst to begin
1315      with.  For those of us in timezones where DST can occur, there
1316      can be a one hour shift depending on the previous contents of the
1317      data area where the data structure is allocated."  */
1318   t.tm_isdst = -1;
1319
1320   /* Note that under foreign locales Solaris strptime() fails to
1321      recognize English dates, which renders this function useless.  I
1322      assume that other non-GNU strptime's are plagued by the same
1323      disease.  We solve this by setting only LC_MESSAGES in
1324      i18n_initialize(), instead of LC_ALL.
1325
1326      Another solution could be to temporarily set locale to C, invoke
1327      strptime(), and restore it back.  This is slow and dirty,
1328      however, and locale support other than LC_MESSAGES can mess other
1329      things, so I rather chose to stick with just setting LC_MESSAGES.
1330
1331      Also note that none of this is necessary under GNU strptime(),
1332      because it recognizes both international and local dates.  */
1333
1334   /* NOTE: We don't use `%n' for white space, as OSF's strptime uses
1335      it to eat all white space up to (and including) a newline, and
1336      the function fails if there is no newline (!).
1337
1338      Let's hope all strptime() implementations use ` ' to skip *all*
1339      whitespace instead of just one (it works that way on all the
1340      systems I've tested it on).  */
1341
1342   /* RFC1123: Thu, 29 Jan 1998 22:12:57 */
1343   if (check_end (strptime (time_string, "%a, %d %b %Y %T", &t)))
1344     return mktime_from_utc (&t);
1345   /* RFC850:  Thu, 29-Jan-98 22:12:57 */
1346   if (check_end (strptime (time_string, "%a, %d-%b-%y %T", &t)))
1347     return mktime_from_utc (&t);
1348   /* asctime: Thu Jan 29 22:12:57 1998 */
1349   if (check_end (strptime (time_string, "%a %b %d %T %Y", &t)))
1350     return mktime_from_utc (&t);
1351   /* Failure.  */
1352   return -1;
1353 }
1354 \f
1355 /* Authorization support: We support two authorization schemes:
1356
1357    * `Basic' scheme, consisting of base64-ing USER:PASSWORD string;
1358
1359    * `Digest' scheme, added by Junio Hamano <junio@twinsun.com>,
1360    consisting of answering to the server's challenge with the proper
1361    MD5 digests.  */
1362
1363 /* How many bytes it will take to store LEN bytes in base64.  */
1364 #define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
1365
1366 /* Encode the string S of length LENGTH to base64 format and place it
1367    to STORE.  STORE will be 0-terminated, and must point to a writable
1368    buffer of at least 1+BASE64_LENGTH(length) bytes.  */
1369 static void
1370 base64_encode (const char *s, char *store, int length)
1371 {
1372   /* Conversion table.  */
1373   static char tbl[64] = {
1374     'A','B','C','D','E','F','G','H',
1375     'I','J','K','L','M','N','O','P',
1376     'Q','R','S','T','U','V','W','X',
1377     'Y','Z','a','b','c','d','e','f',
1378     'g','h','i','j','k','l','m','n',
1379     'o','p','q','r','s','t','u','v',
1380     'w','x','y','z','0','1','2','3',
1381     '4','5','6','7','8','9','+','/'
1382   };
1383   int i;
1384   unsigned char *p = (unsigned char *)store;
1385
1386   /* Transform the 3x8 bits to 4x6 bits, as required by base64.  */
1387   for (i = 0; i < length; i += 3)
1388     {
1389       *p++ = tbl[s[0] >> 2];
1390       *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
1391       *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
1392       *p++ = tbl[s[2] & 0x3f];
1393       s += 3;
1394     }
1395   /* Pad the result if necessary...  */
1396   if (i == length + 1)
1397     *(p - 1) = '=';
1398   else if (i == length + 2)
1399     *(p - 1) = *(p - 2) = '=';
1400   /* ...and zero-terminate it.  */
1401   *p = '\0';
1402 }
1403
1404 /* Create the authentication header contents for the `Basic' scheme.
1405    This is done by encoding the string `USER:PASS' in base64 and
1406    prepending `HEADER: Basic ' to it.  */
1407 static char *
1408 basic_authentication_encode (const char *user, const char *passwd,
1409                              const char *header)
1410 {
1411   char *t1, *t2, *res;
1412   int len1 = strlen (user) + 1 + strlen (passwd);
1413   int len2 = BASE64_LENGTH (len1);
1414
1415   t1 = (char *)alloca (len1 + 1);
1416   sprintf (t1, "%s:%s", user, passwd);
1417   t2 = (char *)alloca (1 + len2);
1418   base64_encode (t1, t2, len1);
1419   res = (char *)malloc (len2 + 11 + strlen (header));
1420   sprintf (res, "%s: Basic %s\r\n", header, t2);
1421
1422   return res;
1423 }
1424
1425 #ifdef USE_DIGEST
1426 /* Parse HTTP `WWW-Authenticate:' header.  AU points to the beginning
1427    of a field in such a header.  If the field is the one specified by
1428    ATTR_NAME ("realm", "opaque", and "nonce" are used by the current
1429    digest authorization code), extract its value in the (char*)
1430    variable pointed by RET.  Returns negative on a malformed header,
1431    or number of bytes that have been parsed by this call.  */
1432 static int
1433 extract_header_attr (const char *au, const char *attr_name, char **ret)
1434 {
1435   const char *cp, *ep;
1436
1437   ep = cp = au;
1438
1439   if (strncmp (cp, attr_name, strlen (attr_name)) == 0)
1440     {
1441       cp += strlen (attr_name);
1442       if (!*cp)
1443         return -1;
1444       cp += skip_lws (cp);
1445       if (*cp != '=')
1446         return -1;
1447       if (!*++cp)
1448         return -1;
1449       cp += skip_lws (cp);
1450       if (*cp != '\"')
1451         return -1;
1452       if (!*++cp)
1453         return -1;
1454       for (ep = cp; *ep && *ep != '\"'; ep++)
1455         ;
1456       if (!*ep)
1457         return -1;
1458       FREE_MAYBE (*ret);
1459       *ret = strdupdelim (cp, ep);
1460       return ep - au + 1;
1461     }
1462   else
1463     return 0;
1464 }
1465
1466 /* Response value needs to be in lowercase, so we cannot use HEXD2ASC
1467    from url.h.  See RFC 2069 2.1.2 for the syntax of response-digest.  */
1468 #define HEXD2asc(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'a'))
1469
1470 /* Dump the hexadecimal representation of HASH to BUF.  HASH should be
1471    an array of 16 bytes containing the hash keys, and BUF should be a
1472    buffer of 33 writable characters (32 for hex digits plus one for
1473    zero termination).  */
1474 static void
1475 dump_hash (unsigned char *buf, const unsigned char *hash)
1476 {
1477   int i;
1478
1479   for (i = 0; i < MD5_HASHLEN; i++, hash++)
1480     {
1481       *buf++ = HEXD2asc (*hash >> 4);
1482       *buf++ = HEXD2asc (*hash & 0xf);
1483     }
1484   *buf = '\0';
1485 }
1486
1487 /* Take the line apart to find the challenge, and compose a digest
1488    authorization header.  See RFC2069 section 2.1.2.  */
1489 char *
1490 digest_authentication_encode (const char *au, const char *user,
1491                               const char *passwd, const char *method,
1492                               const char *path)
1493 {
1494   static char *realm, *opaque, *nonce;
1495   static struct {
1496     const char *name;
1497     char **variable;
1498   } options[] = {
1499     { "realm", &realm },
1500     { "opaque", &opaque },
1501     { "nonce", &nonce }
1502   };
1503   char *res;
1504
1505   realm = opaque = nonce = NULL;
1506
1507   au += 6;                      /* skip over `Digest' */
1508   while (*au)
1509     {
1510       int i;
1511
1512       au += skip_lws (au);
1513       for (i = 0; i < ARRAY_SIZE (options); i++)
1514         {
1515           int skip = extract_header_attr (au, options[i].name,
1516                                           options[i].variable);
1517           if (skip < 0)
1518             {
1519               FREE_MAYBE (realm);
1520               FREE_MAYBE (opaque);
1521               FREE_MAYBE (nonce);
1522               return NULL;
1523             }
1524           else if (skip)
1525             {
1526               au += skip;
1527               break;
1528             }
1529         }
1530       if (i == ARRAY_SIZE (options))
1531         {
1532           while (*au && *au != '=')
1533             au++;
1534           if (*au && *++au)
1535             {
1536               au += skip_lws (au);
1537               if (*au == '\"')
1538                 {
1539                   au++;
1540                   while (*au && *au != '\"')
1541                     au++;
1542                   if (*au)
1543                     au++;
1544                 }
1545             }
1546         }
1547       while (*au && *au != ',')
1548         au++;
1549       if (*au)
1550         au++;
1551     }
1552   if (!realm || !nonce || !user || !passwd || !path || !method)
1553     {
1554       FREE_MAYBE (realm);
1555       FREE_MAYBE (opaque);
1556       FREE_MAYBE (nonce);
1557       return NULL;
1558     }
1559
1560   /* Calculate the digest value.  */
1561   {
1562     struct md5_ctx ctx;
1563     unsigned char hash[MD5_HASHLEN];
1564     unsigned char a1buf[MD5_HASHLEN * 2 + 1], a2buf[MD5_HASHLEN * 2 + 1];
1565     unsigned char response_digest[MD5_HASHLEN * 2 + 1];
1566
1567     /* A1BUF = H(user ":" realm ":" password) */
1568     md5_init_ctx (&ctx);
1569     md5_process_bytes (user, strlen (user), &ctx);
1570     md5_process_bytes (":", 1, &ctx);
1571     md5_process_bytes (realm, strlen (realm), &ctx);
1572     md5_process_bytes (":", 1, &ctx);
1573     md5_process_bytes (passwd, strlen (passwd), &ctx);
1574     md5_finish_ctx (&ctx, hash);
1575     dump_hash (a1buf, hash);
1576
1577     /* A2BUF = H(method ":" path) */
1578     md5_init_ctx (&ctx);
1579     md5_process_bytes (method, strlen (method), &ctx);
1580     md5_process_bytes (":", 1, &ctx);
1581     md5_process_bytes (path, strlen (path), &ctx);
1582     md5_finish_ctx (&ctx, hash);
1583     dump_hash (a2buf, hash);
1584
1585     /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) */
1586     md5_init_ctx (&ctx);
1587     md5_process_bytes (a1buf, MD5_HASHLEN * 2, &ctx);
1588     md5_process_bytes (":", 1, &ctx);
1589     md5_process_bytes (nonce, strlen (nonce), &ctx);
1590     md5_process_bytes (":", 1, &ctx);
1591     md5_process_bytes (a2buf, MD5_HASHLEN * 2, &ctx);
1592     md5_finish_ctx (&ctx, hash);
1593     dump_hash (response_digest, hash);
1594
1595     res = (char*) xmalloc (strlen (user)
1596                            + strlen (user)
1597                            + strlen (realm)
1598                            + strlen (nonce)
1599                            + strlen (path)
1600                            + 2 * MD5_HASHLEN /*strlen (response_digest)*/
1601                            + (opaque ? strlen (opaque) : 0)
1602                            + 128);
1603     sprintf (res, "Authorization: Digest \
1604 username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
1605              user, realm, nonce, path, response_digest);
1606     if (opaque)
1607       {
1608         char *p = res + strlen (res);
1609         strcat (p, ", opaque=\"");
1610         strcat (p, opaque);
1611         strcat (p, "\"");
1612       }
1613     strcat (res, "\r\n");
1614   }
1615   return res;
1616 }
1617 #endif /* USE_DIGEST */
1618
1619
1620 #define HACK_O_MATIC(line, string_constant)                             \
1621   (!strncasecmp (line, string_constant, sizeof (string_constant) - 1)   \
1622    && (ISSPACE (line[sizeof (string_constant) - 1])                     \
1623        || !line[sizeof (string_constant) - 1]))
1624
1625 static int
1626 known_authentication_scheme_p (const char *au)
1627 {
1628   return HACK_O_MATIC (au, "Basic") || HACK_O_MATIC (au, "Digest");
1629 }
1630
1631 #undef HACK_O_MATIC
1632
1633 /* Create the HTTP authorization request header.  When the
1634    `WWW-Authenticate' response header is seen, according to the
1635    authorization scheme specified in that header (`Basic' and `Digest'
1636    are supported by the current implementation), produce an
1637    appropriate HTTP authorization request header.  */
1638 static char *
1639 create_authorization_line (const char *au, const char *user,
1640                            const char *passwd, const char *method,
1641                            const char *path)
1642 {
1643   char *wwwauth = NULL;
1644
1645   if (!strncasecmp (au, "Basic", 5))
1646     wwwauth = basic_authentication_encode (user, passwd, "Authorization");
1647 #ifdef USE_DIGEST
1648   else if (!strncasecmp (au, "Digest", 6))
1649     wwwauth = digest_authentication_encode (au, user, passwd, method, path);
1650 #endif /* USE_DIGEST */
1651   return wwwauth;
1652 }