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