Stephen Hewitt <[EMAIL PROTECTED]> writes:
> Attempting to mirror a particular web site, with wget 1.8.1, I got
> many nested directories like .../images/images/images/images etc For
> example the log file ended like this:
[...]
Thanks for the detailed report and for taking the time to find the
problem. I've seen similar problems, but have never had the
inclination to find the cause; `--mirror' is especially susceptible to
this because it implies `-l0'.
> The fundamental problem in this case is that if you ask for a page
> that does not exist from www.can-online.org.uk, the server does not
> respond correctly. Instead of presenting the 404 not found, it
> serves up some default web page.
Right. And if that same web page contains the link to a non-existent
image, an infloop insues.
> Now at this point is the opportunity for wget to be more robust.
[...]
> So my suggestion is this. If wget is following an <img src="">
> address from a page, and instead of the expected [image/gif] (or
> jpeg or whatever) file type the server gives a [text/html], then
> wget should not follow any links that the text/html file contains.
I agree. I've attached a patch against the current CVS code that
should fix this problem. Could you please try it out and let me know
if it works for you?
> Perhaps you could even argue that it should report an error and not
> even save the html file,
That would be going too far. If the <img src=...> returns an HTML
page, so be it. Let the browsers cope with it as best they can; Wget
will simply not harvest the links from such a page.
2003-10-10 Hrvoje Niksic <[EMAIL PROTECTED]>
* recur.c (retrieve_tree): Don't descend into documents that are
not expected to contain HTML, regardless of their content-type.
* html-url.c (tag_url_attributes): Record which attributes are
supposed to yield HTML links that can be followed.
(tag_find_urls): Propagate that information to the caller through
struct urlpos.
Index: src/convert.h
===================================================================
RCS file: /pack/anoncvs/wget/src/convert.h,v
retrieving revision 1.1
diff -u -r1.1 convert.h
--- src/convert.h 2003/09/21 22:47:13 1.1
+++ src/convert.h 2003/10/10 14:07:41
@@ -56,11 +56,11 @@
/* Information about the original link: */
- unsigned int link_relative_p :1; /* was the link relative? */
- unsigned int link_complete_p :1; /* was the link complete (with the
- host name, etc.) */
- unsigned int link_base_p :1; /* was the link <base href=...> */
- unsigned int link_inline_p :1; /* needed to render the page. */
+ unsigned int link_relative_p :1; /* the link was relative */
+ unsigned int link_complete_p :1; /* the link was complete (had host name) */
+ unsigned int link_base_p :1; /* the url came from <base href=...> */
+ unsigned int link_inline_p :1; /* needed to render the page */
+ unsigned int link_expect_html :1; /* expected to contain HTML */
unsigned int link_refresh_p :1; /* link was received from
<meta http-equiv=refresh content=...> */
Index: src/html-url.c
===================================================================
RCS file: /pack/anoncvs/wget/src/html-url.c,v
retrieving revision 1.33
diff -u -r1.33 html-url.c
--- src/html-url.c 2003/10/10 02:46:09 1.33
+++ src/html-url.c 2003/10/10 14:07:42
@@ -121,11 +121,19 @@
/* tag_url_attributes documents which attributes of which tags contain
URLs to harvest. It is used by tag_find_urls. */
-/* Defines for the FLAGS field; currently only one flag is defined. */
+/* Defines for the FLAGS. */
-/* This tag points to an external document not necessary for rendering this
- document (i.e. it's not an inlined image, stylesheet, etc.). */
-#define TUA_EXTERNAL 1
+/* The link is "inline", i.e. needs to be retrieved for this document
+ to be correctly rendered. Inline links include inlined images,
+ stylesheets, children frames, etc. */
+#define ATTR_INLINE 1
+
+/* The link is expected to yield HTML contents. It's important not to
+ try to follow HTML obtained by following e.g. <img src="...">
+ regardless of content-type. Doing this causes infinite loops for
+ "images" that return non-404 error pages with links to the same
+ image. */
+#define ATTR_HTML 2
/* For tags handled by tag_find_urls: attributes that contain URLs to
download. */
@@ -134,26 +142,26 @@
const char *attr_name;
int flags;
} tag_url_attributes[] = {
- { TAG_A, "href", TUA_EXTERNAL },
- { TAG_APPLET, "code", 0 },
- { TAG_AREA, "href", TUA_EXTERNAL },
- { TAG_BGSOUND, "src", 0 },
- { TAG_BODY, "background", 0 },
- { TAG_EMBED, "href", TUA_EXTERNAL },
- { TAG_EMBED, "src", 0 },
- { TAG_FIG, "src", 0 },
- { TAG_FRAME, "src", 0 },
- { TAG_IFRAME, "src", 0 },
- { TAG_IMG, "href", 0 },
- { TAG_IMG, "lowsrc", 0 },
- { TAG_IMG, "src", 0 },
- { TAG_INPUT, "src", 0 },
- { TAG_LAYER, "src", 0 },
- { TAG_OVERLAY, "src", 0 },
- { TAG_SCRIPT, "src", 0 },
- { TAG_TABLE, "background", 0 },
- { TAG_TD, "background", 0 },
- { TAG_TH, "background", 0 }
+ { TAG_A, "href", ATTR_HTML },
+ { TAG_APPLET, "code", ATTR_INLINE },
+ { TAG_AREA, "href", ATTR_HTML },
+ { TAG_BGSOUND, "src", ATTR_INLINE },
+ { TAG_BODY, "background", ATTR_INLINE },
+ { TAG_EMBED, "href", ATTR_HTML },
+ { TAG_EMBED, "src", ATTR_INLINE | ATTR_HTML },
+ { TAG_FIG, "src", ATTR_INLINE },
+ { TAG_FRAME, "src", ATTR_INLINE | ATTR_HTML },
+ { TAG_IFRAME, "src", ATTR_INLINE | ATTR_HTML },
+ { TAG_IMG, "href", ATTR_INLINE },
+ { TAG_IMG, "lowsrc", ATTR_INLINE },
+ { TAG_IMG, "src", ATTR_INLINE },
+ { TAG_INPUT, "src", ATTR_INLINE },
+ { TAG_LAYER, "src", ATTR_INLINE | ATTR_HTML },
+ { TAG_OVERLAY, "src", ATTR_INLINE | ATTR_HTML },
+ { TAG_SCRIPT, "src", ATTR_INLINE },
+ { TAG_TABLE, "background", ATTR_INLINE },
+ { TAG_TD, "background", ATTR_INLINE },
+ { TAG_TH, "background", ATTR_INLINE }
};
/* The lists of interesting tags and attributes are built dynamically,
@@ -262,7 +270,7 @@
size. */
static struct urlpos *
-append_one_url (const char *link_uri, int inlinep,
+append_one_url (const char *link_uri,
struct taginfo *tag, int attrind, struct map_context *ctx)
{
int link_has_scheme = url_has_scheme (link_uri);
@@ -326,7 +334,6 @@
newel->url = url;
newel->pos = tag->attrs[attrind].value_raw_beginning - ctx->text;
newel->size = tag->attrs[attrind].value_raw_size;
- newel->link_inline_p = inlinep;
/* A URL is relative if the host is not named, and the name does not
start with `/'. */
@@ -393,8 +400,15 @@
if (0 == strcasecmp (tag->attrs[attrind].name,
tag_url_attributes[i].attr_name))
{
- int flags = tag_url_attributes[i].flags;
- append_one_url (link, !(flags & TUA_EXTERNAL), tag, attrind, ctx);
+ struct urlpos *up = append_one_url (link, tag, attrind, ctx);
+ if (up)
+ {
+ int flags = tag_url_attributes[i].flags;
+ if (flags & ATTR_INLINE)
+ up->link_inline_p = 1;
+ if (flags & ATTR_HTML)
+ up->link_expect_html = 1;
+ }
}
}
}
@@ -411,7 +425,7 @@
if (!newbase)
return;
- base_urlpos = append_one_url (newbase, 0, tag, attrind, ctx);
+ base_urlpos = append_one_url (newbase, tag, attrind, ctx);
if (!base_urlpos)
return;
base_urlpos->ignore_when_downloading = 1;
@@ -434,10 +448,9 @@
char *action = find_attr (tag, "action", &attrind);
if (action)
{
- struct urlpos *action_urlpos = append_one_url (action, 0, tag,
- attrind, ctx);
- if (action_urlpos)
- action_urlpos->ignore_when_downloading = 1;
+ struct urlpos *up = append_one_url (action, tag, attrind, ctx);
+ if (up)
+ up->ignore_when_downloading = 1;
}
}
@@ -458,11 +471,15 @@
*/
if (href)
{
- char *rel = find_attr (tag, "rel", NULL);
- int inlinep = (rel
- && (0 == strcasecmp (rel, "stylesheet")
- || 0 == strcasecmp (rel, "shortcut icon")));
- append_one_url (href, inlinep, tag, attrind, ctx);
+ struct urlpos *up = append_one_url (href, tag, attrind, ctx);
+ if (up)
+ {
+ char *rel = find_attr (tag, "rel", NULL);
+ if (rel
+ && (0 == strcasecmp (rel, "stylesheet")
+ || 0 == strcasecmp (rel, "shortcut icon")))
+ up->link_inline_p = 1;
+ }
}
}
@@ -511,7 +528,7 @@
while (ISSPACE (*p))
++p;
- entry = append_one_url (p, 0, tag, attrind, ctx);
+ entry = append_one_url (p, tag, attrind, ctx);
if (entry)
{
entry->link_refresh_p = 1;
Index: src/recur.c
===================================================================
RCS file: /pack/anoncvs/wget/src/recur.c,v
retrieving revision 1.54
diff -u -r1.54 recur.c
--- src/recur.c 2003/10/07 23:53:31 1.54
+++ src/recur.c 2003/10/10 14:07:42
@@ -6,7 +6,7 @@
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ (at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -66,10 +66,13 @@
/* Functions for maintaining the URL queue. */
struct queue_element {
- const char *url;
- const char *referer;
- int depth;
- struct queue_element *next;
+ const char *url; /* the URL to download */
+ const char *referer; /* the referring document */
+ int depth; /* the depth */
+ unsigned int html_allowed :1; /* whether the document is allowed to
+ be treated as HTML. */
+
+ struct queue_element *next; /* next element in queue */
};
struct url_queue {
@@ -102,12 +105,13 @@
static void
url_enqueue (struct url_queue *queue,
- const char *url, const char *referer, int depth)
+ const char *url, const char *referer, int depth, int html_allowed)
{
struct queue_element *qel = xmalloc (sizeof (*qel));
qel->url = url;
qel->referer = referer;
qel->depth = depth;
+ qel->html_allowed = html_allowed;
qel->next = NULL;
++queue->count;
@@ -130,7 +134,8 @@
static int
url_dequeue (struct url_queue *queue,
- const char **url, const char **referer, int *depth)
+ const char **url, const char **referer, int *depth,
+ int *html_allowed)
{
struct queue_element *qel = queue->head;
@@ -144,6 +149,7 @@
*url = qel->url;
*referer = qel->referer;
*depth = qel->depth;
+ *html_allowed = qel->html_allowed;
--queue->count;
@@ -208,14 +214,14 @@
/* Enqueue the starting URL. Use start_url_parsed->url rather than
just URL so we enqueue the canonical form of the URL. */
- url_enqueue (queue, xstrdup (start_url_parsed->url), NULL, 0);
+ url_enqueue (queue, xstrdup (start_url_parsed->url), NULL, 0, 1);
string_set_add (blacklist, start_url_parsed->url);
while (1)
{
int descend = 0;
char *url, *referer, *file = NULL;
- int depth;
+ int depth, html_allowed;
boolean dash_p_leaf_HTML = FALSE;
if (downloaded_exceeds_quota ())
@@ -227,7 +233,7 @@
if (!url_dequeue (queue,
(const char **)&url, (const char **)&referer,
- &depth))
+ &depth, &html_allowed))
break;
/* ...and download it. Note that this download is in most cases
@@ -245,7 +251,8 @@
DEBUGP (("Already downloaded \"%s\", reusing it from \"%s\".\n",
url, file));
- if (downloaded_html_set
+ if (html_allowed
+ && downloaded_html_set
&& string_set_contains (downloaded_html_set, file))
descend = 1;
}
@@ -259,7 +266,7 @@
status = retrieve_url (url, &file, &redirected, referer, &dt);
opt.recursive = oldrec;
- if (file && status == RETROK
+ if (html_allowed && file && status == RETROK
&& (dt & RETROKF) && (dt & TEXTHTML))
descend = 1;
@@ -341,7 +348,8 @@
blacklist))
{
url_enqueue (queue, xstrdup (child->url->url),
- xstrdup (url), depth + 1);
+ xstrdup (url), depth + 1,
+ child->link_expect_html);
/* We blacklist the URL we have enqueued, because we
don't want to enqueue (and hence download) the
same URL twice. */
@@ -382,8 +390,9 @@
now. */
{
char *d1, *d2;
- int d3;
- while (url_dequeue (queue, (const char **)&d1, (const char **)&d2, &d3))
+ int d3, d4;
+ while (url_dequeue (queue,
+ (const char **)&d1, (const char **)&d2, &d3, &d4))
{
xfree (d1);
FREE_MAYBE (d2);