]> sjero.net Git - wget/blobdiff - src/convert.c
[svn] Avoid unneeded initialization of local var.
[wget] / src / convert.c
index b1999560c13d2df44d31e812a6d67fd9812bc58b..0a3f6bd0ef587b213af99eb72665a8956b057ce1 100644 (file)
@@ -166,7 +166,8 @@ convert_all_links (void)
       free_urlpos (urls);
     }
 
-  msecs = wtimer_elapsed (timer);
+  wtimer_update (timer);
+  msecs = wtimer_read (timer);
   wtimer_delete (timer);
   logprintf (LOG_VERBOSE, _("Converted %d files in %.2f seconds.\n"),
             file_count, (double)msecs / 1000);
@@ -201,7 +202,7 @@ convert_links (const char *file, struct urlpos *links)
        any URL needs to be converted in the first place.  If not, just
        leave the file alone.  */
     int dry_count = 0;
-    struct urlpos *dry = links;
+    struct urlpos *dry;
     for (dry = links; dry; dry = dry->next)
       if (dry->convert != CO_NOCONVERT)
        ++dry_count;
@@ -327,58 +328,67 @@ convert_links (const char *file, struct urlpos *links)
   logprintf (LOG_VERBOSE, "%d-%d\n", to_file_count, to_url_count);
 }
 
-/* Construct and return a malloced copy of the relative link from two
-   pieces of information: local name S1 of the referring file and
-   local name S2 of the referred file.
+/* Construct and return a link that points from BASEFILE to LINKFILE.
+   Both files should be local file names, BASEFILE of the referrering
+   file, and LINKFILE of the referred file.
 
-   So, if S1 is "jagor.srce.hr/index.html" and S2 is
-   "jagor.srce.hr/images/news.gif", the function will return
-   "images/news.gif".
+   Examples:
 
-   Alternately, if S1 is "fly.cc.fer.hr/ioccc/index.html", and S2 is
-   "fly.cc.fer.hr/images/fly.gif", the function will return
-   "../images/fly.gif".
+   cr("foo", "bar")         -> "bar"
+   cr("A/foo", "A/bar")     -> "bar"
+   cr("A/foo", "A/B/bar")   -> "B/bar"
+   cr("A/X/foo", "A/Y/bar") -> "../Y/bar"
+   cr("X/", "Y/bar")        -> "../Y/bar" (trailing slash does matter in BASE)
+
+   Both files should be absolute or relative, otherwise strange
+   results might ensue.  The function makes no special efforts to
+   handle "." and ".." in links, so make sure they're not there
+   (e.g. using path_simplify).  */
 
-   Caveats: S1 should not begin with `/', unless S2 also begins with
-   '/'.  S1 should not contain things like ".." and such --
-   construct_relative ("fly/ioccc/../index.html",
-   "fly/images/fly.gif") will fail.  (A workaround is to call
-   something like path_simplify() on S1).  */
 static char *
-construct_relative (const char *s1, const char *s2)
+construct_relative (const char *basefile, const char *linkfile)
 {
-  int i, cnt, sepdirs1;
-  char *res;
-
-  if (*s2 == '/')
-    return xstrdup (s2);
-  /* S1 should *not* be absolute, if S2 wasn't.  */
-  assert (*s1 != '/');
-  i = cnt = 0;
-  /* Skip the directories common to both strings.  */
-  while (1)
+  char *link;
+  int basedirs;
+  const char *b, *l;
+  int i, start;
+
+  /* First, skip the initial directory components common to both
+     files.  */
+  start = 0;
+  for (b = basefile, l = linkfile; *b == *l && *b != '\0'; ++b, ++l)
     {
-      while (s1[i] && s2[i]
-            && (s1[i] == s2[i])
-            && (s1[i] != '/')
-            && (s2[i] != '/'))
-       ++i;
-      if (s1[i] == '/' && s2[i] == '/')
-       cnt = ++i;
-      else
-       break;
+      if (*b == '/')
+       start = (b - basefile) + 1;
+    }
+  basefile += start;
+  linkfile += start;
+
+  /* With common directories out of the way, the situation we have is
+     as follows:
+         b - b1/b2/[...]/bfile
+         l - l1/l2/[...]/lfile
+
+     The link we're constructing needs to be:
+       lnk - ../../l1/l2/[...]/lfile
+
+     Where the number of ".."'s equals the number of bN directory
+     components in B.  */
+
+  /* Count the directory components in B. */
+  basedirs = 0;
+  for (b = basefile; *b; b++)
+    {
+      if (*b == '/')
+       ++basedirs;
     }
-  for (sepdirs1 = 0; s1[i]; i++)
-    if (s1[i] == '/')
-      ++sepdirs1;
-  /* Now, construct the file as of:
-     - ../ repeated sepdirs1 time
-     - all the non-mutual directories of S2.  */
-  res = (char *)xmalloc (3 * sepdirs1 + strlen (s2 + cnt) + 1);
-  for (i = 0; i < sepdirs1; i++)
-    memcpy (res + 3 * i, "../", 3);
-  strcpy (res + 3 * i, s2 + cnt);
-  return res;
+
+  /* Construct LINK as explained above. */
+  link = (char *)xmalloc (3 * basedirs + strlen (linkfile) + 1);
+  for (i = 0; i < basedirs; i++)
+    memcpy (link + 3 * i, "../", 3);
+  strcpy (link + 3 * i, linkfile);
+  return link;
 }
 
 static void
@@ -392,7 +402,7 @@ write_backup_file (const char *file, downloaded_file_t downloaded_file_return)
   /* Construct the backup filename as the original name plus ".orig". */
   size_t         filename_len = strlen(file);
   char*          filename_plus_orig_suffix;
-  boolean        already_wrote_backup_file = FALSE;
+  int            already_wrote_backup_file = 0;
   slist*         converted_file_ptr;
   static slist*  converted_files = NULL;
 
@@ -426,7 +436,7 @@ write_backup_file (const char *file, downloaded_file_t downloaded_file_return)
   while (converted_file_ptr != NULL)
     if (strcmp(converted_file_ptr->string, file) == 0)
       {
-       already_wrote_backup_file = TRUE;
+       already_wrote_backup_file = 1;
        break;
       }
     else
@@ -454,10 +464,10 @@ write_backup_file (const char *file, downloaded_file_t downloaded_file_return)
          because convert_file() is called from convert_all_links at
          the end of the retrieval with a freshly built new urlpos
          list.
-        -- Hrvoje Niksic <hniksic@arsdigita.com>
+        -- Hrvoje Niksic <hniksic@xemacs.org>
       */
-      converted_file_ptr = xmalloc(sizeof(*converted_file_ptr));
-      converted_file_ptr->string = xstrdup(file);  /* die on out-of-mem. */
+      converted_file_ptr = xmalloc (sizeof (*converted_file_ptr));
+      converted_file_ptr->string = xstrdup (file);
       converted_file_ptr->next = converted_files;
       converted_files = converted_file_ptr;
     }
@@ -566,49 +576,52 @@ find_fragment (const char *beg, int size, const char **bp, const char **ep)
    "index.html%3Ffoo=bar" would break local browsing, as the latter
    isn't even recognized as an HTML file!  However, converting
    "index.html?foo=bar.html" to "index.html%3Ffoo=bar.html" should be
-   safe for both local and HTTP-served browsing.  */
+   safe for both local and HTTP-served browsing.
+
+   We always quote "#" as "%23" and "%" as "%25" because those
+   characters have special meanings in URLs.  */
 
 static char *
 local_quote_string (const char *file)
 {
-  const char *file_sans_qmark;
-  int qm;
+  const char *from;
+  char *newname, *to;
 
-  if (!opt.html_extension)
+  char *any = strpbrk (file, "?#%");
+  if (!any)
     return html_quote_string (file);
 
-  qm = count_char (file, '?');
-
-  if (qm)
-    {
-      const char *from = file;
-      char *to, *newname;
-
-      /* qm * 2 because we replace each question mark with "%3F",
-        i.e. replace one char with three, hence two more.  */
-      int fsqlen = strlen (file) + qm * 2;
-
-      to = newname = (char *)alloca (fsqlen + 1);
-      for (; *from; from++)
-       {
-         if (*from != '?')
-           *to++ = *from;
-         else
-           {
-             *to++ = '%';
-             *to++ = '3';
-             *to++ = 'F';
-           }
-       }
-      assert (to - newname == fsqlen);
-      *to = '\0';
-
-      file_sans_qmark = newname;
-    }
-  else
-    file_sans_qmark = file;
+  /* Allocate space assuming the worst-case scenario, each character
+     having to be quoted.  */
+  to = newname = (char *)alloca (3 * strlen (file) + 1);
+  for (from = file; *from; from++)
+    switch (*from)
+      {
+      case '%':
+       *to++ = '%';
+       *to++ = '2';
+       *to++ = '5';
+       break;
+      case '#':
+       *to++ = '%';
+       *to++ = '2';
+       *to++ = '3';
+       break;
+      case '?':
+       if (opt.html_extension)
+         {
+           *to++ = '%';
+           *to++ = '3';
+           *to++ = 'F';
+           break;
+         }
+       /* fallthrough */
+      default:
+       *to++ = *from;
+      }
+  *to = '\0';
 
-  return html_quote_string (file_sans_qmark);
+  return html_quote_string (newname);
 }
 \f
 /* Book-keeping code for dl_file_url_map, dl_url_file_map,