]> sjero.net Git - wget/blob - src/retr.c
3251b3d08f0b2bf84ce9d7c4cea6924972116a1e
[wget] / src / retr.c
1 /* File retrieval.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif /* HAVE_UNISTD_H */
28 #include <errno.h>
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #else
32 # include <strings.h>
33 #endif /* HAVE_STRING_H */
34 #include <assert.h>
35
36 #include "wget.h"
37 #include "utils.h"
38 #include "retr.h"
39 #include "url.h"
40 #include "recur.h"
41 #include "ftp.h"
42 #include "host.h"
43 #include "connect.h"
44 #include "hash.h"
45
46 #ifndef errno
47 extern int errno;
48 #endif
49
50 /* See the comment in gethttp() why this is needed. */
51 int global_download_count;
52
53 void logflush PARAMS ((void));
54
55 /* From http.c.  */
56 uerr_t http_loop PARAMS ((struct urlinfo *, char **, int *));
57 \f
58 /* Flags for show_progress().  */
59 enum spflags { SP_NONE, SP_INIT, SP_FINISH };
60
61 static int show_progress PARAMS ((long, long, enum spflags));
62
63 #define MIN(i, j) ((i) <= (j) ? (i) : (j))
64
65 /* Reads the contents of file descriptor FD, until it is closed, or a
66    read error occurs.  The data is read in 8K chunks, and stored to
67    stream fp, which should have been open for writing.  If BUF is
68    non-NULL and its file descriptor is equal to FD, flush RBUF first.
69    This function will *not* use the rbuf_* functions!
70
71    The EXPECTED argument is passed to show_progress() unchanged, but
72    otherwise ignored.
73
74    If opt.verbose is set, the progress is also shown.  RESTVAL
75    represents a value from which to start downloading (which will be
76    shown accordingly).  If RESTVAL is non-zero, the stream should have
77    been open for appending.
78
79    The function exits and returns codes of 0, -1 and -2 if the
80    connection was closed, there was a read error, or if it could not
81    write to the output stream, respectively.
82
83    IMPORTANT: The function flushes the contents of the buffer in
84    rbuf_flush() before actually reading from fd.  If you wish to read
85    from fd immediately, flush or discard the buffer.  */
86 int
87 get_contents (int fd, FILE *fp, long *len, long restval, long expected,
88               struct rbuf *rbuf, int use_expected)
89 {
90   int res = 0;
91   static char c[8192];
92
93   *len = restval;
94   if (opt.verbose)
95     show_progress (restval, expected, SP_INIT);
96   if (rbuf && RBUF_FD (rbuf) == fd)
97     {
98       while ((res = rbuf_flush (rbuf, c, sizeof (c))) != 0)
99         {
100           if (fwrite (c, sizeof (char), res, fp) < res)
101             return -2;
102           if (opt.verbose)
103             {
104               if (show_progress (res, expected, SP_NONE))
105                 fflush (fp);
106             }
107           *len += res;
108         }
109     }
110   /* Read from fd while there is available data.
111
112      Normally, if expected is 0, it means that it is not known how
113      much data is expected.  However, if use_expected is specified,
114      then expected being zero means exactly that.  */
115   while (!use_expected || (*len < expected))
116     {
117       int amount_to_read = (use_expected
118                             ? MIN (expected - *len, sizeof (c))
119                             : sizeof (c));
120 #ifdef HAVE_SSL
121                 if (rbuf->ssl!=NULL) {
122                   res = ssl_iread (rbuf->ssl, c, amount_to_read);
123                 } else {
124 #endif /* HAVE_SSL */
125                   res = iread (fd, c, amount_to_read);
126 #ifdef HAVE_SSL
127                 }
128 #endif /* HAVE_SSL */
129       if (res > 0)
130         {
131           if (fwrite (c, sizeof (char), res, fp) < res)
132             return -2;
133           if (opt.verbose)
134             {
135               if (show_progress (res, expected, SP_NONE))
136                 fflush (fp);
137             }
138           *len += res;
139         }
140       else
141         break;
142     }
143   if (res < -1)
144     res = -1;
145   if (opt.verbose)
146     show_progress (0, expected, SP_FINISH);
147   return res;
148 }
149
150 static void
151 print_percentage (long bytes, long expected)
152 {
153   int percentage = (int)(100.0 * bytes / expected);
154   logprintf (LOG_VERBOSE, "%3d%%", percentage);
155 }
156
157 /* Show the dotted progress report of file loading.  Called with
158    length and a flag to tell it whether to reset or not.  It keeps the
159    offset information in static local variables.
160
161    Return value: 1 or 0, designating whether any dots have been drawn.
162
163    If the init argument is set, the routine will initialize.
164
165    If the res is non-zero, res/line_bytes lines are skipped
166    (meaning the appropriate number ok kilobytes), and the number of
167    "dots" fitting on the first line are drawn as ','.  */
168 static int
169 show_progress (long res, long expected, enum spflags flags)
170 {
171   static struct wget_timer *timer;
172   static long line_bytes;
173   static long offs, initial_skip;
174   static int ndot, nrow;
175   static long last_timer_value, time_offset;
176   int any_output = 0;
177
178   if (flags == SP_FINISH)
179     {
180       int dot = ndot;
181       char *tmpstr = (char *)alloca (2 * opt.dots_in_line + 1);
182       char *tmpp = tmpstr;
183       time_offset = wtimer_elapsed (timer) - last_timer_value;
184       for (; dot < opt.dots_in_line; dot++)
185         {
186           if (!(dot % opt.dot_spacing))
187             *tmpp++ = ' ';
188           *tmpp++ = ' ';
189         }
190       *tmpp = '\0';
191       logputs (LOG_VERBOSE, tmpstr);
192       if (expected)
193         print_percentage (nrow * line_bytes + ndot * opt.dot_bytes + offs,
194                           expected);
195       logprintf (LOG_VERBOSE, " @%s",
196                  rate (ndot * opt.dot_bytes
197                        + offs - (initial_skip % line_bytes),
198                        time_offset, 1));
199       logputs (LOG_VERBOSE, "\n\n");
200       return 0;
201     }
202
203   /* Temporarily disable flushing.  */
204   opt.no_flush = 1;
205   /* init set means initialization.  If res is set, it also means that
206      the retrieval is *not* done from the beginning.  The part that
207      was already retrieved is not shown again.  */
208   if (flags == SP_INIT)
209     {
210       /* Generic initialization of static variables.  */
211       offs = 0L;
212       ndot = nrow = 0;
213       line_bytes = (long)opt.dots_in_line * opt.dot_bytes;
214       if (!timer)
215         timer = wtimer_allocate ();
216       wtimer_reset (timer);
217       last_timer_value = 0;
218       time_offset = 0;
219       initial_skip = res;
220       if (res)
221         {
222           if (res >= line_bytes)
223             {
224               nrow = res / line_bytes;
225               res %= line_bytes;
226               logprintf (LOG_VERBOSE,
227                          _("\n          [ skipping %dK ]"),
228                          (int) ((nrow * line_bytes) / 1024));
229               ndot = 0;
230             }
231         }
232       logprintf (LOG_VERBOSE, "\n%5ldK", nrow * line_bytes / 1024);
233     }
234   /* Offset gets incremented by current value.  */
235   offs += res;
236   /* While offset is >= opt.dot_bytes, print dots, taking care to
237      precede every 50th dot with a status message.  */
238   for (; offs >= opt.dot_bytes; offs -= opt.dot_bytes)
239     {
240       if (!(ndot % opt.dot_spacing))
241         logputs (LOG_VERBOSE, " ");
242       any_output = 1;
243       logputs (LOG_VERBOSE, flags == SP_INIT ? "," : ".");
244       ++ndot;
245       if (ndot == opt.dots_in_line)
246         {
247           time_offset = wtimer_elapsed (timer) - last_timer_value;
248           last_timer_value += time_offset;
249
250           ndot = 0;
251           ++nrow;
252           if (expected)
253             print_percentage (nrow * line_bytes, expected);
254           logprintf (LOG_VERBOSE, " @%s",
255                      rate (line_bytes - (initial_skip % line_bytes),
256                            time_offset, 1));
257           initial_skip = 0;
258           logprintf (LOG_VERBOSE, "\n%5ldK", nrow * line_bytes / 1024);
259         }
260     }
261   /* Reenable flushing.  */
262   opt.no_flush = 0;
263   if (any_output)
264     /* Force flush.  */
265     logflush ();
266   return any_output;
267 }
268 \f
269 /* Print out the appropriate download rate.  Appropriate means that if
270    rate is > 1024 bytes per second, kilobytes are used, and if rate >
271    1024 * 1024 bps, megabytes are used.
272
273    If PAD is non-zero, strings will be padded to the width of 7
274    characters (xxxx.xx).  */
275 char *
276 rate (long bytes, long msecs, int pad)
277 {
278   static char res[15];
279   double dlrate;
280
281   if (msecs == 0)
282     /* If elapsed time is 0, it means we're under the granularity of
283        the timer.  This often happens on systems that use time() for
284        the timer.  */
285     msecs = wtimer_granularity ();
286
287   dlrate = (double)1000 * bytes / msecs;
288   if (dlrate < 1024.0)
289     sprintf (res, pad ? "%7.2f B/s" : "%.2f B/s", dlrate);
290   else if (dlrate < 1024.0 * 1024.0)
291     sprintf (res, pad ? "%7.2f KB/s" : "%.2f KB/s", dlrate / 1024.0);
292   else if (dlrate < 1024.0 * 1024.0 * 1024.0)
293     sprintf (res, pad ? "%7.2f MB/s" : "%.2f MB/s", dlrate / (1024.0 * 1024.0));
294   else
295     /* Maybe someone will need this one day.  More realistically, it
296        will get tickled by buggy timers. */
297     sprintf (res, pad ? "%7.2f GB/s" : "%.2f GB/s",
298              dlrate / (1024.0 * 1024.0 * 1024.0));
299
300   return res;
301 }
302 \f
303 #define USE_PROXY_P(u) (opt.use_proxy && getproxy((u)->scheme)          \
304                         && no_proxy_match((u)->host,                    \
305                                           (const char **)opt.no_proxy))
306
307 /* Retrieve the given URL.  Decides which loop to call -- HTTP(S), FTP,
308    or simply copy it with file:// (#### the latter not yet
309    implemented!).  */
310 uerr_t
311 retrieve_url (const char *origurl, char **file, char **newloc,
312               const char *refurl, int *dt)
313 {
314   uerr_t result;
315   char *url;
316   int location_changed, dummy;
317   int local_use_proxy;
318   char *mynewloc, *proxy;
319   struct urlinfo *u;
320   struct hash_table *redirections = NULL;
321
322   /* If dt is NULL, just ignore it.  */
323   if (!dt)
324     dt = &dummy;
325   url = xstrdup (origurl);
326   if (newloc)
327     *newloc = NULL;
328   if (file)
329     *file = NULL;
330
331   u = newurl ();
332   /* Parse the URL. */
333   result = parseurl (url, u, 0);
334   if (result != URLOK)
335     {
336       logprintf (LOG_NOTQUIET, "%s: %s.\n", url, uerrmsg (result));
337       freeurl (u, 1);
338       if (redirections)
339         string_set_free (redirections);
340       xfree (url);
341       return result;
342     }
343
344  redirected:
345
346   /* Set the referer.  */
347   if (refurl)
348     u->referer = xstrdup (refurl);
349   else
350     {
351       if (opt.referer)
352         u->referer = xstrdup (opt.referer);
353       else
354         u->referer = NULL;
355     }
356
357   local_use_proxy = USE_PROXY_P (u);
358   if (local_use_proxy)
359     {
360       struct urlinfo *pu = newurl ();
361
362       /* Copy the original URL to new location.  */
363       memcpy (pu, u, sizeof (*u));
364       pu->proxy = NULL; /* A minor correction :) */
365       /* Initialize u to nil.  */
366       memset (u, 0, sizeof (*u));
367       u->proxy = pu;
368       /* Get the appropriate proxy server, appropriate for the
369          current scheme.  */
370       proxy = getproxy (pu->scheme);
371       if (!proxy)
372         {
373           logputs (LOG_NOTQUIET, _("Could not find proxy host.\n"));
374           freeurl (u, 1);
375           if (redirections)
376             string_set_free (redirections);
377           xfree (url);
378           return PROXERR;
379         }
380       /* Parse the proxy URL.  */
381       result = parseurl (proxy, u, 0);
382       if (result != URLOK || u->scheme != SCHEME_HTTP)
383         {
384           if (u->scheme == SCHEME_HTTP)
385             logprintf (LOG_NOTQUIET, "Proxy %s: %s.\n", proxy, uerrmsg(result));
386           else
387             logprintf (LOG_NOTQUIET, _("Proxy %s: Must be HTTP.\n"), proxy);
388           freeurl (u, 1);
389           if (redirections)
390             string_set_free (redirections);
391           xfree (url);
392           return PROXERR;
393         }
394       u->scheme = SCHEME_HTTP;
395     }
396
397   mynewloc = NULL;
398
399   if (u->scheme == SCHEME_HTTP
400 #ifdef HAVE_SSL
401       || u->scheme == SCHEME_HTTPS
402 #endif
403       )
404     result = http_loop (u, &mynewloc, dt);
405   else if (u->scheme == SCHEME_FTP)
406     {
407       /* If this is a redirection, we must not allow recursive FTP
408          retrieval, so we save recursion to oldrec, and restore it
409          later.  */
410       int oldrec = opt.recursive;
411       if (redirections)
412         opt.recursive = 0;
413       result = ftp_loop (u, dt);
414       opt.recursive = oldrec;
415       /* There is a possibility of having HTTP being redirected to
416          FTP.  In these cases we must decide whether the text is HTML
417          according to the suffix.  The HTML suffixes are `.html' and
418          `.htm', case-insensitive.
419
420          #### All of this is, of course, crap.  These types should be
421          determined through mailcap.  */
422       if (redirections && u->local && (u->scheme == SCHEME_FTP))
423         {
424           char *suf = suffix (u->local);
425           if (suf && (!strcasecmp (suf, "html") || !strcasecmp (suf, "htm")))
426             *dt |= TEXTHTML;
427           FREE_MAYBE (suf);
428         }
429     }
430   location_changed = (result == NEWLOCATION);
431   if (location_changed)
432     {
433       char *construced_newloc;
434       uerr_t newloc_result;
435       struct urlinfo *newloc_struct;
436
437       assert (mynewloc != NULL);
438
439       /* The HTTP specs only allow absolute URLs to appear in
440          redirects, but a ton of boneheaded webservers and CGIs out
441          there break the rules and use relative URLs, and popular
442          browsers are lenient about this, so wget should be too. */
443       construced_newloc = uri_merge (url, mynewloc);
444       xfree (mynewloc);
445       mynewloc = construced_newloc;
446
447       /* Now, see if this new location makes sense. */
448       newloc_struct = newurl ();
449       newloc_result = parseurl (mynewloc, newloc_struct, 1);
450       if (newloc_result != URLOK)
451         {
452           logprintf (LOG_NOTQUIET, "%s: %s.\n", mynewloc, uerrmsg (newloc_result));
453           freeurl (newloc_struct, 1);
454           freeurl (u, 1);
455           if (redirections)
456             string_set_free (redirections);
457           xfree (url);
458           xfree (mynewloc);
459           return result;
460         }
461
462       /* Now mynewloc will become newloc_struct->url, because if the
463          Location contained relative paths like .././something, we
464          don't want that propagating as url.  */
465       xfree (mynewloc);
466       mynewloc = xstrdup (newloc_struct->url);
467
468       if (!redirections)
469         {
470           redirections = make_string_hash_table (0);
471           /* Add current URL immediately so we can detect it as soon
472              as possible in case of a cycle. */
473           string_set_add (redirections, u->url);
474         }
475
476       /* The new location is OK.  Let's check for redirection cycle by
477          peeking through the history of redirections. */
478       if (string_set_contains (redirections, newloc_struct->url))
479         {
480           logprintf (LOG_NOTQUIET, _("%s: Redirection cycle detected.\n"),
481                      mynewloc);
482           freeurl (newloc_struct, 1);
483           freeurl (u, 1);
484           if (redirections)
485             string_set_free (redirections);
486           xfree (url);
487           xfree (mynewloc);
488           return WRONGCODE;
489         }
490       string_set_add (redirections, newloc_struct->url);
491
492       xfree (url);
493       url = mynewloc;
494       freeurl (u, 1);
495       u = newloc_struct;
496       goto redirected;
497     }
498
499   if (u->local)
500     {
501       if (*dt & RETROKF)
502         {
503           register_download (url, u->local);
504           if (*dt & TEXTHTML)
505             register_html (url, u->local);
506         }
507     }
508
509   if (file)
510     {
511       if (u->local)
512         *file = xstrdup (u->local);
513       else
514         *file = NULL;
515     }
516   freeurl (u, 1);
517   if (redirections)
518     string_set_free (redirections);
519
520   if (newloc)
521     *newloc = url;
522   else
523     xfree (url);
524
525   ++global_download_count;
526
527   return result;
528 }
529
530 /* Find the URLs in the file and call retrieve_url() for each of
531    them.  If HTML is non-zero, treat the file as HTML, and construct
532    the URLs accordingly.
533
534    If opt.recursive is set, call recursive_retrieve() for each file.  */
535 uerr_t
536 retrieve_from_file (const char *file, int html, int *count)
537 {
538   uerr_t status;
539   urlpos *url_list, *cur_url;
540
541   url_list = (html ? get_urls_html (file, NULL, FALSE, NULL)
542               : get_urls_file (file));
543   status = RETROK;             /* Suppose everything is OK.  */
544   *count = 0;                  /* Reset the URL count.  */
545   recursive_reset ();
546   for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count)
547     {
548       char *filename, *new_file;
549       int dt;
550
551       if (downloaded_exceeds_quota ())
552         {
553           status = QUOTEXC;
554           break;
555         }
556       status = retrieve_url (cur_url->url, &filename, &new_file, NULL, &dt);
557       if (opt.recursive && status == RETROK && (dt & TEXTHTML))
558         status = recursive_retrieve (filename, new_file ? new_file
559                                                         : cur_url->url);
560
561       if (filename && opt.delete_after && file_exists_p (filename))
562         {
563           DEBUGP (("Removing file due to --delete-after in"
564                    " retrieve_from_file():\n"));
565           logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
566           if (unlink (filename))
567             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
568           dt &= ~RETROKF;
569         }
570
571       FREE_MAYBE (new_file);
572       FREE_MAYBE (filename);
573     }
574
575   /* Free the linked list of URL-s.  */
576   free_urlpos (url_list);
577
578   return status;
579 }
580
581 /* Print `giving up', or `retrying', depending on the impending
582    action.  N1 and N2 are the attempt number and the attempt limit.  */
583 void
584 printwhat (int n1, int n2)
585 {
586   logputs (LOG_VERBOSE, (n1 == n2) ? _("Giving up.\n\n") : _("Retrying.\n\n"));
587 }
588
589 /* Increment opt.downloaded by BY_HOW_MUCH.  If an overflow occurs,
590    set opt.downloaded_overflow to 1. */
591 void
592 downloaded_increase (unsigned long by_how_much)
593 {
594   VERY_LONG_TYPE old;
595   if (opt.downloaded_overflow)
596     return;
597   old = opt.downloaded;
598   opt.downloaded += by_how_much;
599   if (opt.downloaded < old)     /* carry flag, where are you when I
600                                    need you? */
601     {
602       /* Overflow. */
603       opt.downloaded_overflow = 1;
604       opt.downloaded = ~((VERY_LONG_TYPE)0);
605     }
606 }
607
608 /* Return non-zero if the downloaded amount of bytes exceeds the
609    desired quota.  If quota is not set or if the amount overflowed, 0
610    is returned. */
611 int
612 downloaded_exceeds_quota (void)
613 {
614   if (!opt.quota)
615     return 0;
616   if (opt.downloaded_overflow)
617     /* We don't really know.  (Wildly) assume not. */
618     return 0;
619
620   return opt.downloaded > opt.quota;
621 }
622
623 /* If opt.wait or opt.waitretry are specified, and if certain
624    conditions are met, sleep the appropriate number of seconds.  See
625    the documentation of --wait and --waitretry for more information.
626
627    COUNT is the count of current retrieval, beginning with 1. */
628
629 void
630 sleep_between_retrievals (int count)
631 {
632   static int first_retrieval = 1;
633
634   if (!first_retrieval && (opt.wait || opt.waitretry))
635     {
636       if (opt.waitretry && count > 1)
637         {
638           /* If opt.waitretry is specified and this is a retry, wait
639              for COUNT-1 number of seconds, or for opt.waitretry
640              seconds.  */
641           if (count <= opt.waitretry)
642             sleep (count - 1);
643           else
644             sleep (opt.waitretry);
645         }
646       else if (opt.wait)
647         /* Otherwise, check if opt.wait is specified.  If so, sleep.  */
648         sleep (opt.wait);
649     }
650   if (first_retrieval)
651     first_retrieval = 0;
652 }