]> sjero.net Git - wget/blob - src/http.c
Fix problem when content-disposition is used with recursive downloading.
[wget] / src / http.c
1 /* HTTP support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3    2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #ifdef HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39 #include <assert.h>
40 #include <errno.h>
41 #include <time.h>
42 #include <locale.h>
43
44 #include "hash.h"
45 #include "http.h"
46 #include "utils.h"
47 #include "url.h"
48 #include "host.h"
49 #include "retr.h"
50 #include "connect.h"
51 #include "netrc.h"
52 #ifdef HAVE_SSL
53 # include "ssl.h"
54 #endif
55 #ifdef ENABLE_NTLM
56 # include "http-ntlm.h"
57 #endif
58 #include "cookies.h"
59 #include "md5.h"
60 #include "convert.h"
61 #include "spider.h"
62
63 #ifdef TESTING
64 #include "test.h"
65 #endif
66
67 #ifdef __VMS
68 # include "vms.h"
69 #endif /* def __VMS */
70
71 extern char *version_string;
72
73 /* Forward decls. */
74 struct http_stat;
75 static char *create_authorization_line (const char *, const char *,
76                                         const char *, const char *,
77                                         const char *, bool *);
78 static char *basic_authentication_encode (const char *, const char *);
79 static bool known_authentication_scheme_p (const char *, const char *);
80 static void ensure_extension (struct http_stat *, const char *, int *);
81 static void load_cookies (void);
82
83 #ifndef MIN
84 # define MIN(x, y) ((x) > (y) ? (y) : (x))
85 #endif
86
87 \f
88 static bool cookies_loaded_p;
89 static struct cookie_jar *wget_cookie_jar;
90
91 #define TEXTHTML_S "text/html"
92 #define TEXTXHTML_S "application/xhtml+xml"
93 #define TEXTCSS_S "text/css"
94
95 /* Some status code validation macros: */
96 #define H_10X(x)        (((x) >= 100) && ((x) < 200))
97 #define H_20X(x)        (((x) >= 200) && ((x) < 300))
98 #define H_PARTIAL(x)    ((x) == HTTP_STATUS_PARTIAL_CONTENTS)
99 #define H_REDIRECTED(x) ((x) == HTTP_STATUS_MOVED_PERMANENTLY          \
100                          || (x) == HTTP_STATUS_MOVED_TEMPORARILY       \
101                          || (x) == HTTP_STATUS_SEE_OTHER               \
102                          || (x) == HTTP_STATUS_TEMPORARY_REDIRECT)
103
104 /* HTTP/1.0 status codes from RFC1945, provided for reference.  */
105 /* Successful 2xx.  */
106 #define HTTP_STATUS_OK                    200
107 #define HTTP_STATUS_CREATED               201
108 #define HTTP_STATUS_ACCEPTED              202
109 #define HTTP_STATUS_NO_CONTENT            204
110 #define HTTP_STATUS_PARTIAL_CONTENTS      206
111
112 /* Redirection 3xx.  */
113 #define HTTP_STATUS_MULTIPLE_CHOICES      300
114 #define HTTP_STATUS_MOVED_PERMANENTLY     301
115 #define HTTP_STATUS_MOVED_TEMPORARILY     302
116 #define HTTP_STATUS_SEE_OTHER             303 /* from HTTP/1.1 */
117 #define HTTP_STATUS_NOT_MODIFIED          304
118 #define HTTP_STATUS_TEMPORARY_REDIRECT    307 /* from HTTP/1.1 */
119
120 /* Client error 4xx.  */
121 #define HTTP_STATUS_BAD_REQUEST           400
122 #define HTTP_STATUS_UNAUTHORIZED          401
123 #define HTTP_STATUS_FORBIDDEN             403
124 #define HTTP_STATUS_NOT_FOUND             404
125 #define HTTP_STATUS_RANGE_NOT_SATISFIABLE 416
126
127 /* Server errors 5xx.  */
128 #define HTTP_STATUS_INTERNAL              500
129 #define HTTP_STATUS_NOT_IMPLEMENTED       501
130 #define HTTP_STATUS_BAD_GATEWAY           502
131 #define HTTP_STATUS_UNAVAILABLE           503
132 \f
133 enum rp {
134   rel_none, rel_name, rel_value, rel_both
135 };
136
137 struct request {
138   const char *method;
139   char *arg;
140
141   struct request_header {
142     char *name, *value;
143     enum rp release_policy;
144   } *headers;
145   int hcount, hcapacity;
146 };
147
148 extern int numurls;
149
150 /* Create a new, empty request.  At least request_set_method must be
151    called before the request can be used.  */
152
153 static struct request *
154 request_new (void)
155 {
156   struct request *req = xnew0 (struct request);
157   req->hcapacity = 8;
158   req->headers = xnew_array (struct request_header, req->hcapacity);
159   return req;
160 }
161
162 /* Set the request's method and its arguments.  METH should be a
163    literal string (or it should outlive the request) because it will
164    not be freed.  ARG will be freed by request_free.  */
165
166 static void
167 request_set_method (struct request *req, const char *meth, char *arg)
168 {
169   req->method = meth;
170   req->arg = arg;
171 }
172
173 /* Return the method string passed with the last call to
174    request_set_method.  */
175
176 static const char *
177 request_method (const struct request *req)
178 {
179   return req->method;
180 }
181
182 /* Free one header according to the release policy specified with
183    request_set_header.  */
184
185 static void
186 release_header (struct request_header *hdr)
187 {
188   switch (hdr->release_policy)
189     {
190     case rel_none:
191       break;
192     case rel_name:
193       xfree (hdr->name);
194       break;
195     case rel_value:
196       xfree (hdr->value);
197       break;
198     case rel_both:
199       xfree (hdr->name);
200       xfree (hdr->value);
201       break;
202     }
203 }
204
205 /* Set the request named NAME to VALUE.  Specifically, this means that
206    a "NAME: VALUE\r\n" header line will be used in the request.  If a
207    header with the same name previously existed in the request, its
208    value will be replaced by this one.  A NULL value means do nothing.
209
210    RELEASE_POLICY determines whether NAME and VALUE should be released
211    (freed) with request_free.  Allowed values are:
212
213     - rel_none     - don't free NAME or VALUE
214     - rel_name     - free NAME when done
215     - rel_value    - free VALUE when done
216     - rel_both     - free both NAME and VALUE when done
217
218    Setting release policy is useful when arguments come from different
219    sources.  For example:
220
221      // Don't free literal strings!
222      request_set_header (req, "Pragma", "no-cache", rel_none);
223
224      // Don't free a global variable, we'll need it later.
225      request_set_header (req, "Referer", opt.referer, rel_none);
226
227      // Value freshly allocated, free it when done.
228      request_set_header (req, "Range",
229                          aprintf ("bytes=%s-", number_to_static_string (hs->restval)),
230                          rel_value);
231    */
232
233 static void
234 request_set_header (struct request *req, char *name, char *value,
235                     enum rp release_policy)
236 {
237   struct request_header *hdr;
238   int i;
239
240   if (!value)
241     {
242       /* A NULL value is a no-op; if freeing the name is requested,
243          free it now to avoid leaks.  */
244       if (release_policy == rel_name || release_policy == rel_both)
245         xfree (name);
246       return;
247     }
248
249   for (i = 0; i < req->hcount; i++)
250     {
251       hdr = &req->headers[i];
252       if (0 == strcasecmp (name, hdr->name))
253         {
254           /* Replace existing header. */
255           release_header (hdr);
256           hdr->name = name;
257           hdr->value = value;
258           hdr->release_policy = release_policy;
259           return;
260         }
261     }
262
263   /* Install new header. */
264
265   if (req->hcount >= req->hcapacity)
266     {
267       req->hcapacity <<= 1;
268       req->headers = xrealloc (req->headers, req->hcapacity * sizeof (*hdr));
269     }
270   hdr = &req->headers[req->hcount++];
271   hdr->name = name;
272   hdr->value = value;
273   hdr->release_policy = release_policy;
274 }
275
276 /* Like request_set_header, but sets the whole header line, as
277    provided by the user using the `--header' option.  For example,
278    request_set_user_header (req, "Foo: bar") works just like
279    request_set_header (req, "Foo", "bar").  */
280
281 static void
282 request_set_user_header (struct request *req, const char *header)
283 {
284   char *name;
285   const char *p = strchr (header, ':');
286   if (!p)
287     return;
288   BOUNDED_TO_ALLOCA (header, p, name);
289   ++p;
290   while (c_isspace (*p))
291     ++p;
292   request_set_header (req, xstrdup (name), (char *) p, rel_name);
293 }
294
295 /* Remove the header with specified name from REQ.  Returns true if
296    the header was actually removed, false otherwise.  */
297
298 static bool
299 request_remove_header (struct request *req, char *name)
300 {
301   int i;
302   for (i = 0; i < req->hcount; i++)
303     {
304       struct request_header *hdr = &req->headers[i];
305       if (0 == strcasecmp (name, hdr->name))
306         {
307           release_header (hdr);
308           /* Move the remaining headers by one. */
309           if (i < req->hcount - 1)
310             memmove (hdr, hdr + 1, (req->hcount - i - 1) * sizeof (*hdr));
311           --req->hcount;
312           return true;
313         }
314     }
315   return false;
316 }
317
318 #define APPEND(p, str) do {                     \
319   int A_len = strlen (str);                     \
320   memcpy (p, str, A_len);                       \
321   p += A_len;                                   \
322 } while (0)
323
324 /* Construct the request and write it to FD using fd_write.  */
325
326 static int
327 request_send (const struct request *req, int fd)
328 {
329   char *request_string, *p;
330   int i, size, write_error;
331
332   /* Count the request size. */
333   size = 0;
334
335   /* METHOD " " ARG " " "HTTP/1.0" "\r\n" */
336   size += strlen (req->method) + 1 + strlen (req->arg) + 1 + 8 + 2;
337
338   for (i = 0; i < req->hcount; i++)
339     {
340       struct request_header *hdr = &req->headers[i];
341       /* NAME ": " VALUE "\r\n" */
342       size += strlen (hdr->name) + 2 + strlen (hdr->value) + 2;
343     }
344
345   /* "\r\n\0" */
346   size += 3;
347
348   p = request_string = alloca_array (char, size);
349
350   /* Generate the request. */
351
352   APPEND (p, req->method); *p++ = ' ';
353   APPEND (p, req->arg);    *p++ = ' ';
354   memcpy (p, "HTTP/1.1\r\n", 10); p += 10;
355
356   for (i = 0; i < req->hcount; i++)
357     {
358       struct request_header *hdr = &req->headers[i];
359       APPEND (p, hdr->name);
360       *p++ = ':', *p++ = ' ';
361       APPEND (p, hdr->value);
362       *p++ = '\r', *p++ = '\n';
363     }
364
365   *p++ = '\r', *p++ = '\n', *p++ = '\0';
366   assert (p - request_string == size);
367
368 #undef APPEND
369
370   DEBUGP (("\n---request begin---\n%s---request end---\n", request_string));
371
372   /* Send the request to the server. */
373
374   write_error = fd_write (fd, request_string, size - 1, -1);
375   if (write_error < 0)
376     logprintf (LOG_VERBOSE, _("Failed writing HTTP request: %s.\n"),
377                fd_errstr (fd));
378   return write_error;
379 }
380
381 /* Release the resources used by REQ. */
382
383 static void
384 request_free (struct request *req)
385 {
386   int i;
387   xfree_null (req->arg);
388   for (i = 0; i < req->hcount; i++)
389     release_header (&req->headers[i]);
390   xfree_null (req->headers);
391   xfree (req);
392 }
393
394 static struct hash_table *basic_authed_hosts;
395
396 /* Find out if this host has issued a Basic challenge yet; if so, give
397  * it the username, password. A temporary measure until we can get
398  * proper authentication in place. */
399
400 static bool
401 maybe_send_basic_creds (const char *hostname, const char *user,
402                         const char *passwd, struct request *req)
403 {
404   bool do_challenge = false;
405
406   if (opt.auth_without_challenge)
407     {
408       DEBUGP (("Auth-without-challenge set, sending Basic credentials.\n"));
409       do_challenge = true;
410     }
411   else if (basic_authed_hosts
412       && hash_table_contains(basic_authed_hosts, hostname))
413     {
414       DEBUGP (("Found %s in basic_authed_hosts.\n", quote (hostname)));
415       do_challenge = true;
416     }
417   else
418     {
419       DEBUGP (("Host %s has not issued a general basic challenge.\n",
420               quote (hostname)));
421     }
422   if (do_challenge)
423     {
424       request_set_header (req, "Authorization",
425                           basic_authentication_encode (user, passwd),
426                           rel_value);
427     }
428   return do_challenge;
429 }
430
431 static void
432 register_basic_auth_host (const char *hostname)
433 {
434   if (!basic_authed_hosts)
435     {
436       basic_authed_hosts = make_nocase_string_hash_table (1);
437     }
438   if (!hash_table_contains(basic_authed_hosts, hostname))
439     {
440       hash_table_put (basic_authed_hosts, xstrdup(hostname), NULL);
441       DEBUGP (("Inserted %s into basic_authed_hosts\n", quote (hostname)));
442     }
443 }
444
445
446 /* Send the contents of FILE_NAME to SOCK.  Make sure that exactly
447    PROMISED_SIZE bytes are sent over the wire -- if the file is
448    longer, read only that much; if the file is shorter, report an error.  */
449
450 static int
451 post_file (int sock, const char *file_name, wgint promised_size)
452 {
453   static char chunk[8192];
454   wgint written = 0;
455   int write_error;
456   FILE *fp;
457
458   DEBUGP (("[writing POST file %s ... ", file_name));
459
460   fp = fopen (file_name, "rb");
461   if (!fp)
462     return -1;
463   while (!feof (fp) && written < promised_size)
464     {
465       int towrite;
466       int length = fread (chunk, 1, sizeof (chunk), fp);
467       if (length == 0)
468         break;
469       towrite = MIN (promised_size - written, length);
470       write_error = fd_write (sock, chunk, towrite, -1);
471       if (write_error < 0)
472         {
473           fclose (fp);
474           return -1;
475         }
476       written += towrite;
477     }
478   fclose (fp);
479
480   /* If we've written less than was promised, report a (probably
481      nonsensical) error rather than break the promise.  */
482   if (written < promised_size)
483     {
484       errno = EINVAL;
485       return -1;
486     }
487
488   assert (written == promised_size);
489   DEBUGP (("done]\n"));
490   return 0;
491 }
492 \f
493 /* Determine whether [START, PEEKED + PEEKLEN) contains an empty line.
494    If so, return the pointer to the position after the line, otherwise
495    return NULL.  This is used as callback to fd_read_hunk.  The data
496    between START and PEEKED has been read and cannot be "unread"; the
497    data after PEEKED has only been peeked.  */
498
499 static const char *
500 response_head_terminator (const char *start, const char *peeked, int peeklen)
501 {
502   const char *p, *end;
503
504   /* If at first peek, verify whether HUNK starts with "HTTP".  If
505      not, this is a HTTP/0.9 request and we must bail out without
506      reading anything.  */
507   if (start == peeked && 0 != memcmp (start, "HTTP", MIN (peeklen, 4)))
508     return start;
509
510   /* Look for "\n[\r]\n", and return the following position if found.
511      Start two chars before the current to cover the possibility that
512      part of the terminator (e.g. "\n\r") arrived in the previous
513      batch.  */
514   p = peeked - start < 2 ? start : peeked - 2;
515   end = peeked + peeklen;
516
517   /* Check for \n\r\n or \n\n anywhere in [p, end-2). */
518   for (; p < end - 2; p++)
519     if (*p == '\n')
520       {
521         if (p[1] == '\r' && p[2] == '\n')
522           return p + 3;
523         else if (p[1] == '\n')
524           return p + 2;
525       }
526   /* p==end-2: check for \n\n directly preceding END. */
527   if (p[0] == '\n' && p[1] == '\n')
528     return p + 2;
529
530   return NULL;
531 }
532
533 /* The maximum size of a single HTTP response we care to read.  Rather
534    than being a limit of the reader implementation, this limit
535    prevents Wget from slurping all available memory upon encountering
536    malicious or buggy server output, thus protecting the user.  Define
537    it to 0 to remove the limit.  */
538
539 #define HTTP_RESPONSE_MAX_SIZE 65536
540
541 /* Read the HTTP request head from FD and return it.  The error
542    conditions are the same as with fd_read_hunk.
543
544    To support HTTP/0.9 responses, this function tries to make sure
545    that the data begins with "HTTP".  If this is not the case, no data
546    is read and an empty request is returned, so that the remaining
547    data can be treated as body.  */
548
549 static char *
550 read_http_response_head (int fd)
551 {
552   return fd_read_hunk (fd, response_head_terminator, 512,
553                        HTTP_RESPONSE_MAX_SIZE);
554 }
555
556 struct response {
557   /* The response data. */
558   const char *data;
559
560   /* The array of pointers that indicate where each header starts.
561      For example, given this HTTP response:
562
563        HTTP/1.0 200 Ok
564        Description: some
565         text
566        Etag: x
567
568      The headers are located like this:
569
570      "HTTP/1.0 200 Ok\r\nDescription: some\r\n text\r\nEtag: x\r\n\r\n"
571      ^                   ^                             ^          ^
572      headers[0]          headers[1]                    headers[2] headers[3]
573
574      I.e. headers[0] points to the beginning of the request,
575      headers[1] points to the end of the first header and the
576      beginning of the second one, etc.  */
577
578   const char **headers;
579 };
580
581 /* Create a new response object from the text of the HTTP response,
582    available in HEAD.  That text is automatically split into
583    constituent header lines for fast retrieval using
584    resp_header_*.  */
585
586 static struct response *
587 resp_new (const char *head)
588 {
589   const char *hdr;
590   int count, size;
591
592   struct response *resp = xnew0 (struct response);
593   resp->data = head;
594
595   if (*head == '\0')
596     {
597       /* Empty head means that we're dealing with a headerless
598          (HTTP/0.9) response.  In that case, don't set HEADERS at
599          all.  */
600       return resp;
601     }
602
603   /* Split HEAD into header lines, so that resp_header_* functions
604      don't need to do this over and over again.  */
605
606   size = count = 0;
607   hdr = head;
608   while (1)
609     {
610       DO_REALLOC (resp->headers, size, count + 1, const char *);
611       resp->headers[count++] = hdr;
612
613       /* Break upon encountering an empty line. */
614       if (!hdr[0] || (hdr[0] == '\r' && hdr[1] == '\n') || hdr[0] == '\n')
615         break;
616
617       /* Find the end of HDR, including continuations. */
618       do
619         {
620           const char *end = strchr (hdr, '\n');
621           if (end)
622             hdr = end + 1;
623           else
624             hdr += strlen (hdr);
625         }
626       while (*hdr == ' ' || *hdr == '\t');
627     }
628   DO_REALLOC (resp->headers, size, count + 1, const char *);
629   resp->headers[count] = NULL;
630
631   return resp;
632 }
633
634 /* Locate the header named NAME in the request data, starting with
635    position START.  This allows the code to loop through the request
636    data, filtering for all requests of a given name.  Returns the
637    found position, or -1 for failure.  The code that uses this
638    function typically looks like this:
639
640      for (pos = 0; (pos = resp_header_locate (...)) != -1; pos++)
641        ... do something with header ...
642
643    If you only care about one header, use resp_header_get instead of
644    this function.  */
645
646 static int
647 resp_header_locate (const struct response *resp, const char *name, int start,
648                     const char **begptr, const char **endptr)
649 {
650   int i;
651   const char **headers = resp->headers;
652   int name_len;
653
654   if (!headers || !headers[1])
655     return -1;
656
657   name_len = strlen (name);
658   if (start > 0)
659     i = start;
660   else
661     i = 1;
662
663   for (; headers[i + 1]; i++)
664     {
665       const char *b = headers[i];
666       const char *e = headers[i + 1];
667       if (e - b > name_len
668           && b[name_len] == ':'
669           && 0 == strncasecmp (b, name, name_len))
670         {
671           b += name_len + 1;
672           while (b < e && c_isspace (*b))
673             ++b;
674           while (b < e && c_isspace (e[-1]))
675             --e;
676           *begptr = b;
677           *endptr = e;
678           return i;
679         }
680     }
681   return -1;
682 }
683
684 /* Find and retrieve the header named NAME in the request data.  If
685    found, set *BEGPTR to its starting, and *ENDPTR to its ending
686    position, and return true.  Otherwise return false.
687
688    This function is used as a building block for resp_header_copy
689    and resp_header_strdup.  */
690
691 static bool
692 resp_header_get (const struct response *resp, const char *name,
693                  const char **begptr, const char **endptr)
694 {
695   int pos = resp_header_locate (resp, name, 0, begptr, endptr);
696   return pos != -1;
697 }
698
699 /* Copy the response header named NAME to buffer BUF, no longer than
700    BUFSIZE (BUFSIZE includes the terminating 0).  If the header
701    exists, true is returned, false otherwise.  If there should be no
702    limit on the size of the header, use resp_header_strdup instead.
703
704    If BUFSIZE is 0, no data is copied, but the boolean indication of
705    whether the header is present is still returned.  */
706
707 static bool
708 resp_header_copy (const struct response *resp, const char *name,
709                   char *buf, int bufsize)
710 {
711   const char *b, *e;
712   if (!resp_header_get (resp, name, &b, &e))
713     return false;
714   if (bufsize)
715     {
716       int len = MIN (e - b, bufsize - 1);
717       memcpy (buf, b, len);
718       buf[len] = '\0';
719     }
720   return true;
721 }
722
723 /* Return the value of header named NAME in RESP, allocated with
724    malloc.  If such a header does not exist in RESP, return NULL.  */
725
726 static char *
727 resp_header_strdup (const struct response *resp, const char *name)
728 {
729   const char *b, *e;
730   if (!resp_header_get (resp, name, &b, &e))
731     return NULL;
732   return strdupdelim (b, e);
733 }
734
735 /* Parse the HTTP status line, which is of format:
736
737    HTTP-Version SP Status-Code SP Reason-Phrase
738
739    The function returns the status-code, or -1 if the status line
740    appears malformed.  The pointer to "reason-phrase" message is
741    returned in *MESSAGE.  */
742
743 static int
744 resp_status (const struct response *resp, char **message)
745 {
746   int status;
747   const char *p, *end;
748
749   if (!resp->headers)
750     {
751       /* For a HTTP/0.9 response, assume status 200. */
752       if (message)
753         *message = xstrdup (_("No headers, assuming HTTP/0.9"));
754       return 200;
755     }
756
757   p = resp->headers[0];
758   end = resp->headers[1];
759
760   if (!end)
761     return -1;
762
763   /* "HTTP" */
764   if (end - p < 4 || 0 != strncmp (p, "HTTP", 4))
765     return -1;
766   p += 4;
767
768   /* Match the HTTP version.  This is optional because Gnutella
769      servers have been reported to not specify HTTP version.  */
770   if (p < end && *p == '/')
771     {
772       ++p;
773       while (p < end && c_isdigit (*p))
774         ++p;
775       if (p < end && *p == '.')
776         ++p;
777       while (p < end && c_isdigit (*p))
778         ++p;
779     }
780
781   while (p < end && c_isspace (*p))
782     ++p;
783   if (end - p < 3 || !c_isdigit (p[0]) || !c_isdigit (p[1]) || !c_isdigit (p[2]))
784     return -1;
785
786   status = 100 * (p[0] - '0') + 10 * (p[1] - '0') + (p[2] - '0');
787   p += 3;
788
789   if (message)
790     {
791       while (p < end && c_isspace (*p))
792         ++p;
793       while (p < end && c_isspace (end[-1]))
794         --end;
795       *message = strdupdelim (p, end);
796     }
797
798   return status;
799 }
800
801 /* Release the resources used by RESP.  */
802
803 static void
804 resp_free (struct response *resp)
805 {
806   xfree_null (resp->headers);
807   xfree (resp);
808 }
809
810 /* Print a single line of response, the characters [b, e).  We tried
811    getting away with
812       logprintf (LOG_VERBOSE, "%s%.*s\n", prefix, (int) (e - b), b);
813    but that failed to escape the non-printable characters and, in fact,
814    caused crashes in UTF-8 locales.  */
815
816 static void
817 print_response_line(const char *prefix, const char *b, const char *e)
818 {
819   char *copy;
820   BOUNDED_TO_ALLOCA(b, e, copy);
821   logprintf (LOG_ALWAYS, "%s%s\n", prefix,
822              quotearg_style (escape_quoting_style, copy));
823 }
824
825 /* Print the server response, line by line, omitting the trailing CRLF
826    from individual header lines, and prefixed with PREFIX.  */
827
828 static void
829 print_server_response (const struct response *resp, const char *prefix)
830 {
831   int i;
832   if (!resp->headers)
833     return;
834   for (i = 0; resp->headers[i + 1]; i++)
835     {
836       const char *b = resp->headers[i];
837       const char *e = resp->headers[i + 1];
838       /* Skip CRLF */
839       if (b < e && e[-1] == '\n')
840         --e;
841       if (b < e && e[-1] == '\r')
842         --e;
843       print_response_line(prefix, b, e);
844     }
845 }
846
847 /* Parse the `Content-Range' header and extract the information it
848    contains.  Returns true if successful, false otherwise.  */
849 static bool
850 parse_content_range (const char *hdr, wgint *first_byte_ptr,
851                      wgint *last_byte_ptr, wgint *entity_length_ptr)
852 {
853   wgint num;
854
855   /* Ancient versions of Netscape proxy server, presumably predating
856      rfc2068, sent out `Content-Range' without the "bytes"
857      specifier.  */
858   if (0 == strncasecmp (hdr, "bytes", 5))
859     {
860       hdr += 5;
861       /* "JavaWebServer/1.1.1" sends "bytes: x-y/z", contrary to the
862          HTTP spec. */
863       if (*hdr == ':')
864         ++hdr;
865       while (c_isspace (*hdr))
866         ++hdr;
867       if (!*hdr)
868         return false;
869     }
870   if (!c_isdigit (*hdr))
871     return false;
872   for (num = 0; c_isdigit (*hdr); hdr++)
873     num = 10 * num + (*hdr - '0');
874   if (*hdr != '-' || !c_isdigit (*(hdr + 1)))
875     return false;
876   *first_byte_ptr = num;
877   ++hdr;
878   for (num = 0; c_isdigit (*hdr); hdr++)
879     num = 10 * num + (*hdr - '0');
880   if (*hdr != '/' || !c_isdigit (*(hdr + 1)))
881     return false;
882   *last_byte_ptr = num;
883   ++hdr;
884   if (*hdr == '*')
885     num = -1;
886   else
887     for (num = 0; c_isdigit (*hdr); hdr++)
888       num = 10 * num + (*hdr - '0');
889   *entity_length_ptr = num;
890   return true;
891 }
892
893 /* Read the body of the request, but don't store it anywhere and don't
894    display a progress gauge.  This is useful for reading the bodies of
895    administrative responses to which we will soon issue another
896    request.  The response is not useful to the user, but reading it
897    allows us to continue using the same connection to the server.
898
899    If reading fails, false is returned, true otherwise.  In debug
900    mode, the body is displayed for debugging purposes.  */
901
902 static bool
903 skip_short_body (int fd, wgint contlen, bool chunked)
904 {
905   enum {
906     SKIP_SIZE = 512,                /* size of the download buffer */
907     SKIP_THRESHOLD = 4096        /* the largest size we read */
908   };
909   wgint remaining_chunk_size = 0;
910   char dlbuf[SKIP_SIZE + 1];
911   dlbuf[SKIP_SIZE] = '\0';        /* so DEBUGP can safely print it */
912
913   assert (contlen != -1 || contlen);
914
915   /* If the body is too large, it makes more sense to simply close the
916      connection than to try to read the body.  */
917   if (contlen > SKIP_THRESHOLD)
918     return false;
919
920   while (contlen > 0 || chunked)
921     {
922       int ret;
923       if (chunked)
924         {
925           if (remaining_chunk_size == 0)
926             {
927               char *line = fd_read_line (fd);
928               char *endl;
929               if (line == NULL)
930                 {
931                   ret = -1;
932                   break;
933                 }
934
935               remaining_chunk_size = strtol (line, &endl, 16);
936               if (remaining_chunk_size == 0)
937                 {
938                   ret = 0;
939                   if (fd_read_line (fd) == NULL)
940                     ret = -1;
941                   break;
942                 }
943             }
944
945           contlen = MIN (remaining_chunk_size, SKIP_SIZE);
946         }
947
948       DEBUGP (("Skipping %s bytes of body: [", number_to_static_string (contlen)));
949
950       ret = fd_read (fd, dlbuf, MIN (contlen, SKIP_SIZE), -1);
951       if (ret <= 0)
952         {
953           /* Don't normally report the error since this is an
954              optimization that should be invisible to the user.  */
955           DEBUGP (("] aborting (%s).\n",
956                    ret < 0 ? fd_errstr (fd) : "EOF received"));
957           return false;
958         }
959       contlen -= ret;
960
961       if (chunked)
962         {
963           remaining_chunk_size -= ret;
964           if (remaining_chunk_size == 0)
965             if (fd_read_line (fd) == NULL)
966               return false;
967         }
968
969       /* Safe even if %.*s bogusly expects terminating \0 because
970          we've zero-terminated dlbuf above.  */
971       DEBUGP (("%.*s", ret, dlbuf));
972     }
973
974   DEBUGP (("] done.\n"));
975   return true;
976 }
977
978 #define NOT_RFC2231 0
979 #define RFC2231_NOENCODING 1
980 #define RFC2231_ENCODING 2
981
982 /* extract_param extracts the parameter name into NAME.
983    However, if the parameter name is in RFC2231 format then
984    this function adjusts NAME by stripping of the trailing
985    characters that are not part of the name but are present to
986    indicate the presence of encoding information in the value
987    or a fragment of a long parameter value
988 */
989 static int
990 modify_param_name(param_token *name)
991 {
992   const char *delim1 = memchr (name->b, '*', name->e - name->b);
993   const char *delim2 = memrchr (name->b, '*', name->e - name->b);
994
995   int result;
996
997   if(delim1 == NULL)
998     {
999       result = NOT_RFC2231;
1000     }
1001   else if(delim1 == delim2)
1002     {
1003       if ((name->e - 1) == delim1)
1004         {
1005           result = RFC2231_ENCODING;
1006         }
1007       else
1008         {
1009           result = RFC2231_NOENCODING;
1010         }
1011       name->e = delim1;
1012     }
1013   else
1014     {
1015       name->e = delim1;
1016       result = RFC2231_ENCODING;
1017     }
1018   return result;
1019 }
1020
1021 /* extract_param extract the paramater value into VALUE.
1022    Like modify_param_name this function modifies VALUE by
1023    stripping off the encoding information from the actual value
1024 */
1025 static void
1026 modify_param_value (param_token *value, int encoding_type )
1027 {
1028   if (RFC2231_ENCODING == encoding_type)
1029     {
1030       const char *delim = memrchr (value->b, '\'', value->e - value->b);
1031       if ( delim != NULL )
1032         {
1033           value->b = (delim+1);
1034         }
1035     }
1036 }
1037
1038 /* Extract a parameter from the string (typically an HTTP header) at
1039    **SOURCE and advance SOURCE to the next parameter.  Return false
1040    when there are no more parameters to extract.  The name of the
1041    parameter is returned in NAME, and the value in VALUE.  If the
1042    parameter has no value, the token's value is zeroed out.
1043
1044    For example, if *SOURCE points to the string "attachment;
1045    filename=\"foo bar\"", the first call to this function will return
1046    the token named "attachment" and no value, and the second call will
1047    return the token named "filename" and value "foo bar".  The third
1048    call will return false, indicating no more valid tokens.  */
1049
1050 bool
1051 extract_param (const char **source, param_token *name, param_token *value,
1052                char separator)
1053 {
1054   const char *p = *source;
1055
1056   while (c_isspace (*p)) ++p;
1057   if (!*p)
1058     {
1059       *source = p;
1060       return false;             /* no error; nothing more to extract */
1061     }
1062
1063   /* Extract name. */
1064   name->b = p;
1065   while (*p && !c_isspace (*p) && *p != '=' && *p != separator) ++p;
1066   name->e = p;
1067   if (name->b == name->e)
1068     return false;               /* empty name: error */
1069   while (c_isspace (*p)) ++p;
1070   if (*p == separator || !*p)           /* no value */
1071     {
1072       xzero (*value);
1073       if (*p == separator) ++p;
1074       *source = p;
1075       return true;
1076     }
1077   if (*p != '=')
1078     return false;               /* error */
1079
1080   /* *p is '=', extract value */
1081   ++p;
1082   while (c_isspace (*p)) ++p;
1083   if (*p == '"')                /* quoted */
1084     {
1085       value->b = ++p;
1086       while (*p && *p != '"') ++p;
1087       if (!*p)
1088         return false;
1089       value->e = p++;
1090       /* Currently at closing quote; find the end of param. */
1091       while (c_isspace (*p)) ++p;
1092       while (*p && *p != separator) ++p;
1093       if (*p == separator)
1094         ++p;
1095       else if (*p)
1096         /* garbage after closed quote, e.g. foo="bar"baz */
1097         return false;
1098     }
1099   else                          /* unquoted */
1100     {
1101       value->b = p;
1102       while (*p && *p != separator) ++p;
1103       value->e = p;
1104       while (value->e != value->b && c_isspace (value->e[-1]))
1105         --value->e;
1106       if (*p == separator) ++p;
1107     }
1108   *source = p;
1109
1110   int param_type = modify_param_name(name);
1111   if (NOT_RFC2231 != param_type)
1112     {
1113       modify_param_value(value, param_type);
1114     }
1115   return true;
1116 }
1117
1118 #undef NOT_RFC2231
1119 #undef RFC2231_NOENCODING
1120 #undef RFC2231_ENCODING
1121
1122 /* Appends the string represented by VALUE to FILENAME */
1123
1124 static void
1125 append_value_to_filename (char **filename, param_token const * const value)
1126 {
1127   int original_length = strlen(*filename);
1128   int new_length = strlen(*filename) + (value->e - value->b);
1129   *filename = xrealloc (*filename, new_length+1);
1130   memcpy (*filename + original_length, value->b, (value->e - value->b)); 
1131   (*filename)[new_length] = '\0';
1132 }
1133
1134 #undef MAX
1135 #define MAX(p, q) ((p) > (q) ? (p) : (q))
1136
1137 /* Parse the contents of the `Content-Disposition' header, extracting
1138    the information useful to Wget.  Content-Disposition is a header
1139    borrowed from MIME; when used in HTTP, it typically serves for
1140    specifying the desired file name of the resource.  For example:
1141
1142        Content-Disposition: attachment; filename="flora.jpg"
1143
1144    Wget will skip the tokens it doesn't care about, such as
1145    "attachment" in the previous example; it will also skip other
1146    unrecognized params.  If the header is syntactically correct and
1147    contains a file name, a copy of the file name is stored in
1148    *filename and true is returned.  Otherwise, the function returns
1149    false.
1150
1151    The file name is stripped of directory components and must not be
1152    empty.
1153
1154    Historically, this function returned filename prefixed with opt.dir_prefix,
1155    now that logic is handled by the caller, new code should pay attention,
1156    changed by crq, Sep 2010.
1157
1158 */
1159 static bool
1160 parse_content_disposition (const char *hdr, char **filename)
1161 {
1162   param_token name, value;
1163   *filename = NULL;
1164   while (extract_param (&hdr, &name, &value, ';'))
1165     {
1166       int isFilename = BOUNDED_EQUAL_NO_CASE ( name.b, name.e, "filename" );
1167       if ( isFilename && value.b != NULL)
1168         {
1169           /* Make the file name begin at the last slash or backslash. */
1170           const char *last_slash = memrchr (value.b, '/', value.e - value.b);
1171           const char *last_bs = memrchr (value.b, '\\', value.e - value.b);
1172           if (last_slash && last_bs)
1173             value.b = 1 + MAX (last_slash, last_bs);
1174           else if (last_slash || last_bs)
1175             value.b = 1 + (last_slash ? last_slash : last_bs);
1176           if (value.b == value.e)
1177             continue;
1178
1179           if (*filename)
1180             append_value_to_filename (filename, &value);
1181           else
1182             *filename = strdupdelim (value.b, value.e);
1183         }
1184     }
1185
1186   if (*filename)
1187     return true;
1188   else
1189     return false;
1190 }
1191
1192 \f
1193 /* Persistent connections.  Currently, we cache the most recently used
1194    connection as persistent, provided that the HTTP server agrees to
1195    make it such.  The persistence data is stored in the variables
1196    below.  Ideally, it should be possible to cache an arbitrary fixed
1197    number of these connections.  */
1198
1199 /* Whether a persistent connection is active. */
1200 static bool pconn_active;
1201
1202 static struct {
1203   /* The socket of the connection.  */
1204   int socket;
1205
1206   /* Host and port of the currently active persistent connection. */
1207   char *host;
1208   int port;
1209
1210   /* Whether a ssl handshake has occoured on this connection.  */
1211   bool ssl;
1212
1213   /* Whether the connection was authorized.  This is only done by
1214      NTLM, which authorizes *connections* rather than individual
1215      requests.  (That practice is peculiar for HTTP, but it is a
1216      useful optimization.)  */
1217   bool authorized;
1218
1219 #ifdef ENABLE_NTLM
1220   /* NTLM data of the current connection.  */
1221   struct ntlmdata ntlm;
1222 #endif
1223 } pconn;
1224
1225 /* Mark the persistent connection as invalid and free the resources it
1226    uses.  This is used by the CLOSE_* macros after they forcefully
1227    close a registered persistent connection.  */
1228
1229 static void
1230 invalidate_persistent (void)
1231 {
1232   DEBUGP (("Disabling further reuse of socket %d.\n", pconn.socket));
1233   pconn_active = false;
1234   fd_close (pconn.socket);
1235   xfree (pconn.host);
1236   xzero (pconn);
1237 }
1238
1239 /* Register FD, which should be a TCP/IP connection to HOST:PORT, as
1240    persistent.  This will enable someone to use the same connection
1241    later.  In the context of HTTP, this must be called only AFTER the
1242    response has been received and the server has promised that the
1243    connection will remain alive.
1244
1245    If a previous connection was persistent, it is closed. */
1246
1247 static void
1248 register_persistent (const char *host, int port, int fd, bool ssl)
1249 {
1250   if (pconn_active)
1251     {
1252       if (pconn.socket == fd)
1253         {
1254           /* The connection FD is already registered. */
1255           return;
1256         }
1257       else
1258         {
1259           /* The old persistent connection is still active; close it
1260              first.  This situation arises whenever a persistent
1261              connection exists, but we then connect to a different
1262              host, and try to register a persistent connection to that
1263              one.  */
1264           invalidate_persistent ();
1265         }
1266     }
1267
1268   pconn_active = true;
1269   pconn.socket = fd;
1270   pconn.host = xstrdup (host);
1271   pconn.port = port;
1272   pconn.ssl = ssl;
1273   pconn.authorized = false;
1274
1275   DEBUGP (("Registered socket %d for persistent reuse.\n", fd));
1276 }
1277
1278 /* Return true if a persistent connection is available for connecting
1279    to HOST:PORT.  */
1280
1281 static bool
1282 persistent_available_p (const char *host, int port, bool ssl,
1283                         bool *host_lookup_failed)
1284 {
1285   /* First, check whether a persistent connection is active at all.  */
1286   if (!pconn_active)
1287     return false;
1288
1289   /* If we want SSL and the last connection wasn't or vice versa,
1290      don't use it.  Checking for host and port is not enough because
1291      HTTP and HTTPS can apparently coexist on the same port.  */
1292   if (ssl != pconn.ssl)
1293     return false;
1294
1295   /* If we're not connecting to the same port, we're not interested. */
1296   if (port != pconn.port)
1297     return false;
1298
1299   /* If the host is the same, we're in business.  If not, there is
1300      still hope -- read below.  */
1301   if (0 != strcasecmp (host, pconn.host))
1302     {
1303       /* Check if pconn.socket is talking to HOST under another name.
1304          This happens often when both sites are virtual hosts
1305          distinguished only by name and served by the same network
1306          interface, and hence the same web server (possibly set up by
1307          the ISP and serving many different web sites).  This
1308          admittedly unconventional optimization does not contradict
1309          HTTP and works well with popular server software.  */
1310
1311       bool found;
1312       ip_address ip;
1313       struct address_list *al;
1314
1315       if (ssl)
1316         /* Don't try to talk to two different SSL sites over the same
1317            secure connection!  (Besides, it's not clear that
1318            name-based virtual hosting is even possible with SSL.)  */
1319         return false;
1320
1321       /* If pconn.socket's peer is one of the IP addresses HOST
1322          resolves to, pconn.socket is for all intents and purposes
1323          already talking to HOST.  */
1324
1325       if (!socket_ip_address (pconn.socket, &ip, ENDPOINT_PEER))
1326         {
1327           /* Can't get the peer's address -- something must be very
1328              wrong with the connection.  */
1329           invalidate_persistent ();
1330           return false;
1331         }
1332       al = lookup_host (host, 0);
1333       if (!al)
1334         {
1335           *host_lookup_failed = true;
1336           return false;
1337         }
1338
1339       found = address_list_contains (al, &ip);
1340       address_list_release (al);
1341
1342       if (!found)
1343         return false;
1344
1345       /* The persistent connection's peer address was found among the
1346          addresses HOST resolved to; therefore, pconn.sock is in fact
1347          already talking to HOST -- no need to reconnect.  */
1348     }
1349
1350   /* Finally, check whether the connection is still open.  This is
1351      important because most servers implement liberal (short) timeout
1352      on persistent connections.  Wget can of course always reconnect
1353      if the connection doesn't work out, but it's nicer to know in
1354      advance.  This test is a logical followup of the first test, but
1355      is "expensive" and therefore placed at the end of the list.
1356
1357      (Current implementation of test_socket_open has a nice side
1358      effect that it treats sockets with pending data as "closed".
1359      This is exactly what we want: if a broken server sends message
1360      body in response to HEAD, or if it sends more than conent-length
1361      data, we won't reuse the corrupted connection.)  */
1362
1363   if (!test_socket_open (pconn.socket))
1364     {
1365       /* Oops, the socket is no longer open.  Now that we know that,
1366          let's invalidate the persistent connection before returning
1367          0.  */
1368       invalidate_persistent ();
1369       return false;
1370     }
1371
1372   return true;
1373 }
1374
1375 /* The idea behind these two CLOSE macros is to distinguish between
1376    two cases: one when the job we've been doing is finished, and we
1377    want to close the connection and leave, and two when something is
1378    seriously wrong and we're closing the connection as part of
1379    cleanup.
1380
1381    In case of keep_alive, CLOSE_FINISH should leave the connection
1382    open, while CLOSE_INVALIDATE should still close it.
1383
1384    Note that the semantics of the flag `keep_alive' is "this
1385    connection *will* be reused (the server has promised not to close
1386    the connection once we're done)", while the semantics of
1387    `pc_active_p && (fd) == pc_last_fd' is "we're *now* using an
1388    active, registered connection".  */
1389
1390 #define CLOSE_FINISH(fd) do {                   \
1391   if (!keep_alive)                              \
1392     {                                           \
1393       if (pconn_active && (fd) == pconn.socket) \
1394         invalidate_persistent ();               \
1395       else                                      \
1396         {                                       \
1397           fd_close (fd);                        \
1398           fd = -1;                              \
1399         }                                       \
1400     }                                           \
1401 } while (0)
1402
1403 #define CLOSE_INVALIDATE(fd) do {               \
1404   if (pconn_active && (fd) == pconn.socket)     \
1405     invalidate_persistent ();                   \
1406   else                                          \
1407     fd_close (fd);                              \
1408   fd = -1;                                      \
1409 } while (0)
1410 \f
1411 struct http_stat
1412 {
1413   wgint len;                    /* received length */
1414   wgint contlen;                /* expected length */
1415   wgint restval;                /* the restart value */
1416   int res;                      /* the result of last read */
1417   char *rderrmsg;               /* error message from read error */
1418   char *newloc;                 /* new location (redirection) */
1419   char *remote_time;            /* remote time-stamp string */
1420   char *error;                  /* textual HTTP error */
1421   int statcode;                 /* status code */
1422   char *message;                /* status message */
1423   wgint rd_size;                /* amount of data read from socket */
1424   double dltime;                /* time it took to download the data */
1425   const char *referer;          /* value of the referer header. */
1426   char *local_file;             /* local file name. */
1427   bool existence_checked;       /* true if we already checked for a file's
1428                                    existence after having begun to download
1429                                    (needed in gethttp for when connection is
1430                                    interrupted/restarted. */
1431   bool timestamp_checked;       /* true if pre-download time-stamping checks
1432                                  * have already been performed */
1433   char *orig_file_name;         /* name of file to compare for time-stamping
1434                                  * (might be != local_file if -K is set) */
1435   wgint orig_file_size;         /* size of file to compare for time-stamping */
1436   time_t orig_file_tstamp;      /* time-stamp of file to compare for
1437                                  * time-stamping */
1438 };
1439
1440 static void
1441 free_hstat (struct http_stat *hs)
1442 {
1443   xfree_null (hs->newloc);
1444   xfree_null (hs->remote_time);
1445   xfree_null (hs->error);
1446   xfree_null (hs->rderrmsg);
1447   xfree_null (hs->local_file);
1448   xfree_null (hs->orig_file_name);
1449   xfree_null (hs->message);
1450
1451   /* Guard against being called twice. */
1452   hs->newloc = NULL;
1453   hs->remote_time = NULL;
1454   hs->error = NULL;
1455 }
1456
1457 #define BEGINS_WITH(line, string_constant)                               \
1458   (!strncasecmp (line, string_constant, sizeof (string_constant) - 1)    \
1459    && (c_isspace (line[sizeof (string_constant) - 1])                      \
1460        || !line[sizeof (string_constant) - 1]))
1461
1462 #ifdef __VMS
1463 #define SET_USER_AGENT(req) do {                                         \
1464   if (!opt.useragent)                                                    \
1465     request_set_header (req, "User-Agent",                               \
1466                         aprintf ("Wget/%s (VMS %s %s)",                  \
1467                         version_string, vms_arch(), vms_vers()),         \
1468                         rel_value);                                      \
1469   else if (*opt.useragent)                                               \
1470     request_set_header (req, "User-Agent", opt.useragent, rel_none);     \
1471 } while (0)
1472 #else /* def __VMS */
1473 #define SET_USER_AGENT(req) do {                                         \
1474   if (!opt.useragent)                                                    \
1475     request_set_header (req, "User-Agent",                               \
1476                         aprintf ("Wget/%s (%s)",                         \
1477                         version_string, OS_TYPE),                        \
1478                         rel_value);                                      \
1479   else if (*opt.useragent)                                               \
1480     request_set_header (req, "User-Agent", opt.useragent, rel_none);     \
1481 } while (0)
1482 #endif /* def __VMS [else] */
1483
1484 /* The flags that allow clobbering the file (opening with "wb").
1485    Defined here to avoid repetition later.  #### This will require
1486    rework.  */
1487 #define ALLOW_CLOBBER (opt.noclobber || opt.always_rest || opt.timestamping \
1488                        || opt.dirstruct || opt.output_document)
1489
1490 /* Retrieve a document through HTTP protocol.  It recognizes status
1491    code, and correctly handles redirections.  It closes the network
1492    socket.  If it receives an error from the functions below it, it
1493    will print it if there is enough information to do so (almost
1494    always), returning the error to the caller (i.e. http_loop).
1495
1496    Various HTTP parameters are stored to hs.
1497
1498    If PROXY is non-NULL, the connection will be made to the proxy
1499    server, and u->url will be requested.  */
1500 static uerr_t
1501 gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy,
1502          struct iri *iri)
1503 {
1504   struct request *req;
1505
1506   char *type;
1507   char *user, *passwd;
1508   char *proxyauth;
1509   int statcode;
1510   int write_error;
1511   wgint contlen, contrange;
1512   struct url *conn;
1513   FILE *fp;
1514
1515   int sock = -1;
1516   int flags;
1517
1518   /* Set to 1 when the authorization has already been sent and should
1519      not be tried again. */
1520   bool auth_finished = false;
1521
1522   /* Set to 1 when just globally-set Basic authorization has been sent;
1523    * should prevent further Basic negotiations, but not other
1524    * mechanisms. */
1525   bool basic_auth_finished = false;
1526
1527   /* Whether NTLM authentication is used for this request. */
1528   bool ntlm_seen = false;
1529
1530   /* Whether our connection to the remote host is through SSL.  */
1531   bool using_ssl = false;
1532
1533   /* Whether a HEAD request will be issued (as opposed to GET or
1534      POST). */
1535   bool head_only = !!(*dt & HEAD_ONLY);
1536
1537   char *head;
1538   struct response *resp;
1539   char hdrval[256];
1540   char *message;
1541
1542   /* Whether this connection will be kept alive after the HTTP request
1543      is done. */
1544   bool keep_alive;
1545
1546   /* Is the server using the chunked transfer encoding?  */
1547   bool chunked_transfer_encoding = false;
1548
1549   /* Whether keep-alive should be inhibited.  */
1550   bool inhibit_keep_alive =
1551     !opt.http_keep_alive || opt.ignore_length;
1552
1553   /* Headers sent when using POST. */
1554   wgint post_data_size = 0;
1555
1556   bool host_lookup_failed = false;
1557
1558 #ifdef HAVE_SSL
1559   if (u->scheme == SCHEME_HTTPS)
1560     {
1561       /* Initialize the SSL context.  After this has once been done,
1562          it becomes a no-op.  */
1563       if (!ssl_init ())
1564         {
1565           scheme_disable (SCHEME_HTTPS);
1566           logprintf (LOG_NOTQUIET,
1567                      _("Disabling SSL due to encountered errors.\n"));
1568           return SSLINITFAILED;
1569         }
1570     }
1571 #endif /* HAVE_SSL */
1572
1573   /* Initialize certain elements of struct http_stat.  */
1574   hs->len = 0;
1575   hs->contlen = -1;
1576   hs->res = -1;
1577   hs->rderrmsg = NULL;
1578   hs->newloc = NULL;
1579   hs->remote_time = NULL;
1580   hs->error = NULL;
1581   hs->message = NULL;
1582
1583   conn = u;
1584
1585   /* Prepare the request to send. */
1586
1587   req = request_new ();
1588   {
1589     char *meth_arg;
1590     const char *meth = "GET";
1591     if (head_only)
1592       meth = "HEAD";
1593     else if (opt.post_file_name || opt.post_data)
1594       meth = "POST";
1595     /* Use the full path, i.e. one that includes the leading slash and
1596        the query string.  E.g. if u->path is "foo/bar" and u->query is
1597        "param=value", full_path will be "/foo/bar?param=value".  */
1598     if (proxy
1599 #ifdef HAVE_SSL
1600         /* When using SSL over proxy, CONNECT establishes a direct
1601            connection to the HTTPS server.  Therefore use the same
1602            argument as when talking to the server directly. */
1603         && u->scheme != SCHEME_HTTPS
1604 #endif
1605         )
1606       meth_arg = xstrdup (u->url);
1607     else
1608       meth_arg = url_full_path (u);
1609     request_set_method (req, meth, meth_arg);
1610   }
1611
1612   request_set_header (req, "Referer", (char *) hs->referer, rel_none);
1613   if (*dt & SEND_NOCACHE)
1614     request_set_header (req, "Pragma", "no-cache", rel_none);
1615   if (hs->restval && !opt.timestamping)
1616     request_set_header (req, "Range",
1617                         aprintf ("bytes=%s-",
1618                                  number_to_static_string (hs->restval)),
1619                         rel_value);
1620   SET_USER_AGENT (req);
1621   request_set_header (req, "Accept", "*/*", rel_none);
1622
1623   /* Find the username and password for authentication. */
1624   user = u->user;
1625   passwd = u->passwd;
1626   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 0);
1627   user = user ? user : (opt.http_user ? opt.http_user : opt.user);
1628   passwd = passwd ? passwd : (opt.http_passwd ? opt.http_passwd : opt.passwd);
1629
1630   /* We only do "site-wide" authentication with "global" user/password
1631    * values unless --auth-no-challange has been requested; URL user/password
1632    * info overrides. */
1633   if (user && passwd && (!u->user || opt.auth_without_challenge))
1634     {
1635       /* If this is a host for which we've already received a Basic
1636        * challenge, we'll go ahead and send Basic authentication creds. */
1637       basic_auth_finished = maybe_send_basic_creds(u->host, user, passwd, req);
1638     }
1639
1640   /* Generate the Host header, HOST:PORT.  Take into account that:
1641
1642      - Broken server-side software often doesn't recognize the PORT
1643        argument, so we must generate "Host: www.server.com" instead of
1644        "Host: www.server.com:80" (and likewise for https port).
1645
1646      - IPv6 addresses contain ":", so "Host: 3ffe:8100:200:2::2:1234"
1647        becomes ambiguous and needs to be rewritten as "Host:
1648        [3ffe:8100:200:2::2]:1234".  */
1649   {
1650     /* Formats arranged for hfmt[add_port][add_squares].  */
1651     static const char *hfmt[][2] = {
1652       { "%s", "[%s]" }, { "%s:%d", "[%s]:%d" }
1653     };
1654     int add_port = u->port != scheme_default_port (u->scheme);
1655     int add_squares = strchr (u->host, ':') != NULL;
1656     request_set_header (req, "Host",
1657                         aprintf (hfmt[add_port][add_squares], u->host, u->port),
1658                         rel_value);
1659   }
1660
1661   if (inhibit_keep_alive)
1662     request_set_header (req, "Connection", "Close", rel_none);
1663   else
1664     {
1665       if (proxy == NULL)
1666         request_set_header (req, "Connection", "Keep-Alive", rel_none);
1667       else
1668         {
1669           request_set_header (req, "Connection", "Close", rel_none);
1670           request_set_header (req, "Proxy-Connection", "Keep-Alive", rel_none);
1671         }
1672     }
1673
1674   if (opt.post_data || opt.post_file_name)
1675     {
1676       request_set_header (req, "Content-Type",
1677                           "application/x-www-form-urlencoded", rel_none);
1678       if (opt.post_data)
1679         post_data_size = strlen (opt.post_data);
1680       else
1681         {
1682           post_data_size = file_size (opt.post_file_name);
1683           if (post_data_size == -1)
1684             {
1685               logprintf (LOG_NOTQUIET, _("POST data file %s missing: %s\n"),
1686                          quote (opt.post_file_name), strerror (errno));
1687               post_data_size = 0;
1688             }
1689         }
1690       request_set_header (req, "Content-Length",
1691                           xstrdup (number_to_static_string (post_data_size)),
1692                           rel_value);
1693     }
1694
1695  retry_with_auth:
1696   /* We need to come back here when the initial attempt to retrieve
1697      without authorization header fails.  (Expected to happen at least
1698      for the Digest authorization scheme.)  */
1699
1700   if (opt.cookies)
1701     request_set_header (req, "Cookie",
1702                         cookie_header (wget_cookie_jar,
1703                                        u->host, u->port, u->path,
1704 #ifdef HAVE_SSL
1705                                        u->scheme == SCHEME_HTTPS
1706 #else
1707                                        0
1708 #endif
1709                                        ),
1710                         rel_value);
1711
1712   /* Add the user headers. */
1713   if (opt.user_headers)
1714     {
1715       int i;
1716       for (i = 0; opt.user_headers[i]; i++)
1717         request_set_user_header (req, opt.user_headers[i]);
1718     }
1719
1720   proxyauth = NULL;
1721   if (proxy)
1722     {
1723       char *proxy_user, *proxy_passwd;
1724       /* For normal username and password, URL components override
1725          command-line/wgetrc parameters.  With proxy
1726          authentication, it's the reverse, because proxy URLs are
1727          normally the "permanent" ones, so command-line args
1728          should take precedence.  */
1729       if (opt.proxy_user && opt.proxy_passwd)
1730         {
1731           proxy_user = opt.proxy_user;
1732           proxy_passwd = opt.proxy_passwd;
1733         }
1734       else
1735         {
1736           proxy_user = proxy->user;
1737           proxy_passwd = proxy->passwd;
1738         }
1739       /* #### This does not appear right.  Can't the proxy request,
1740          say, `Digest' authentication?  */
1741       if (proxy_user && proxy_passwd)
1742         proxyauth = basic_authentication_encode (proxy_user, proxy_passwd);
1743
1744       /* If we're using a proxy, we will be connecting to the proxy
1745          server.  */
1746       conn = proxy;
1747
1748       /* Proxy authorization over SSL is handled below. */
1749 #ifdef HAVE_SSL
1750       if (u->scheme != SCHEME_HTTPS)
1751 #endif
1752         request_set_header (req, "Proxy-Authorization", proxyauth, rel_value);
1753     }
1754
1755   keep_alive = true;
1756
1757   /* Establish the connection.  */
1758
1759   if (inhibit_keep_alive)
1760     keep_alive = false;
1761   else
1762     {
1763       /* Look for a persistent connection to target host, unless a
1764          proxy is used.  The exception is when SSL is in use, in which
1765          case the proxy is nothing but a passthrough to the target
1766          host, registered as a connection to the latter.  */
1767       struct url *relevant = conn;
1768 #ifdef HAVE_SSL
1769       if (u->scheme == SCHEME_HTTPS)
1770         relevant = u;
1771 #endif
1772
1773       if (persistent_available_p (relevant->host, relevant->port,
1774 #ifdef HAVE_SSL
1775                                   relevant->scheme == SCHEME_HTTPS,
1776 #else
1777                                   0,
1778 #endif
1779                                   &host_lookup_failed))
1780         {
1781           sock = pconn.socket;
1782           using_ssl = pconn.ssl;
1783           logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"),
1784                      quotearg_style (escape_quoting_style, pconn.host),
1785                      pconn.port);
1786           DEBUGP (("Reusing fd %d.\n", sock));
1787           if (pconn.authorized)
1788             /* If the connection is already authorized, the "Basic"
1789                authorization added by code above is unnecessary and
1790                only hurts us.  */
1791             request_remove_header (req, "Authorization");
1792         }
1793       else if (host_lookup_failed)
1794         {
1795           request_free (req);
1796           logprintf(LOG_NOTQUIET,
1797                     _("%s: unable to resolve host address %s\n"),
1798                     exec_name, quote (relevant->host));
1799           return HOSTERR;
1800         }
1801     }
1802
1803   if (sock < 0)
1804     {
1805       sock = connect_to_host (conn->host, conn->port);
1806       if (sock == E_HOST)
1807         {
1808           request_free (req);
1809           return HOSTERR;
1810         }
1811       else if (sock < 0)
1812         {
1813           request_free (req);
1814           return (retryable_socket_connect_error (errno)
1815                   ? CONERROR : CONIMPOSSIBLE);
1816         }
1817
1818 #ifdef HAVE_SSL
1819       if (proxy && u->scheme == SCHEME_HTTPS)
1820         {
1821           /* When requesting SSL URLs through proxies, use the
1822              CONNECT method to request passthrough.  */
1823           struct request *connreq = request_new ();
1824           request_set_method (connreq, "CONNECT",
1825                               aprintf ("%s:%d", u->host, u->port));
1826           SET_USER_AGENT (connreq);
1827           if (proxyauth)
1828             {
1829               request_set_header (connreq, "Proxy-Authorization",
1830                                   proxyauth, rel_value);
1831               /* Now that PROXYAUTH is part of the CONNECT request,
1832                  zero it out so we don't send proxy authorization with
1833                  the regular request below.  */
1834               proxyauth = NULL;
1835             }
1836           /* Examples in rfc2817 use the Host header in CONNECT
1837              requests.  I don't see how that gains anything, given
1838              that the contents of Host would be exactly the same as
1839              the contents of CONNECT.  */
1840
1841           write_error = request_send (connreq, sock);
1842           request_free (connreq);
1843           if (write_error < 0)
1844             {
1845               CLOSE_INVALIDATE (sock);
1846               return WRITEFAILED;
1847             }
1848
1849           head = read_http_response_head (sock);
1850           if (!head)
1851             {
1852               logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"),
1853                          fd_errstr (sock));
1854               CLOSE_INVALIDATE (sock);
1855               return HERR;
1856             }
1857           message = NULL;
1858           if (!*head)
1859             {
1860               xfree (head);
1861               goto failed_tunnel;
1862             }
1863           DEBUGP (("proxy responded with: [%s]\n", head));
1864
1865           resp = resp_new (head);
1866           statcode = resp_status (resp, &message);
1867           if (statcode < 0)
1868             {
1869               char *tms = datetime_str (time (NULL));
1870               logprintf (LOG_VERBOSE, "%d\n", statcode);
1871               logprintf (LOG_NOTQUIET, _("%s ERROR %d: %s.\n"), tms, statcode,
1872                          quotearg_style (escape_quoting_style,
1873                                          _("Malformed status line")));
1874               xfree (head);
1875               return HERR;
1876             }
1877           hs->message = xstrdup (message);
1878           resp_free (resp);
1879           xfree (head);
1880           if (statcode != 200)
1881             {
1882             failed_tunnel:
1883               logprintf (LOG_NOTQUIET, _("Proxy tunneling failed: %s"),
1884                          message ? quotearg_style (escape_quoting_style, message) : "?");
1885               xfree_null (message);
1886               return CONSSLERR;
1887             }
1888           xfree_null (message);
1889
1890           /* SOCK is now *really* connected to u->host, so update CONN
1891              to reflect this.  That way register_persistent will
1892              register SOCK as being connected to u->host:u->port.  */
1893           conn = u;
1894         }
1895
1896       if (conn->scheme == SCHEME_HTTPS)
1897         {
1898           if (!ssl_connect_wget (sock))
1899             {
1900               fd_close (sock);
1901               return CONSSLERR;
1902             }
1903           else if (!ssl_check_certificate (sock, u->host))
1904             {
1905               fd_close (sock);
1906               return VERIFCERTERR;
1907             }
1908           using_ssl = true;
1909         }
1910 #endif /* HAVE_SSL */
1911     }
1912
1913   /* Send the request to server.  */
1914   write_error = request_send (req, sock);
1915
1916   if (write_error >= 0)
1917     {
1918       if (opt.post_data)
1919         {
1920           DEBUGP (("[POST data: %s]\n", opt.post_data));
1921           write_error = fd_write (sock, opt.post_data, post_data_size, -1);
1922         }
1923       else if (opt.post_file_name && post_data_size != 0)
1924         write_error = post_file (sock, opt.post_file_name, post_data_size);
1925     }
1926
1927   if (write_error < 0)
1928     {
1929       CLOSE_INVALIDATE (sock);
1930       request_free (req);
1931       return WRITEFAILED;
1932     }
1933   logprintf (LOG_VERBOSE, _("%s request sent, awaiting response... "),
1934              proxy ? "Proxy" : "HTTP");
1935   contlen = -1;
1936   contrange = 0;
1937   *dt &= ~RETROKF;
1938
1939 read_header:
1940   head = read_http_response_head (sock);
1941   if (!head)
1942     {
1943       if (errno == 0)
1944         {
1945           logputs (LOG_NOTQUIET, _("No data received.\n"));
1946           CLOSE_INVALIDATE (sock);
1947           request_free (req);
1948           return HEOF;
1949         }
1950       else
1951         {
1952           logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),
1953                      fd_errstr (sock));
1954           CLOSE_INVALIDATE (sock);
1955           request_free (req);
1956           return HERR;
1957         }
1958     }
1959   DEBUGP (("\n---response begin---\n%s---response end---\n", head));
1960
1961   resp = resp_new (head);
1962
1963   /* Check for status line.  */
1964   message = NULL;
1965   statcode = resp_status (resp, &message);
1966   if (statcode < 0)
1967     {
1968       char *tms = datetime_str (time (NULL));
1969       logprintf (LOG_VERBOSE, "%d\n", statcode);
1970       logprintf (LOG_NOTQUIET, _("%s ERROR %d: %s.\n"), tms, statcode,
1971                  quotearg_style (escape_quoting_style,
1972                                  _("Malformed status line")));
1973       CLOSE_INVALIDATE (sock);
1974       request_free (req);
1975       return HERR;
1976     }
1977
1978   if (H_10X (statcode))
1979     {
1980       DEBUGP (("Ignoring response\n"));
1981       goto read_header;
1982     }
1983
1984   hs->message = xstrdup (message);
1985   if (!opt.server_response)
1986     logprintf (LOG_VERBOSE, "%2d %s\n", statcode,
1987                message ? quotearg_style (escape_quoting_style, message) : "");
1988   else
1989     {
1990       logprintf (LOG_VERBOSE, "\n");
1991       print_server_response (resp, "  ");
1992     }
1993
1994   if (!opt.ignore_length
1995       && resp_header_copy (resp, "Content-Length", hdrval, sizeof (hdrval)))
1996     {
1997       wgint parsed;
1998       errno = 0;
1999       parsed = str_to_wgint (hdrval, NULL, 10);
2000       if (parsed == WGINT_MAX && errno == ERANGE)
2001         {
2002           /* Out of range.
2003              #### If Content-Length is out of range, it most likely
2004              means that the file is larger than 2G and that we're
2005              compiled without LFS.  In that case we should probably
2006              refuse to even attempt to download the file.  */
2007           contlen = -1;
2008         }
2009       else if (parsed < 0)
2010         {
2011           /* Negative Content-Length; nonsensical, so we can't
2012              assume any information about the content to receive. */
2013           contlen = -1;
2014         }
2015       else
2016         contlen = parsed;
2017     }
2018
2019   /* Check for keep-alive related responses. */
2020   if (!inhibit_keep_alive && contlen != -1)
2021     {
2022       if (resp_header_copy (resp, "Connection", hdrval, sizeof (hdrval)))
2023         {
2024           if (0 == strcasecmp (hdrval, "Close"))
2025             keep_alive = false;
2026         }
2027     }
2028
2029   resp_header_copy (resp, "Transfer-Encoding", hdrval, sizeof (hdrval));
2030   if (0 == strcasecmp (hdrval, "chunked"))
2031     chunked_transfer_encoding = true;
2032
2033   /* Handle (possibly multiple instances of) the Set-Cookie header. */
2034   if (opt.cookies)
2035     {
2036       int scpos;
2037       const char *scbeg, *scend;
2038       /* The jar should have been created by now. */
2039       assert (wget_cookie_jar != NULL);
2040       for (scpos = 0;
2041            (scpos = resp_header_locate (resp, "Set-Cookie", scpos,
2042                                         &scbeg, &scend)) != -1;
2043            ++scpos)
2044         {
2045           char *set_cookie; BOUNDED_TO_ALLOCA (scbeg, scend, set_cookie);
2046           cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port,
2047                                     u->path, set_cookie);
2048         }
2049     }
2050
2051   if (keep_alive)
2052     /* The server has promised that it will not close the connection
2053        when we're done.  This means that we can register it.  */
2054     register_persistent (conn->host, conn->port, sock, using_ssl);
2055
2056   if (statcode == HTTP_STATUS_UNAUTHORIZED)
2057     {
2058       /* Authorization is required.  */
2059       if (keep_alive && !head_only
2060           && skip_short_body (sock, contlen, chunked_transfer_encoding))
2061         CLOSE_FINISH (sock);
2062       else
2063         CLOSE_INVALIDATE (sock);
2064       pconn.authorized = false;
2065       if (!auth_finished && (user && passwd))
2066         {
2067           /* IIS sends multiple copies of WWW-Authenticate, one with
2068              the value "negotiate", and other(s) with data.  Loop over
2069              all the occurrences and pick the one we recognize.  */
2070           int wapos;
2071           const char *wabeg, *waend;
2072           char *www_authenticate = NULL;
2073           for (wapos = 0;
2074                (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos,
2075                                             &wabeg, &waend)) != -1;
2076                ++wapos)
2077             if (known_authentication_scheme_p (wabeg, waend))
2078               {
2079                 BOUNDED_TO_ALLOCA (wabeg, waend, www_authenticate);
2080                 break;
2081               }
2082
2083           if (!www_authenticate)
2084             {
2085               /* If the authentication header is missing or
2086                  unrecognized, there's no sense in retrying.  */
2087               logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));
2088             }
2089           else if (!basic_auth_finished
2090                    || !BEGINS_WITH (www_authenticate, "Basic"))
2091             {
2092               char *pth;
2093               pth = url_full_path (u);
2094               request_set_header (req, "Authorization",
2095                                   create_authorization_line (www_authenticate,
2096                                                              user, passwd,
2097                                                              request_method (req),
2098                                                              pth,
2099                                                              &auth_finished),
2100                                   rel_value);
2101               if (BEGINS_WITH (www_authenticate, "NTLM"))
2102                 ntlm_seen = true;
2103               else if (!u->user && BEGINS_WITH (www_authenticate, "Basic"))
2104                 {
2105                   /* Need to register this host as using basic auth,
2106                    * so we automatically send creds next time. */
2107                   register_basic_auth_host (u->host);
2108                 }
2109               xfree (pth);
2110               xfree_null (message);
2111               resp_free (resp);
2112               xfree (head);
2113               goto retry_with_auth;
2114             }
2115           else
2116             {
2117               /* We already did Basic auth, and it failed. Gotta
2118                * give up. */
2119             }
2120         }
2121       logputs (LOG_NOTQUIET, _("Authorization failed.\n"));
2122       request_free (req);
2123       xfree_null (message);
2124       resp_free (resp);
2125       xfree (head);
2126       return AUTHFAILED;
2127     }
2128   else /* statcode != HTTP_STATUS_UNAUTHORIZED */
2129     {
2130       /* Kludge: if NTLM is used, mark the TCP connection as authorized. */
2131       if (ntlm_seen)
2132         pconn.authorized = true;
2133     }
2134
2135   /* Determine the local filename if needed. Notice that if -O is used
2136    * hstat.local_file is set by http_loop to the argument of -O. */
2137   if (!hs->local_file)
2138     {
2139       char *local_file = NULL;
2140
2141       /* Honor Content-Disposition whether possible. */
2142       if (!opt.content_disposition
2143           || !resp_header_copy (resp, "Content-Disposition",
2144                                 hdrval, sizeof (hdrval))
2145           || !parse_content_disposition (hdrval, &local_file))
2146         {
2147           /* The Content-Disposition header is missing or broken.
2148            * Choose unique file name according to given URL. */
2149           hs->local_file = url_file_name (u, NULL);
2150         }
2151       else
2152         {
2153           DEBUGP (("Parsed filename from Content-Disposition: %s\n",
2154                   local_file));
2155           hs->local_file = url_file_name (u, local_file);
2156         }
2157     }
2158
2159   /* TODO: perform this check only once. */
2160   if (!hs->existence_checked && file_exists_p (hs->local_file))
2161     {
2162       if (opt.noclobber && !opt.output_document)
2163         {
2164           /* If opt.noclobber is turned on and file already exists, do not
2165              retrieve the file. But if the output_document was given, then this
2166              test was already done and the file didn't exist. Hence the !opt.output_document */
2167           logprintf (LOG_VERBOSE, _("\
2168 File %s already there; not retrieving.\n\n"), quote (hs->local_file));
2169           /* If the file is there, we suppose it's retrieved OK.  */
2170           *dt |= RETROKF;
2171
2172           /* #### Bogusness alert.  */
2173           /* If its suffix is "html" or "htm" or similar, assume text/html.  */
2174           if (has_html_suffix_p (hs->local_file))
2175             *dt |= TEXTHTML;
2176
2177           xfree (head);
2178           xfree_null (message);
2179           return RETRUNNEEDED;
2180         }
2181       else if (!ALLOW_CLOBBER)
2182         {
2183           char *unique = unique_name (hs->local_file, true);
2184           if (unique != hs->local_file)
2185             xfree (hs->local_file);
2186           hs->local_file = unique;
2187         }
2188     }
2189   hs->existence_checked = true;
2190
2191   /* Support timestamping */
2192   /* TODO: move this code out of gethttp. */
2193   if (opt.timestamping && !hs->timestamp_checked)
2194     {
2195       size_t filename_len = strlen (hs->local_file);
2196       char *filename_plus_orig_suffix = alloca (filename_len + sizeof (ORIG_SFX));
2197       bool local_dot_orig_file_exists = false;
2198       char *local_filename = NULL;
2199       struct_stat st;
2200
2201       if (opt.backup_converted)
2202         /* If -K is specified, we'll act on the assumption that it was specified
2203            last time these files were downloaded as well, and instead of just
2204            comparing local file X against server file X, we'll compare local
2205            file X.orig (if extant, else X) against server file X.  If -K
2206            _wasn't_ specified last time, or the server contains files called
2207            *.orig, -N will be back to not operating correctly with -k. */
2208         {
2209           /* Would a single s[n]printf() call be faster?  --dan
2210
2211              Definitely not.  sprintf() is horribly slow.  It's a
2212              different question whether the difference between the two
2213              affects a program.  Usually I'd say "no", but at one
2214              point I profiled Wget, and found that a measurable and
2215              non-negligible amount of time was lost calling sprintf()
2216              in url.c.  Replacing sprintf with inline calls to
2217              strcpy() and number_to_string() made a difference.
2218              --hniksic */
2219           memcpy (filename_plus_orig_suffix, hs->local_file, filename_len);
2220           memcpy (filename_plus_orig_suffix + filename_len,
2221                   ORIG_SFX, sizeof (ORIG_SFX));
2222
2223           /* Try to stat() the .orig file. */
2224           if (stat (filename_plus_orig_suffix, &st) == 0)
2225             {
2226               local_dot_orig_file_exists = true;
2227               local_filename = filename_plus_orig_suffix;
2228             }
2229         }
2230
2231       if (!local_dot_orig_file_exists)
2232         /* Couldn't stat() <file>.orig, so try to stat() <file>. */
2233         if (stat (hs->local_file, &st) == 0)
2234           local_filename = hs->local_file;
2235
2236       if (local_filename != NULL)
2237         /* There was a local file, so we'll check later to see if the version
2238            the server has is the same version we already have, allowing us to
2239            skip a download. */
2240         {
2241           hs->orig_file_name = xstrdup (local_filename);
2242           hs->orig_file_size = st.st_size;
2243           hs->orig_file_tstamp = st.st_mtime;
2244 #ifdef WINDOWS
2245           /* Modification time granularity is 2 seconds for Windows, so
2246              increase local time by 1 second for later comparison. */
2247           ++hs->orig_file_tstamp;
2248 #endif
2249         }
2250     }
2251
2252   request_free (req);
2253
2254   hs->statcode = statcode;
2255   if (statcode == -1)
2256     hs->error = xstrdup (_("Malformed status line"));
2257   else if (!*message)
2258     hs->error = xstrdup (_("(no description)"));
2259   else
2260     hs->error = xstrdup (message);
2261   xfree_null (message);
2262
2263   type = resp_header_strdup (resp, "Content-Type");
2264   if (type)
2265     {
2266       char *tmp = strchr (type, ';');
2267       if (tmp)
2268         {
2269           /* sXXXav: only needed if IRI support is enabled */
2270           char *tmp2 = tmp + 1;
2271
2272           while (tmp > type && c_isspace (tmp[-1]))
2273             --tmp;
2274           *tmp = '\0';
2275
2276           /* Try to get remote encoding if needed */
2277           if (opt.enable_iri && !opt.encoding_remote)
2278             {
2279               tmp = parse_charset (tmp2);
2280               if (tmp)
2281                 set_content_encoding (iri, tmp);
2282             }
2283         }
2284     }
2285   hs->newloc = resp_header_strdup (resp, "Location");
2286   hs->remote_time = resp_header_strdup (resp, "Last-Modified");
2287
2288   if (resp_header_copy (resp, "Content-Range", hdrval, sizeof (hdrval)))
2289     {
2290       wgint first_byte_pos, last_byte_pos, entity_length;
2291       if (parse_content_range (hdrval, &first_byte_pos, &last_byte_pos,
2292                                &entity_length))
2293         {
2294           contrange = first_byte_pos;
2295           contlen = last_byte_pos - first_byte_pos + 1;
2296         }
2297     }
2298   resp_free (resp);
2299
2300   /* 20x responses are counted among successful by default.  */
2301   if (H_20X (statcode))
2302     *dt |= RETROKF;
2303
2304   /* Return if redirected.  */
2305   if (H_REDIRECTED (statcode) || statcode == HTTP_STATUS_MULTIPLE_CHOICES)
2306     {
2307       /* RFC2068 says that in case of the 300 (multiple choices)
2308          response, the server can output a preferred URL through
2309          `Location' header; otherwise, the request should be treated
2310          like GET.  So, if the location is set, it will be a
2311          redirection; otherwise, just proceed normally.  */
2312       if (statcode == HTTP_STATUS_MULTIPLE_CHOICES && !hs->newloc)
2313         *dt |= RETROKF;
2314       else
2315         {
2316           logprintf (LOG_VERBOSE,
2317                      _("Location: %s%s\n"),
2318                      hs->newloc ? escnonprint_uri (hs->newloc) : _("unspecified"),
2319                      hs->newloc ? _(" [following]") : "");
2320           if (keep_alive && !head_only
2321               && skip_short_body (sock, contlen, chunked_transfer_encoding))
2322             CLOSE_FINISH (sock);
2323           else
2324             CLOSE_INVALIDATE (sock);
2325           xfree_null (type);
2326           xfree (head);
2327           return NEWLOCATION;
2328         }
2329     }
2330
2331   /* If content-type is not given, assume text/html.  This is because
2332      of the multitude of broken CGI's that "forget" to generate the
2333      content-type.  */
2334   if (!type ||
2335         0 == strncasecmp (type, TEXTHTML_S, strlen (TEXTHTML_S)) ||
2336         0 == strncasecmp (type, TEXTXHTML_S, strlen (TEXTXHTML_S)))
2337     *dt |= TEXTHTML;
2338   else
2339     *dt &= ~TEXTHTML;
2340
2341   if (type &&
2342       0 == strncasecmp (type, TEXTCSS_S, strlen (TEXTCSS_S)))
2343     *dt |= TEXTCSS;
2344   else
2345     *dt &= ~TEXTCSS;
2346
2347   if (opt.adjust_extension)
2348     {
2349       if (*dt & TEXTHTML)
2350         /* -E / --adjust-extension / adjust_extension = on was specified,
2351            and this is a text/html file.  If some case-insensitive
2352            variation on ".htm[l]" isn't already the file's suffix,
2353            tack on ".html". */
2354         {
2355           ensure_extension (hs, ".html", dt);
2356         }
2357       else if (*dt & TEXTCSS)
2358         {
2359           ensure_extension (hs, ".css", dt);
2360         }
2361     }
2362
2363   if (statcode == HTTP_STATUS_RANGE_NOT_SATISFIABLE
2364       || (!opt.timestamping && hs->restval > 0 && statcode == HTTP_STATUS_OK
2365           && contrange == 0 && contlen >= 0 && hs->restval >= contlen))
2366     {
2367       /* If `-c' is in use and the file has been fully downloaded (or
2368          the remote file has shrunk), Wget effectively requests bytes
2369          after the end of file and the server response with 416
2370          (or 200 with a <= Content-Length.  */
2371       logputs (LOG_VERBOSE, _("\
2372 \n    The file is already fully retrieved; nothing to do.\n\n"));
2373       /* In case the caller inspects. */
2374       hs->len = contlen;
2375       hs->res = 0;
2376       /* Mark as successfully retrieved. */
2377       *dt |= RETROKF;
2378       xfree_null (type);
2379       CLOSE_INVALIDATE (sock);        /* would be CLOSE_FINISH, but there
2380                                    might be more bytes in the body. */
2381       xfree (head);
2382       return RETRUNNEEDED;
2383     }
2384   if ((contrange != 0 && contrange != hs->restval)
2385       || (H_PARTIAL (statcode) && !contrange))
2386     {
2387       /* The Range request was somehow misunderstood by the server.
2388          Bail out.  */
2389       xfree_null (type);
2390       CLOSE_INVALIDATE (sock);
2391       xfree (head);
2392       return RANGEERR;
2393     }
2394   if (contlen == -1)
2395     hs->contlen = -1;
2396   else
2397     hs->contlen = contlen + contrange;
2398
2399   if (opt.verbose)
2400     {
2401       if (*dt & RETROKF)
2402         {
2403           /* No need to print this output if the body won't be
2404              downloaded at all, or if the original server response is
2405              printed.  */
2406           logputs (LOG_VERBOSE, _("Length: "));
2407           if (contlen != -1)
2408             {
2409               logputs (LOG_VERBOSE, number_to_static_string (contlen + contrange));
2410               if (contlen + contrange >= 1024)
2411                 logprintf (LOG_VERBOSE, " (%s)",
2412                            human_readable (contlen + contrange));
2413               if (contrange)
2414                 {
2415                   if (contlen >= 1024)
2416                     logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
2417                                number_to_static_string (contlen),
2418                                human_readable (contlen));
2419                   else
2420                     logprintf (LOG_VERBOSE, _(", %s remaining"),
2421                                number_to_static_string (contlen));
2422                 }
2423             }
2424           else
2425             logputs (LOG_VERBOSE,
2426                      opt.ignore_length ? _("ignored") : _("unspecified"));
2427           if (type)
2428             logprintf (LOG_VERBOSE, " [%s]\n", quotearg_style (escape_quoting_style, type));
2429           else
2430             logputs (LOG_VERBOSE, "\n");
2431         }
2432     }
2433   xfree_null (type);
2434   type = NULL;                        /* We don't need it any more.  */
2435
2436   /* Return if we have no intention of further downloading.  */
2437   if (!(*dt & RETROKF) || head_only)
2438     {
2439       /* In case the caller cares to look...  */
2440       hs->len = 0;
2441       hs->res = 0;
2442       xfree_null (type);
2443       if (head_only)
2444         /* Pre-1.10 Wget used CLOSE_INVALIDATE here.  Now we trust the
2445            servers not to send body in response to a HEAD request, and
2446            those that do will likely be caught by test_socket_open.
2447            If not, they can be worked around using
2448            `--no-http-keep-alive'.  */
2449         CLOSE_FINISH (sock);
2450       else if (keep_alive
2451                && skip_short_body (sock, contlen, chunked_transfer_encoding))
2452         /* Successfully skipped the body; also keep using the socket. */
2453         CLOSE_FINISH (sock);
2454       else
2455         CLOSE_INVALIDATE (sock);
2456       xfree (head);
2457       return RETRFINISHED;
2458     }
2459
2460 /* 2005-06-17 SMS.
2461    For VMS, define common fopen() optional arguments.
2462 */
2463 #ifdef __VMS
2464 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
2465 # define FOPEN_BIN_FLAG 3
2466 #else /* def __VMS */
2467 # define FOPEN_BIN_FLAG true
2468 #endif /* def __VMS [else] */
2469
2470   /* Open the local file.  */
2471   if (!output_stream)
2472     {
2473       mkalldirs (hs->local_file);
2474       if (opt.backups)
2475         rotate_backups (hs->local_file);
2476       if (hs->restval)
2477         {
2478 #ifdef __VMS
2479           int open_id;
2480
2481           open_id = 21;
2482           fp = fopen (hs->local_file, "ab", FOPEN_OPT_ARGS);
2483 #else /* def __VMS */
2484           fp = fopen (hs->local_file, "ab");
2485 #endif /* def __VMS [else] */
2486         }
2487       else if (ALLOW_CLOBBER)
2488         {
2489 #ifdef __VMS
2490           int open_id;
2491
2492           open_id = 22;
2493           fp = fopen (hs->local_file, "wb", FOPEN_OPT_ARGS);
2494 #else /* def __VMS */
2495           fp = fopen (hs->local_file, "wb");
2496 #endif /* def __VMS [else] */
2497         }
2498       else
2499         {
2500           fp = fopen_excl (hs->local_file, FOPEN_BIN_FLAG);
2501           if (!fp && errno == EEXIST)
2502             {
2503               /* We cannot just invent a new name and use it (which is
2504                  what functions like unique_create typically do)
2505                  because we told the user we'd use this name.
2506                  Instead, return and retry the download.  */
2507               logprintf (LOG_NOTQUIET,
2508                          _("%s has sprung into existence.\n"),
2509                          hs->local_file);
2510               CLOSE_INVALIDATE (sock);
2511               xfree (head);
2512               return FOPEN_EXCL_ERR;
2513             }
2514         }
2515       if (!fp)
2516         {
2517           logprintf (LOG_NOTQUIET, "%s: %s\n", hs->local_file, strerror (errno));
2518           CLOSE_INVALIDATE (sock);
2519           xfree (head);
2520           return FOPENERR;
2521         }
2522     }
2523   else
2524     fp = output_stream;
2525
2526   /* Print fetch message, if opt.verbose.  */
2527   if (opt.verbose)
2528     {
2529       logprintf (LOG_NOTQUIET, _("Saving to: %s\n"),
2530                  HYPHENP (hs->local_file) ? quote ("STDOUT") : quote (hs->local_file));
2531     }
2532
2533   /* This confuses the timestamping code that checks for file size.
2534      #### The timestamping code should be smarter about file size.  */
2535   if (opt.save_headers && hs->restval == 0)
2536     fwrite (head, 1, strlen (head), fp);
2537
2538   /* Now we no longer need to store the response header. */
2539   xfree (head);
2540
2541   /* Download the request body.  */
2542   flags = 0;
2543   if (contlen != -1)
2544     /* If content-length is present, read that much; otherwise, read
2545        until EOF.  The HTTP spec doesn't require the server to
2546        actually close the connection when it's done sending data. */
2547     flags |= rb_read_exactly;
2548   if (hs->restval > 0 && contrange == 0)
2549     /* If the server ignored our range request, instruct fd_read_body
2550        to skip the first RESTVAL bytes of body.  */
2551     flags |= rb_skip_startpos;
2552
2553   if (chunked_transfer_encoding)
2554     flags |= rb_chunked_transfer_encoding;
2555
2556   hs->len = hs->restval;
2557   hs->rd_size = 0;
2558   hs->res = fd_read_body (sock, fp, contlen != -1 ? contlen : 0,
2559                           hs->restval, &hs->rd_size, &hs->len, &hs->dltime,
2560                           flags);
2561
2562   if (hs->res >= 0)
2563     CLOSE_FINISH (sock);
2564   else
2565     {
2566       if (hs->res < 0)
2567         hs->rderrmsg = xstrdup (fd_errstr (sock));
2568       CLOSE_INVALIDATE (sock);
2569     }
2570
2571   if (!output_stream)
2572     fclose (fp);
2573   if (hs->res == -2)
2574     return FWRITEERR;
2575   return RETRFINISHED;
2576 }
2577
2578 /* The genuine HTTP loop!  This is the part where the retrieval is
2579    retried, and retried, and retried, and...  */
2580 uerr_t
2581 http_loop (struct url *u, struct url *original_url, char **newloc,
2582            char **local_file, const char *referer, int *dt, struct url *proxy,
2583            struct iri *iri)
2584 {
2585   int count;
2586   bool got_head = false;         /* used for time-stamping and filename detection */
2587   bool time_came_from_head = false;
2588   bool got_name = false;
2589   char *tms;
2590   const char *tmrate;
2591   uerr_t err, ret = TRYLIMEXC;
2592   time_t tmr = -1;               /* remote time-stamp */
2593   struct http_stat hstat;        /* HTTP status */
2594   struct_stat st;
2595   bool send_head_first = true;
2596   char *file_name;
2597   bool force_full_retrieve = false;
2598
2599   /* Assert that no value for *LOCAL_FILE was passed. */
2600   assert (local_file == NULL || *local_file == NULL);
2601
2602   /* Set LOCAL_FILE parameter. */
2603   if (local_file && opt.output_document)
2604     *local_file = HYPHENP (opt.output_document) ? NULL : xstrdup (opt.output_document);
2605
2606   /* Reset NEWLOC parameter. */
2607   *newloc = NULL;
2608
2609   /* This used to be done in main(), but it's a better idea to do it
2610      here so that we don't go through the hoops if we're just using
2611      FTP or whatever. */
2612   if (opt.cookies)
2613     load_cookies ();
2614
2615   /* Warn on (likely bogus) wildcard usage in HTTP. */
2616   if (opt.ftp_glob && has_wildcards_p (u->path))
2617     logputs (LOG_VERBOSE, _("Warning: wildcards not supported in HTTP.\n"));
2618
2619   /* Setup hstat struct. */
2620   xzero (hstat);
2621   hstat.referer = referer;
2622
2623   if (opt.output_document)
2624     {
2625       hstat.local_file = xstrdup (opt.output_document);
2626       got_name = true;
2627     }
2628   else if (!opt.content_disposition)
2629     {
2630       hstat.local_file =
2631         url_file_name (opt.trustservernames ? u : original_url, NULL);
2632       got_name = true;
2633     }
2634
2635   /* TODO: Ick! This code is now in both gethttp and http_loop, and is
2636    * screaming for some refactoring. */
2637   if (got_name && file_exists_p (hstat.local_file) && opt.noclobber && !opt.output_document)
2638     {
2639       /* If opt.noclobber is turned on and file already exists, do not
2640          retrieve the file. But if the output_document was given, then this
2641          test was already done and the file didn't exist. Hence the !opt.output_document */
2642       logprintf (LOG_VERBOSE, _("\
2643 File %s already there; not retrieving.\n\n"),
2644                  quote (hstat.local_file));
2645       /* If the file is there, we suppose it's retrieved OK.  */
2646       *dt |= RETROKF;
2647
2648       /* #### Bogusness alert.  */
2649       /* If its suffix is "html" or "htm" or similar, assume text/html.  */
2650       if (has_html_suffix_p (hstat.local_file))
2651         *dt |= TEXTHTML;
2652
2653       ret = RETROK;
2654       goto exit;
2655     }
2656
2657   /* Reset the counter. */
2658   count = 0;
2659
2660   /* Reset the document type. */
2661   *dt = 0;
2662
2663   /* Skip preliminary HEAD request if we're not in spider mode.  */
2664   if (!opt.spider)
2665     send_head_first = false;
2666
2667   /* Send preliminary HEAD request if -N is given and we have an existing
2668    * destination file. */
2669   file_name = url_file_name (opt.trustservernames ? u : original_url, NULL);
2670   if (opt.timestamping && (file_exists_p (file_name)
2671                            || opt.content_disposition))
2672     send_head_first = true;
2673   xfree (file_name);
2674
2675   /* THE loop */
2676   do
2677     {
2678       /* Increment the pass counter.  */
2679       ++count;
2680       sleep_between_retrievals (count);
2681
2682       /* Get the current time string.  */
2683       tms = datetime_str (time (NULL));
2684
2685       if (opt.spider && !got_head)
2686         logprintf (LOG_VERBOSE, _("\
2687 Spider mode enabled. Check if remote file exists.\n"));
2688
2689       /* Print fetch message, if opt.verbose.  */
2690       if (opt.verbose)
2691         {
2692           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
2693
2694           if (count > 1)
2695             {
2696               char tmp[256];
2697               sprintf (tmp, _("(try:%2d)"), count);
2698               logprintf (LOG_NOTQUIET, "--%s--  %s  %s\n",
2699                          tms, tmp, hurl);
2700             }
2701           else
2702             {
2703               logprintf (LOG_NOTQUIET, "--%s--  %s\n",
2704                          tms, hurl);
2705             }
2706
2707 #ifdef WINDOWS
2708           ws_changetitle (hurl);
2709 #endif
2710           xfree (hurl);
2711         }
2712
2713       /* Default document type is empty.  However, if spider mode is
2714          on or time-stamping is employed, HEAD_ONLY commands is
2715          encoded within *dt.  */
2716       if (send_head_first && !got_head)
2717         *dt |= HEAD_ONLY;
2718       else
2719         *dt &= ~HEAD_ONLY;
2720
2721       /* Decide whether or not to restart.  */
2722       if (force_full_retrieve)
2723         hstat.restval = hstat.len;
2724       else if (opt.always_rest
2725           && got_name
2726           && stat (hstat.local_file, &st) == 0
2727           && S_ISREG (st.st_mode))
2728         /* When -c is used, continue from on-disk size.  (Can't use
2729            hstat.len even if count>1 because we don't want a failed
2730            first attempt to clobber existing data.)  */
2731         hstat.restval = st.st_size;
2732       else if (count > 1)
2733         /* otherwise, continue where the previous try left off */
2734         hstat.restval = hstat.len;
2735       else
2736         hstat.restval = 0;
2737
2738       /* Decide whether to send the no-cache directive.  We send it in
2739          two cases:
2740            a) we're using a proxy, and we're past our first retrieval.
2741               Some proxies are notorious for caching incomplete data, so
2742               we require a fresh get.
2743            b) caching is explicitly inhibited. */
2744       if ((proxy && count > 1)        /* a */
2745           || !opt.allow_cache)        /* b */
2746         *dt |= SEND_NOCACHE;
2747       else
2748         *dt &= ~SEND_NOCACHE;
2749
2750       /* Try fetching the document, or at least its head.  */
2751       err = gethttp (u, &hstat, dt, proxy, iri);
2752
2753       /* Time?  */
2754       tms = datetime_str (time (NULL));
2755
2756       /* Get the new location (with or without the redirection).  */
2757       if (hstat.newloc)
2758         *newloc = xstrdup (hstat.newloc);
2759
2760       switch (err)
2761         {
2762         case HERR: case HEOF: case CONSOCKERR: case CONCLOSED:
2763         case CONERROR: case READERR: case WRITEFAILED:
2764         case RANGEERR: case FOPEN_EXCL_ERR:
2765           /* Non-fatal errors continue executing the loop, which will
2766              bring them to "while" statement at the end, to judge
2767              whether the number of tries was exceeded.  */
2768           printwhat (count, opt.ntry);
2769           continue;
2770         case FWRITEERR: case FOPENERR:
2771           /* Another fatal error.  */
2772           logputs (LOG_VERBOSE, "\n");
2773           logprintf (LOG_NOTQUIET, _("Cannot write to %s (%s).\n"),
2774                      quote (hstat.local_file), strerror (errno));
2775         case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case AUTHFAILED:
2776         case SSLINITFAILED: case CONTNOTSUPPORTED: case VERIFCERTERR:
2777           /* Fatal errors just return from the function.  */
2778           ret = err;
2779           goto exit;
2780         case CONSSLERR:
2781           /* Another fatal error.  */
2782           logprintf (LOG_NOTQUIET, _("Unable to establish SSL connection.\n"));
2783           ret = err;
2784           goto exit;
2785         case NEWLOCATION:
2786           /* Return the new location to the caller.  */
2787           if (!*newloc)
2788             {
2789               logprintf (LOG_NOTQUIET,
2790                          _("ERROR: Redirection (%d) without location.\n"),
2791                          hstat.statcode);
2792               ret = WRONGCODE;
2793             }
2794           else
2795             {
2796               ret = NEWLOCATION;
2797             }
2798           goto exit;
2799         case RETRUNNEEDED:
2800           /* The file was already fully retrieved. */
2801           ret = RETROK;
2802           goto exit;
2803         case RETRFINISHED:
2804           /* Deal with you later.  */
2805           break;
2806         default:
2807           /* All possibilities should have been exhausted.  */
2808           abort ();
2809         }
2810
2811       if (!(*dt & RETROKF))
2812         {
2813           char *hurl = NULL;
2814           if (!opt.verbose)
2815             {
2816               /* #### Ugly ugly ugly! */
2817               hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
2818               logprintf (LOG_NONVERBOSE, "%s:\n", hurl);
2819             }
2820
2821           /* Fall back to GET if HEAD fails with a 500 or 501 error code. */
2822           if (*dt & HEAD_ONLY
2823               && (hstat.statcode == 500 || hstat.statcode == 501))
2824             {
2825               got_head = true;
2826               continue;
2827             }
2828           /* Maybe we should always keep track of broken links, not just in
2829            * spider mode.
2830            * Don't log error if it was UTF-8 encoded because we will try
2831            * once unencoded. */
2832           else if (opt.spider && !iri->utf8_encode)
2833             {
2834               /* #### Again: ugly ugly ugly! */
2835               if (!hurl)
2836                 hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
2837               nonexisting_url (hurl);
2838               logprintf (LOG_NOTQUIET, _("\
2839 Remote file does not exist -- broken link!!!\n"));
2840             }
2841           else
2842             {
2843               logprintf (LOG_NOTQUIET, _("%s ERROR %d: %s.\n"),
2844                          tms, hstat.statcode,
2845                          quotearg_style (escape_quoting_style, hstat.error));
2846             }
2847           logputs (LOG_VERBOSE, "\n");
2848           ret = WRONGCODE;
2849           xfree_null (hurl);
2850           goto exit;
2851         }
2852
2853       /* Did we get the time-stamp? */
2854       if (!got_head)
2855         {
2856           got_head = true;    /* no more time-stamping */
2857
2858           if (opt.timestamping && !hstat.remote_time)
2859             {
2860               logputs (LOG_NOTQUIET, _("\
2861 Last-modified header missing -- time-stamps turned off.\n"));
2862             }
2863           else if (hstat.remote_time)
2864             {
2865               /* Convert the date-string into struct tm.  */
2866               tmr = http_atotm (hstat.remote_time);
2867               if (tmr == (time_t) (-1))
2868                 logputs (LOG_VERBOSE, _("\
2869 Last-modified header invalid -- time-stamp ignored.\n"));
2870               if (*dt & HEAD_ONLY)
2871                 time_came_from_head = true;
2872             }
2873
2874           if (send_head_first)
2875             {
2876               /* The time-stamping section.  */
2877               if (opt.timestamping)
2878                 {
2879                   if (hstat.orig_file_name) /* Perform the following
2880                                                checks only if the file
2881                                                we're supposed to
2882                                                download already exists.  */
2883                     {
2884                       if (hstat.remote_time &&
2885                           tmr != (time_t) (-1))
2886                         {
2887                           /* Now time-stamping can be used validly.
2888                              Time-stamping means that if the sizes of
2889                              the local and remote file match, and local
2890                              file is newer than the remote file, it will
2891                              not be retrieved.  Otherwise, the normal
2892                              download procedure is resumed.  */
2893                           if (hstat.orig_file_tstamp >= tmr)
2894                             {
2895                               if (hstat.contlen == -1
2896                                   || hstat.orig_file_size == hstat.contlen)
2897                                 {
2898                                   logprintf (LOG_VERBOSE, _("\
2899 Server file no newer than local file %s -- not retrieving.\n\n"),
2900                                              quote (hstat.orig_file_name));
2901                                   ret = RETROK;
2902                                   goto exit;
2903                                 }
2904                               else
2905                                 {
2906                                   logprintf (LOG_VERBOSE, _("\
2907 The sizes do not match (local %s) -- retrieving.\n"),
2908                                              number_to_static_string (hstat.orig_file_size));
2909                                 }
2910                             }
2911                           else
2912                             {
2913                               force_full_retrieve = true;
2914                               logputs (LOG_VERBOSE,
2915                                        _("Remote file is newer, retrieving.\n"));
2916                             }
2917
2918                           logputs (LOG_VERBOSE, "\n");
2919                         }
2920                     }
2921
2922                   /* free_hstat (&hstat); */
2923                   hstat.timestamp_checked = true;
2924                 }
2925
2926               if (opt.spider)
2927                 {
2928                   bool finished = true;
2929                   if (opt.recursive)
2930                     {
2931                       if (*dt & TEXTHTML)
2932                         {
2933                           logputs (LOG_VERBOSE, _("\
2934 Remote file exists and could contain links to other resources -- retrieving.\n\n"));
2935                           finished = false;
2936                         }
2937                       else
2938                         {
2939                           logprintf (LOG_VERBOSE, _("\
2940 Remote file exists but does not contain any link -- not retrieving.\n\n"));
2941                           ret = RETROK; /* RETRUNNEEDED is not for caller. */
2942                         }
2943                     }
2944                   else
2945                     {
2946                       if (*dt & TEXTHTML)
2947                         {
2948                           logprintf (LOG_VERBOSE, _("\
2949 Remote file exists and could contain further links,\n\
2950 but recursion is disabled -- not retrieving.\n\n"));
2951                         }
2952                       else
2953                         {
2954                           logprintf (LOG_VERBOSE, _("\
2955 Remote file exists.\n\n"));
2956                         }
2957                       ret = RETROK; /* RETRUNNEEDED is not for caller. */
2958                     }
2959
2960                   if (finished)
2961                     {
2962                       logprintf (LOG_NONVERBOSE,
2963                                  _("%s URL: %s %2d %s\n"),
2964                                  tms, u->url, hstat.statcode,
2965                                  hstat.message ? quotearg_style (escape_quoting_style, hstat.message) : "");
2966                       goto exit;
2967                     }
2968                 }
2969
2970               got_name = true;
2971               *dt &= ~HEAD_ONLY;
2972               count = 0;          /* the retrieve count for HEAD is reset */
2973               continue;
2974             } /* send_head_first */
2975         } /* !got_head */
2976
2977       if (opt.useservertimestamps
2978           && (tmr != (time_t) (-1))
2979           && ((hstat.len == hstat.contlen) ||
2980               ((hstat.res == 0) && (hstat.contlen == -1))))
2981         {
2982           const char *fl = NULL;
2983           set_local_file (&fl, hstat.local_file);
2984           if (fl)
2985             {
2986               time_t newtmr = -1;
2987               /* Reparse time header, in case it's changed. */
2988               if (time_came_from_head
2989                   && hstat.remote_time && hstat.remote_time[0])
2990                 {
2991                   newtmr = http_atotm (hstat.remote_time);
2992                   if (newtmr != (time_t)-1)
2993                     tmr = newtmr;
2994                 }
2995               touch (fl, tmr);
2996             }
2997         }
2998       /* End of time-stamping section. */
2999
3000       tmrate = retr_rate (hstat.rd_size, hstat.dltime);
3001       total_download_time += hstat.dltime;
3002
3003       if (hstat.len == hstat.contlen)
3004         {
3005           if (*dt & RETROKF)
3006             {
3007               bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
3008
3009               logprintf (LOG_VERBOSE,
3010                          write_to_stdout
3011                          ? _("%s (%s) - written to stdout %s[%s/%s]\n\n")
3012                          : _("%s (%s) - %s saved [%s/%s]\n\n"),
3013                          tms, tmrate,
3014                          write_to_stdout ? "" : quote (hstat.local_file),
3015                          number_to_static_string (hstat.len),
3016                          number_to_static_string (hstat.contlen));
3017               logprintf (LOG_NONVERBOSE,
3018                          "%s URL:%s [%s/%s] -> \"%s\" [%d]\n",
3019                          tms, u->url,
3020                          number_to_static_string (hstat.len),
3021                          number_to_static_string (hstat.contlen),
3022                          hstat.local_file, count);
3023             }
3024           ++numurls;
3025           total_downloaded_bytes += hstat.rd_size;
3026
3027           /* Remember that we downloaded the file for later ".orig" code. */
3028           if (*dt & ADDED_HTML_EXTENSION)
3029             downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file);
3030           else
3031             downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file);
3032
3033           ret = RETROK;
3034           goto exit;
3035         }
3036       else if (hstat.res == 0) /* No read error */
3037         {
3038           if (hstat.contlen == -1)  /* We don't know how much we were supposed
3039                                        to get, so assume we succeeded. */
3040             {
3041               if (*dt & RETROKF)
3042                 {
3043                   bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
3044
3045                   logprintf (LOG_VERBOSE,
3046                              write_to_stdout
3047                              ? _("%s (%s) - written to stdout %s[%s]\n\n")
3048                              : _("%s (%s) - %s saved [%s]\n\n"),
3049                              tms, tmrate,
3050                              write_to_stdout ? "" : quote (hstat.local_file),
3051                              number_to_static_string (hstat.len));
3052                   logprintf (LOG_NONVERBOSE,
3053                              "%s URL:%s [%s] -> \"%s\" [%d]\n",
3054                              tms, u->url, number_to_static_string (hstat.len),
3055                              hstat.local_file, count);
3056                 }
3057               ++numurls;
3058               total_downloaded_bytes += hstat.rd_size;
3059
3060               /* Remember that we downloaded the file for later ".orig" code. */
3061               if (*dt & ADDED_HTML_EXTENSION)
3062                 downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file);
3063               else
3064                 downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file);
3065
3066               ret = RETROK;
3067               goto exit;
3068             }
3069           else if (hstat.len < hstat.contlen) /* meaning we lost the
3070                                                  connection too soon */
3071             {
3072               logprintf (LOG_VERBOSE,
3073                          _("%s (%s) - Connection closed at byte %s. "),
3074                          tms, tmrate, number_to_static_string (hstat.len));
3075               printwhat (count, opt.ntry);
3076               continue;
3077             }
3078           else if (hstat.len != hstat.restval)
3079             /* Getting here would mean reading more data than
3080                requested with content-length, which we never do.  */
3081             abort ();
3082           else
3083             {
3084               /* Getting here probably means that the content-length was
3085                * _less_ than the original, local size. We should probably
3086                * truncate or re-read, or something. FIXME */
3087               ret = RETROK;
3088               goto exit;
3089             }
3090         }
3091       else /* from now on hstat.res can only be -1 */
3092         {
3093           if (hstat.contlen == -1)
3094             {
3095               logprintf (LOG_VERBOSE,
3096                          _("%s (%s) - Read error at byte %s (%s)."),
3097                          tms, tmrate, number_to_static_string (hstat.len),
3098                          hstat.rderrmsg);
3099               printwhat (count, opt.ntry);
3100               continue;
3101             }
3102           else /* hstat.res == -1 and contlen is given */
3103             {
3104               logprintf (LOG_VERBOSE,
3105                          _("%s (%s) - Read error at byte %s/%s (%s). "),
3106                          tms, tmrate,
3107                          number_to_static_string (hstat.len),
3108                          number_to_static_string (hstat.contlen),
3109                          hstat.rderrmsg);
3110               printwhat (count, opt.ntry);
3111               continue;
3112             }
3113         }
3114       /* not reached */
3115     }
3116   while (!opt.ntry || (count < opt.ntry));
3117
3118 exit:
3119   if (ret == RETROK)
3120     *local_file = xstrdup (hstat.local_file);
3121   free_hstat (&hstat);
3122
3123   return ret;
3124 }
3125 \f
3126 /* Check whether the result of strptime() indicates success.
3127    strptime() returns the pointer to how far it got to in the string.
3128    The processing has been successful if the string is at `GMT' or
3129    `+X', or at the end of the string.
3130
3131    In extended regexp parlance, the function returns 1 if P matches
3132    "^ *(GMT|[+-][0-9]|$)", 0 otherwise.  P being NULL (which strptime
3133    can return) is considered a failure and 0 is returned.  */
3134 static bool
3135 check_end (const char *p)
3136 {
3137   if (!p)
3138     return false;
3139   while (c_isspace (*p))
3140     ++p;
3141   if (!*p
3142       || (p[0] == 'G' && p[1] == 'M' && p[2] == 'T')
3143       || ((p[0] == '+' || p[0] == '-') && c_isdigit (p[1])))
3144     return true;
3145   else
3146     return false;
3147 }
3148
3149 /* Convert the textual specification of time in TIME_STRING to the
3150    number of seconds since the Epoch.
3151
3152    TIME_STRING can be in any of the three formats RFC2616 allows the
3153    HTTP servers to emit -- RFC1123-date, RFC850-date or asctime-date,
3154    as well as the time format used in the Set-Cookie header.
3155    Timezones are ignored, and should be GMT.
3156
3157    Return the computed time_t representation, or -1 if the conversion
3158    fails.
3159
3160    This function uses strptime with various string formats for parsing
3161    TIME_STRING.  This results in a parser that is not as lenient in
3162    interpreting TIME_STRING as I would like it to be.  Being based on
3163    strptime, it always allows shortened months, one-digit days, etc.,
3164    but due to the multitude of formats in which time can be
3165    represented, an ideal HTTP time parser would be even more
3166    forgiving.  It should completely ignore things like week days and
3167    concentrate only on the various forms of representing years,
3168    months, days, hours, minutes, and seconds.  For example, it would
3169    be nice if it accepted ISO 8601 out of the box.
3170
3171    I've investigated free and PD code for this purpose, but none was
3172    usable.  getdate was big and unwieldy, and had potential copyright
3173    issues, or so I was informed.  Dr. Marcus Hennecke's atotm(),
3174    distributed with phttpd, is excellent, but we cannot use it because
3175    it is not assigned to the FSF.  So I stuck it with strptime.  */
3176
3177 time_t
3178 http_atotm (const char *time_string)
3179 {
3180   /* NOTE: Solaris strptime man page claims that %n and %t match white
3181      space, but that's not universally available.  Instead, we simply
3182      use ` ' to mean "skip all WS", which works under all strptime
3183      implementations I've tested.  */
3184
3185   static const char *time_formats[] = {
3186     "%a, %d %b %Y %T",          /* rfc1123: Thu, 29 Jan 1998 22:12:57 */
3187     "%A, %d-%b-%y %T",          /* rfc850:  Thursday, 29-Jan-98 22:12:57 */
3188     "%a %b %d %T %Y",           /* asctime: Thu Jan 29 22:12:57 1998 */
3189     "%a, %d-%b-%Y %T"           /* cookies: Thu, 29-Jan-1998 22:12:57
3190                                    (used in Set-Cookie, defined in the
3191                                    Netscape cookie specification.) */
3192   };
3193   const char *oldlocale;
3194   char savedlocale[256];
3195   size_t i;
3196   time_t ret = (time_t) -1;
3197
3198   /* Solaris strptime fails to recognize English month names in
3199      non-English locales, which we work around by temporarily setting
3200      locale to C before invoking strptime.  */
3201   oldlocale = setlocale (LC_TIME, NULL);
3202   if (oldlocale)
3203     {
3204       size_t l = strlen (oldlocale) + 1;
3205       if (l >= sizeof savedlocale)
3206         savedlocale[0] = '\0';
3207       else
3208         memcpy (savedlocale, oldlocale, l);
3209     }
3210   else savedlocale[0] = '\0';
3211
3212   setlocale (LC_TIME, "C");
3213
3214   for (i = 0; i < countof (time_formats); i++)
3215     {
3216       struct tm t;
3217
3218       /* Some versions of strptime use the existing contents of struct
3219          tm to recalculate the date according to format.  Zero it out
3220          to prevent stack garbage from influencing strptime.  */
3221       xzero (t);
3222
3223       if (check_end (strptime (time_string, time_formats[i], &t)))
3224         {
3225           ret = timegm (&t);
3226           break;
3227         }
3228     }
3229
3230   /* Restore the previous locale. */
3231   if (savedlocale[0])
3232     setlocale (LC_TIME, savedlocale);
3233
3234   return ret;
3235 }
3236 \f
3237 /* Authorization support: We support three authorization schemes:
3238
3239    * `Basic' scheme, consisting of base64-ing USER:PASSWORD string;
3240
3241    * `Digest' scheme, added by Junio Hamano <junio@twinsun.com>,
3242    consisting of answering to the server's challenge with the proper
3243    MD5 digests.
3244
3245    * `NTLM' ("NT Lan Manager") scheme, based on code written by Daniel
3246    Stenberg for libcurl.  Like digest, NTLM is based on a
3247    challenge-response mechanism, but unlike digest, it is non-standard
3248    (authenticates TCP connections rather than requests), undocumented
3249    and Microsoft-specific.  */
3250
3251 /* Create the authentication header contents for the `Basic' scheme.
3252    This is done by encoding the string "USER:PASS" to base64 and
3253    prepending the string "Basic " in front of it.  */
3254
3255 static char *
3256 basic_authentication_encode (const char *user, const char *passwd)
3257 {
3258   char *t1, *t2;
3259   int len1 = strlen (user) + 1 + strlen (passwd);
3260
3261   t1 = (char *)alloca (len1 + 1);
3262   sprintf (t1, "%s:%s", user, passwd);
3263
3264   t2 = (char *)alloca (BASE64_LENGTH (len1) + 1);
3265   base64_encode (t1, len1, t2);
3266
3267   return concat_strings ("Basic ", t2, (char *) 0);
3268 }
3269
3270 #define SKIP_WS(x) do {                         \
3271   while (c_isspace (*(x)))                        \
3272     ++(x);                                      \
3273 } while (0)
3274
3275 #ifdef ENABLE_DIGEST
3276 /* Dump the hexadecimal representation of HASH to BUF.  HASH should be
3277    an array of 16 bytes containing the hash keys, and BUF should be a
3278    buffer of 33 writable characters (32 for hex digits plus one for
3279    zero termination).  */
3280 static void
3281 dump_hash (char *buf, const unsigned char *hash)
3282 {
3283   int i;
3284
3285   for (i = 0; i < MD5_DIGEST_SIZE; i++, hash++)
3286     {
3287       *buf++ = XNUM_TO_digit (*hash >> 4);
3288       *buf++ = XNUM_TO_digit (*hash & 0xf);
3289     }
3290   *buf = '\0';
3291 }
3292
3293 /* Take the line apart to find the challenge, and compose a digest
3294    authorization header.  See RFC2069 section 2.1.2.  */
3295 static char *
3296 digest_authentication_encode (const char *au, const char *user,
3297                               const char *passwd, const char *method,
3298                               const char *path)
3299 {
3300   static char *realm, *opaque, *nonce;
3301   static struct {
3302     const char *name;
3303     char **variable;
3304   } options[] = {
3305     { "realm", &realm },
3306     { "opaque", &opaque },
3307     { "nonce", &nonce }
3308   };
3309   char *res;
3310   param_token name, value;
3311
3312   realm = opaque = nonce = NULL;
3313
3314   au += 6;                      /* skip over `Digest' */
3315   while (extract_param (&au, &name, &value, ','))
3316     {
3317       size_t i;
3318       size_t namelen = name.e - name.b;
3319       for (i = 0; i < countof (options); i++)
3320         if (namelen == strlen (options[i].name)
3321             && 0 == strncmp (name.b, options[i].name,
3322                              namelen))
3323           {
3324             *options[i].variable = strdupdelim (value.b, value.e);
3325             break;
3326           }
3327     }
3328   if (!realm || !nonce || !user || !passwd || !path || !method)
3329     {
3330       xfree_null (realm);
3331       xfree_null (opaque);
3332       xfree_null (nonce);
3333       return NULL;
3334     }
3335
3336   /* Calculate the digest value.  */
3337   {
3338     struct md5_ctx ctx;
3339     unsigned char hash[MD5_DIGEST_SIZE];
3340     char a1buf[MD5_DIGEST_SIZE * 2 + 1], a2buf[MD5_DIGEST_SIZE * 2 + 1];
3341     char response_digest[MD5_DIGEST_SIZE * 2 + 1];
3342
3343     /* A1BUF = H(user ":" realm ":" password) */
3344     md5_init_ctx (&ctx);
3345     md5_process_bytes ((unsigned char *)user, strlen (user), &ctx);
3346     md5_process_bytes ((unsigned char *)":", 1, &ctx);
3347     md5_process_bytes ((unsigned char *)realm, strlen (realm), &ctx);
3348     md5_process_bytes ((unsigned char *)":", 1, &ctx);
3349     md5_process_bytes ((unsigned char *)passwd, strlen (passwd), &ctx);
3350     md5_finish_ctx (&ctx, hash);
3351     dump_hash (a1buf, hash);
3352
3353     /* A2BUF = H(method ":" path) */
3354     md5_init_ctx (&ctx);
3355     md5_process_bytes ((unsigned char *)method, strlen (method), &ctx);
3356     md5_process_bytes ((unsigned char *)":", 1, &ctx);
3357     md5_process_bytes ((unsigned char *)path, strlen (path), &ctx);
3358     md5_finish_ctx (&ctx, hash);
3359     dump_hash (a2buf, hash);
3360
3361     /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) */
3362     md5_init_ctx (&ctx);
3363     md5_process_bytes ((unsigned char *)a1buf, MD5_DIGEST_SIZE * 2, &ctx);
3364     md5_process_bytes ((unsigned char *)":", 1, &ctx);
3365     md5_process_bytes ((unsigned char *)nonce, strlen (nonce), &ctx);
3366     md5_process_bytes ((unsigned char *)":", 1, &ctx);
3367     md5_process_bytes ((unsigned char *)a2buf, MD5_DIGEST_SIZE * 2, &ctx);
3368     md5_finish_ctx (&ctx, hash);
3369     dump_hash (response_digest, hash);
3370
3371     res = xmalloc (strlen (user)
3372                    + strlen (user)
3373                    + strlen (realm)
3374                    + strlen (nonce)
3375                    + strlen (path)
3376                    + 2 * MD5_DIGEST_SIZE /*strlen (response_digest)*/
3377                    + (opaque ? strlen (opaque) : 0)
3378                    + 128);
3379     sprintf (res, "Digest \
3380 username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
3381              user, realm, nonce, path, response_digest);
3382     if (opaque)
3383       {
3384         char *p = res + strlen (res);
3385         strcat (p, ", opaque=\"");
3386         strcat (p, opaque);
3387         strcat (p, "\"");
3388       }
3389   }
3390   return res;
3391 }
3392 #endif /* ENABLE_DIGEST */
3393
3394 /* Computing the size of a string literal must take into account that
3395    value returned by sizeof includes the terminating \0.  */
3396 #define STRSIZE(literal) (sizeof (literal) - 1)
3397
3398 /* Whether chars in [b, e) begin with the literal string provided as
3399    first argument and are followed by whitespace or terminating \0.
3400    The comparison is case-insensitive.  */
3401 #define STARTS(literal, b, e)                           \
3402   ((e > b) \
3403    && ((size_t) ((e) - (b))) >= STRSIZE (literal)   \
3404    && 0 == strncasecmp (b, literal, STRSIZE (literal))  \
3405    && ((size_t) ((e) - (b)) == STRSIZE (literal)          \
3406        || c_isspace (b[STRSIZE (literal)])))
3407
3408 static bool
3409 known_authentication_scheme_p (const char *hdrbeg, const char *hdrend)
3410 {
3411   return STARTS ("Basic", hdrbeg, hdrend)
3412 #ifdef ENABLE_DIGEST
3413     || STARTS ("Digest", hdrbeg, hdrend)
3414 #endif
3415 #ifdef ENABLE_NTLM
3416     || STARTS ("NTLM", hdrbeg, hdrend)
3417 #endif
3418     ;
3419 }
3420
3421 #undef STARTS
3422
3423 /* Create the HTTP authorization request header.  When the
3424    `WWW-Authenticate' response header is seen, according to the
3425    authorization scheme specified in that header (`Basic' and `Digest'
3426    are supported by the current implementation), produce an
3427    appropriate HTTP authorization request header.  */
3428 static char *
3429 create_authorization_line (const char *au, const char *user,
3430                            const char *passwd, const char *method,
3431                            const char *path, bool *finished)
3432 {
3433   /* We are called only with known schemes, so we can dispatch on the
3434      first letter. */
3435   switch (c_toupper (*au))
3436     {
3437     case 'B':                   /* Basic */
3438       *finished = true;
3439       return basic_authentication_encode (user, passwd);
3440 #ifdef ENABLE_DIGEST
3441     case 'D':                   /* Digest */
3442       *finished = true;
3443       return digest_authentication_encode (au, user, passwd, method, path);
3444 #endif
3445 #ifdef ENABLE_NTLM
3446     case 'N':                   /* NTLM */
3447       if (!ntlm_input (&pconn.ntlm, au))
3448         {
3449           *finished = true;
3450           return NULL;
3451         }
3452       return ntlm_output (&pconn.ntlm, user, passwd, finished);
3453 #endif
3454     default:
3455       /* We shouldn't get here -- this function should be only called
3456          with values approved by known_authentication_scheme_p.  */
3457       abort ();
3458     }
3459 }
3460 \f
3461 static void
3462 load_cookies (void)
3463 {
3464   if (!wget_cookie_jar)
3465     wget_cookie_jar = cookie_jar_new ();
3466   if (opt.cookies_input && !cookies_loaded_p)
3467     {
3468       cookie_jar_load (wget_cookie_jar, opt.cookies_input);
3469       cookies_loaded_p = true;
3470     }
3471 }
3472
3473 void
3474 save_cookies (void)
3475 {
3476   if (wget_cookie_jar)
3477     cookie_jar_save (wget_cookie_jar, opt.cookies_output);
3478 }
3479
3480 void
3481 http_cleanup (void)
3482 {
3483   xfree_null (pconn.host);
3484   if (wget_cookie_jar)
3485     cookie_jar_delete (wget_cookie_jar);
3486 }
3487
3488 void
3489 ensure_extension (struct http_stat *hs, const char *ext, int *dt)
3490 {
3491   char *last_period_in_local_filename = strrchr (hs->local_file, '.');
3492   char shortext[8];
3493   int len = strlen (ext);
3494   if (len == 5)
3495     {
3496       strncpy (shortext, ext, len - 1);
3497       shortext[len - 2] = '\0';
3498     }
3499
3500   if (last_period_in_local_filename == NULL
3501       || !(0 == strcasecmp (last_period_in_local_filename, shortext)
3502            || 0 == strcasecmp (last_period_in_local_filename, ext)))
3503     {
3504       int local_filename_len = strlen (hs->local_file);
3505       /* Resize the local file, allowing for ".html" preceded by
3506          optional ".NUMBER".  */
3507       hs->local_file = xrealloc (hs->local_file,
3508                                  local_filename_len + 24 + len);
3509       strcpy (hs->local_file + local_filename_len, ext);
3510       /* If clobbering is not allowed and the file, as named,
3511          exists, tack on ".NUMBER.html" instead. */
3512       if (!ALLOW_CLOBBER && file_exists_p (hs->local_file))
3513         {
3514           int ext_num = 1;
3515           do
3516             sprintf (hs->local_file + local_filename_len,
3517                      ".%d%s", ext_num++, ext);
3518           while (file_exists_p (hs->local_file));
3519         }
3520       *dt |= ADDED_HTML_EXTENSION;
3521     }
3522 }
3523
3524
3525 #ifdef TESTING
3526
3527 const char *
3528 test_parse_content_disposition()
3529 {
3530   int i;
3531   struct {
3532     char *hdrval;
3533     char *filename;
3534     bool result;
3535   } test_array[] = {
3536     { "filename=\"file.ext\"", "file.ext", true },
3537     { "attachment; filename=\"file.ext\"", "file.ext", true },
3538     { "attachment; filename=\"file.ext\"; dummy", "file.ext", true },
3539     { "attachment", NULL, false },
3540     { "attachement; filename*=UTF-8'en-US'hello.txt", "hello.txt", true },
3541     { "attachement; filename*0=\"hello\"; filename*1=\"world.txt\"", "helloworld.txt", true },
3542   };
3543
3544   for (i = 0; i < sizeof(test_array)/sizeof(test_array[0]); ++i)
3545     {
3546       char *filename;
3547       bool res;
3548
3549       res = parse_content_disposition (test_array[i].hdrval, &filename);
3550
3551       mu_assert ("test_parse_content_disposition: wrong result",
3552                  res == test_array[i].result
3553                  && (res == false
3554                      || 0 == strcmp (test_array[i].filename, filename)));
3555     }
3556
3557   return NULL;
3558 }
3559
3560 #endif /* TESTING */
3561
3562 /*
3563  * vim: et sts=2 sw=2 cino+={s
3564  */
3565