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