]> sjero.net Git - wget/blobdiff - src/html-url.c
[svn] Doc fix.
[wget] / src / html-url.c
index 6ab54a9f992761528e7aa6cf1031a8375a2669b3..cac61ae3af0ad6b26a37b64ad14f7a5ee2df1e41 100644 (file)
@@ -1,5 +1,5 @@
 /* Collect URLs from HTML source.
-   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -284,12 +284,9 @@ struct collect_urls_closure {
   char *text;                  /* HTML text. */
   char *base;                  /* Base URI of the document, possibly
                                   changed through <base href=...>. */
-  urlpos *head, *tail;         /* List of URLs */
+  struct urlpos *head, *tail;  /* List of URLs */
   const char *parent_base;     /* Base of the current document. */
   const char *document_file;   /* File name of this document. */
-  int dash_p_leaf_HTML;                /* Whether -p is specified, and this
-                                   document is the "leaf" node of the
-                                   HTML tree. */
   int nofollow;                        /* whether NOFOLLOW was specified in a
                                    <meta name=robots> tag. */
 };
@@ -297,63 +294,71 @@ struct collect_urls_closure {
 /* Resolve LINK_URI and append it to closure->tail.  TAG and ATTRID
    are the necessary context to store the position and size.  */
 
-static void
+static struct urlpos *
 handle_link (struct collect_urls_closure *closure, const char *link_uri,
             struct taginfo *tag, int attrid)
 {
-  int no_scheme = !url_has_scheme (link_uri);
-  urlpos *newel;
-
+  int link_has_scheme = url_has_scheme (link_uri);
+  struct urlpos *newel;
   const char *base = closure->base ? closure->base : closure->parent_base;
-  char *complete_uri;
-
-  char *fragment = strrchr (link_uri, '#');
-
-  if (fragment)
-    {
-      /* Nullify the fragment identifier, i.e. everything after the
-         last occurrence of `#', inclusive.  This copying is
-         relatively inefficient, but it doesn't matter because
-         fragment identifiers don't come up all that often.  */
-      int hashlen = fragment - link_uri;
-      char *p = alloca (hashlen + 1);
-      memcpy (p, link_uri, hashlen);
-      p[hashlen] = '\0';
-      link_uri = p;
-    }
+  struct url *url;
 
   if (!base)
     {
-      if (no_scheme)
+      DEBUGP (("%s: no base, merge will use \"%s\".\n",
+              closure->document_file, link_uri));
+
+      if (!link_has_scheme)
        {
          /* We have no base, and the link does not have a host
             attached to it.  Nothing we can do.  */
          /* #### Should we print a warning here?  Wget 1.5.x used to.  */
-         return;
+         return NULL;
+       }
+
+      url = url_parse (link_uri, NULL);
+      if (!url)
+       {
+         DEBUGP (("%s: link \"%s\" doesn't parse.\n",
+                  closure->document_file, link_uri));
+         return NULL;
        }
-      else
-       complete_uri = xstrdup (link_uri);
     }
   else
-    complete_uri = uri_merge (base, link_uri);
+    {
+      /* Merge BASE with LINK_URI, but also make sure the result is
+        canonicalized, i.e. that "../" have been resolved.
+        (parse_url will do that for us.) */
+
+      char *complete_uri = uri_merge (base, link_uri);
+
+      DEBUGP (("%s: merge(\"%s\", \"%s\") -> %s\n",
+              closure->document_file, base, link_uri, complete_uri));
 
-  DEBUGP (("%s: merge(\"%s\", \"%s\") -> %s\n",
-          closure->document_file, base ? base : "(null)",
-          link_uri, complete_uri));
+      url = url_parse (complete_uri, NULL);
+      if (!url)
+       {
+         DEBUGP (("%s: merged link \"%s\" doesn't parse.\n",
+                  closure->document_file, complete_uri));
+         xfree (complete_uri);
+         return NULL;
+       }
+      xfree (complete_uri);
+    }
 
-  newel = (urlpos *)xmalloc (sizeof (urlpos));
+  newel = (struct urlpos *)xmalloc (sizeof (struct urlpos));
 
   memset (newel, 0, sizeof (*newel));
   newel->next = NULL;
-  newel->url = complete_uri;
+  newel->url = url;
   newel->pos = tag->attrs[attrid].value_raw_beginning - closure->text;
   newel->size = tag->attrs[attrid].value_raw_size;
 
   /* A URL is relative if the host is not named, and the name does not
      start with `/'.  */
-  if (no_scheme && *link_uri != '/')
+  if (!link_has_scheme && *link_uri != '/')
     newel->link_relative_p = 1;
-  else if (!no_scheme)
+  else if (link_has_scheme)
     newel->link_complete_p = 1;
 
   if (closure->tail)
@@ -363,6 +368,8 @@ handle_link (struct collect_urls_closure *closure, const char *link_uri,
     }
   else
     closure->tail = closure->head = newel;
+
+  return newel;
 }
 
 /* Examine name and attributes of TAG and take appropriate action.
@@ -403,20 +410,18 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
            for (i = first; (i < size && url_tag_attr_map[i].tagid == tagid);
                 i++)
              {
-               char *attr_value;
-               if (closure->dash_p_leaf_HTML
-                   && (url_tag_attr_map[i].flags & AF_EXTERNAL))
-                 /* If we're at a -p leaf node, we don't want to retrieve
-                    links to references we know are external to this document,
-                    such as <a href=...>.  */
-                 continue;
-
-               if (!strcasecmp (tag->attrs[id].name,
-                                url_tag_attr_map[i].attr_name))
+               if (0 == strcasecmp (tag->attrs[id].name,
+                                    url_tag_attr_map[i].attr_name))
                  {
-                   attr_value = tag->attrs[id].value;
+                   char *attr_value = tag->attrs[id].value;
                    if (attr_value)
-                     handle_link (closure, attr_value, tag, id);
+                     {
+                       struct urlpos *entry;
+                       entry = handle_link (closure, attr_value, tag, id);
+                       if (entry != NULL
+                           && !(url_tag_attr_map[i].flags & AF_EXTERNAL))
+                         entry->link_inline_p = 1;
+                     }
                  }
              }
          }
@@ -427,9 +432,18 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
        {
        case TAG_BASE:
          {
-           char *newbase = find_attr (tag, "href", NULL);
+           struct urlpos *base_urlpos;
+           int id;
+           char *newbase = find_attr (tag, "href", &id);
            if (!newbase)
              break;
+
+           base_urlpos = handle_link (closure, newbase, tag, id);
+           if (!base_urlpos)
+             break;
+           base_urlpos->ignore_when_downloading = 1;
+           base_urlpos->link_base_p = 1;
+
            if (closure->base)
              xfree (closure->base);
            if (closure->parent_base)
@@ -441,24 +455,20 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
        case TAG_LINK:
          {
            int id;
-           char *rel  = find_attr (tag, "rel", NULL);
            char *href = find_attr (tag, "href", &id);
+
+           /* All <link href="..."> link references are external,
+              except for <link rel="stylesheet" href="...">.  */
            if (href)
              {
-               /* In the normal case, all <link href=...> tags are
-                  fair game.
-
-                  In the special case of when -p is active, however,
-                  and we're at a leaf node (relative to the -l
-                  max. depth) in the HTML document tree, the only
-                  <LINK> tag we'll follow is a <LINK REL=
-                  "stylesheet">, as it'll be necessary for displaying
-                  this document properly.  We won't follow other
-                  <LINK> tags, like <LINK REL="home">, for instance,
-                  as they refer to external documents.  */
-               if (!closure->dash_p_leaf_HTML
-                   || (rel && !strcasecmp (rel, "stylesheet")))
-                 handle_link (closure, href, tag, id);
+               struct urlpos *entry;
+               entry = handle_link (closure, href, tag, id);
+               if (entry != NULL)
+                 {
+                   char *rel  = find_attr (tag, "rel", NULL);
+                   if (rel && 0 == strcasecmp (rel, "stylesheet"))
+                     entry->link_inline_p = 1;
+                 }
              }
          }
          break;
@@ -472,18 +482,21 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
             So we just need to skip past the "NUMBER; URL=" garbage
             to get to the URL.  */
          {
-           int id;
            char *name = find_attr (tag, "name", NULL);
-           char *http_equiv = find_attr (tag, "http-equiv", &id);
+           char *http_equiv = find_attr (tag, "http-equiv", NULL);
            if (http_equiv && !strcasecmp (http_equiv, "refresh"))
              {
-               char *refresh = find_attr (tag, "content", NULL);
-               char *p = refresh;
-               int offset;
-               while (ISDIGIT (*p))
-                 ++p;
+               struct urlpos *entry;
+
+               int id;
+               char *p, *refresh = find_attr (tag, "content", &id);
+               int timeout = 0;
+
+               for (p = refresh; ISDIGIT (*p); p++)
+                 timeout = 10 * timeout + *p - '0';
                if (*p++ != ';')
                  return;
+
                while (ISSPACE (*p))
                  ++p;
                if (!(TOUPPER (*p) == 'U'
@@ -494,10 +507,13 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
                p += 4;
                while (ISSPACE (*p))
                  ++p;
-               offset = p - refresh;
-               tag->attrs[id].value_raw_beginning += offset;
-               tag->attrs[id].value_raw_size -= offset;
-               handle_link (closure, p, tag, id);
+
+               entry = handle_link (closure, p, tag, id);
+               if (entry)
+                 {
+                   entry->link_refresh_p = 1;
+                   entry->refresh_timeout = timeout;
+                 }
              }
            else if (name && !strcasecmp (name, "robots"))
              {
@@ -537,14 +553,10 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
 }
 
 /* Analyze HTML tags FILE and construct a list of URLs referenced from
-   it.  It merges relative links in FILE with THIS_URL.  It is aware
-   of <base href=...> and does the right thing.
-
-   If dash_p_leaf_HTML is non-zero, only the elements needed to render
-   FILE ("non-external" links) will be returned.  */
-urlpos *
-get_urls_html (const char *file, const char *this_url, int dash_p_leaf_HTML,
-              int *meta_disallow_follow)
+   it.  It merges relative links in FILE with URL.  It is aware of
+   <base href=...> and does the right thing.  */
+struct urlpos *
+get_urls_html (const char *file, const char *url, int *meta_disallow_follow)
 {
   struct file_memory *fm;
   struct collect_urls_closure closure;
@@ -561,9 +573,8 @@ get_urls_html (const char *file, const char *this_url, int dash_p_leaf_HTML,
   closure.text = fm->content;
   closure.head = closure.tail = NULL;
   closure.base = NULL;
-  closure.parent_base = this_url ? this_url : opt.base_href;
+  closure.parent_base = url ? url : opt.base_href;
   closure.document_file = file;
-  closure.dash_p_leaf_HTML = dash_p_leaf_HTML;
   closure.nofollow = 0;
 
   if (!interesting_tags)