]> sjero.net Git - wget/blobdiff - src/url.c
[svn] Rename long_to_string to number_to_string, and make it return a useful
[wget] / src / url.c
index 1ce7222a7d06e2053e0ee21987d1b9c02b04d17a..f2953c40c778aefa35e18323014e383eae9c5e47 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -54,19 +54,20 @@ struct scheme_data
 {
   char *leading_string;
   int default_port;
+  int enabled;
 };
 
 /* Supported schemes: */
 static struct scheme_data supported_schemes[] =
 {
-  { "http://",  DEFAULT_HTTP_PORT },
+  { "http://",  DEFAULT_HTTP_PORT,  1 },
 #ifdef HAVE_SSL
-  { "https://", DEFAULT_HTTPS_PORT },
+  { "https://", DEFAULT_HTTPS_PORT, 1 },
 #endif
-  { "ftp://",   DEFAULT_FTP_PORT },
+  { "ftp://",   DEFAULT_FTP_PORT,   1 },
 
   /* SCHEME_INVALID */
-  { NULL,       -1 }
+  { NULL,       -1,                 0 }
 };
 
 static char *construct_relative PARAMS ((const char *, const char *));
@@ -333,7 +334,7 @@ decide_copy_method (const char *p)
    "foo+bar"         -> "foo+bar"            (plus is reserved!)
    "foo%2b+bar"      -> "foo%2b+bar"  */
 
-char *
+static char *
 reencode_string (const char *s)
 {
   const char *p1;
@@ -420,9 +421,15 @@ url_scheme (const char *url)
   int i;
 
   for (i = 0; supported_schemes[i].leading_string; i++)
-    if (!strncasecmp (url, supported_schemes[i].leading_string,
-                     strlen (supported_schemes[i].leading_string)))
-      return (enum url_scheme)i;
+    if (0 == strncasecmp (url, supported_schemes[i].leading_string,
+                         strlen (supported_schemes[i].leading_string)))
+      {
+       if (supported_schemes[i].enabled)
+         return (enum url_scheme) i;
+       else
+         return SCHEME_INVALID;
+      }
+
   return SCHEME_INVALID;
 }
 
@@ -466,6 +473,12 @@ scheme_default_port (enum url_scheme scheme)
   return supported_schemes[scheme].default_port;
 }
 
+void
+scheme_disable (enum url_scheme scheme)
+{
+  supported_schemes[scheme].enabled = 0;
+}
+
 /* Skip the username and password, if present here.  The function
    should be called *not* with the complete URL, but with the part
    right after the scheme.
@@ -546,19 +559,17 @@ rewrite_shorthand_url (const char *url)
 
   if (*p == ':')
     {
-      const char *pp, *path;
+      const char *pp;
       char *res;
       /* If the characters after the colon and before the next slash
         or end of string are all digits, it's HTTP.  */
       int digits = 0;
       for (pp = p + 1; ISDIGIT (*pp); pp++)
        ++digits;
-      if (digits > 0
-         && (*pp == '/' || *pp == '\0'))
+      if (digits > 0 && (*pp == '/' || *pp == '\0'))
        goto http;
 
       /* Prepend "ftp://" to the entire URL... */
-      path = p + 1;
       res = xmalloc (6 + strlen (url) + 1);
       sprintf (res, "ftp://%s", url);
       /* ...and replace ':' with '/'. */
@@ -595,7 +606,7 @@ lowercase_str (char *str)
 {
   int change = 0;
   for (; *str; str++)
-    if (!ISLOWER (*str))
+    if (ISUPPER (*str))
       {
        change = 1;
        *str = TOLOWER (*str);
@@ -606,8 +617,8 @@ lowercase_str (char *str)
 static char *parse_errors[] = {
 #define PE_NO_ERROR            0
   "No error",
-#define PE_UNRECOGNIZED_SCHEME 1
-  "Unrecognized scheme",
+#define PE_UNSUPPORTED_SCHEME 1
+  "Unsupported scheme",
 #define PE_EMPTY_HOST          2
   "Empty host",
 #define PE_BAD_PORT_NUMBER     3
@@ -650,7 +661,7 @@ url_parse (const char *url, int *error)
   scheme = url_scheme (url);
   if (scheme == SCHEME_INVALID)
     {
-      SETERR (error, PE_UNRECOGNIZED_SCHEME);
+      SETERR (error, PE_UNSUPPORTED_SCHEME);
       return NULL;
     }
 
@@ -787,13 +798,11 @@ url_parse (const char *url, int *error)
   if (fragment_b)
     u->fragment = strdupdelim (fragment_b, fragment_e);
 
-
-  if (path_modified || u->fragment || host_modified)
+  if (path_modified || u->fragment || host_modified || path_b == path_e)
     {
-      /* If path_simplify modified the path, or if a fragment is
-        present, or if the original host name had caps in it, make
-        sure that u->url is equivalent to what would be printed by
-        url_string.  */
+      /* If we suspect that a transformation has rendered what
+        url_string might return different from URL_ENCODED, rebuild
+        u->url using url_string.  */
       u->url = url_string (u, 0);
 
       if (url_encoded != url)
@@ -886,7 +895,10 @@ full_path_write (const struct url *url, char *where)
 #undef FROB
 }
 
-/* Public function for getting the "full path". */
+/* Public function for getting the "full path".  E.g. if u->path is
+   "foo/bar" and u->query is "param=value", full_path will be
+   "/foo/bar?param=value". */
+
 char *
 url_full_path (const struct url *url)
 {
@@ -900,6 +912,7 @@ url_full_path (const struct url *url)
 }
 
 /* Sync u->path and u->url with u->dir and u->file. */
+
 static void
 sync_path (struct url *url)
 {
@@ -1005,13 +1018,25 @@ get_urls_file (const char *file)
        --line_end;
       if (line_end > line_beg)
        {
+         /* URL is in the [line_beg, line_end) region. */
+
          int up_error_code;
          char *url_text;
          struct urlpos *entry;
          struct url *url;
 
-         /* We must copy the URL to a zero-terminated string.  *sigh*.  */
+         /* We must copy the URL to a zero-terminated string, and we
+            can't use alloca because we're in a loop.  *sigh*.  */
          url_text = strdupdelim (line_beg, line_end);
+
+         if (opt.base_href)
+           {
+             /* Merge opt.base_href with URL. */
+             char *merged = uri_merge (opt.base_href, url_text);
+             xfree (url_text);
+             url_text = merged;
+           }
+
          url = url_parse (url_text, &up_error_code);
          if (!url)
            {
@@ -1181,7 +1206,7 @@ mkstruct (const struct url *u)
        {
          int len = strlen (dirpref);
          dirpref[len] = ':';
-         long_to_string (dirpref + len + 1, u->port);
+         number_to_string (dirpref + len + 1, u->port);
        }
     }
   else                         /* not add_hostdir */
@@ -1378,7 +1403,7 @@ find_last_char (const char *b, const char *e, char c)
    The parameters LINKLENGTH is useful if LINK is not zero-terminated.
    See uri_merge for a gentler interface to this functionality.
 
-   #### This function should handle `./' and `../' so that the evil
+   Perhaps this function should handle `./' and `../' so that the evil
    path_simplify can go.  */
 static char *
 uri_merge_1 (const char *base, const char *link, int linklength, int no_scheme)
@@ -1629,8 +1654,7 @@ url_string (const struct url *url, int hide_password)
   if (url->port != scheme_port)
     {
       *p++ = ':';
-      long_to_string (p, url->port);
-      p += strlen (p);
+      p = number_to_string (p, url->port);
     }
 
   full_path_write (url, p);
@@ -1698,7 +1722,10 @@ no_proxy_match (const char *host, const char **no_proxy)
 }
 \f
 static void write_backup_file PARAMS ((const char *, downloaded_file_t));
-static const char *replace_attr PARAMS ((const char *, int, FILE *, const char *));
+static const char *replace_attr PARAMS ((const char *, int, FILE *,
+                                        const char *));
+static const char *replace_attr_refresh_hack PARAMS ((const char *, int, FILE *,
+                                                     const char *, int));
 static char *local_quote_string PARAMS ((const char *));
 
 /* Change the links in one HTML file.  LINKS is a list of links in the
@@ -1797,7 +1824,13 @@ convert_links (const char *file, struct urlpos *links)
          {
            char *newname = construct_relative (file, link->local_name);
            char *quoted_newname = local_quote_string (newname);
-           p = replace_attr (p, link->size, fp, quoted_newname);
+
+           if (!link->link_refresh_p)
+             p = replace_attr (p, link->size, fp, quoted_newname);
+           else
+             p = replace_attr_refresh_hack (p, link->size, fp, quoted_newname,
+                                            link->refresh_timeout);
+
            DEBUGP (("TO_RELATIVE: %s to %s at position %d in %s.\n",
                     link->url->url, newname, link->pos, file));
            xfree (newname);
@@ -1810,7 +1843,13 @@ convert_links (const char *file, struct urlpos *links)
          {
            char *newlink = link->url->url;
            char *quoted_newlink = html_quote_string (newlink);
-           p = replace_attr (p, link->size, fp, quoted_newlink);
+
+           if (!link->link_refresh_p)
+             p = replace_attr (p, link->size, fp, quoted_newlink);
+           else
+             p = replace_attr_refresh_hack (p, link->size, fp, quoted_newlink,
+                                            link->refresh_timeout);
+
            DEBUGP (("TO_COMPLETE: <something> to %s at position %d in %s.\n",
                     newlink, link->pos, file));
            xfree (quoted_newlink);
@@ -1833,8 +1872,7 @@ convert_links (const char *file, struct urlpos *links)
   fclose (fp);
   read_file_free (fm);
 
-  logprintf (LOG_VERBOSE,
-            _("%d-%d\n"), to_file_count, to_url_count);
+  logprintf (LOG_VERBOSE, "%d-%d\n", to_file_count, to_url_count);
 }
 
 /* Construct and return a malloced copy of the relative link from two
@@ -2015,6 +2053,24 @@ replace_attr (const char *p, int size, FILE *fp, const char *new_text)
   return p;
 }
 
+/* The same as REPLACE_ATTR, but used when replacing
+   <meta http-equiv=refresh content="new_text"> because we need to
+   append "timeout_value; URL=" before the next_text.  */
+
+static const char *
+replace_attr_refresh_hack (const char *p, int size, FILE *fp,
+                          const char *new_text, int timeout)
+{
+  /* "0; URL=..." */
+  char *new_with_timeout = (char *)alloca (numdigit (timeout)
+                                          + 6 /* "; URL=" */
+                                          + strlen (new_text)
+                                          + 1);
+  sprintf (new_with_timeout, "%d; URL=%s", timeout, new_text);
+
+  return replace_attr (p, size, fp, new_with_timeout);
+}
+
 /* Find the first occurrence of '#' in [BEG, BEG+SIZE) that is not
    preceded by '&'.  If the character is not found, return zero.  If
    the character is found, return 1 and set BP and EP to point to the
@@ -2049,32 +2105,27 @@ find_fragment (const char *beg, int size, const char **bp, const char **ep)
   return 0;
 }
 
-/* The idea here was to quote ? as %3F to avoid passing part of the
-   file name as the parameter when browsing the converted file through
-   HTTP.  However, actually doing that breaks local browsing because
-   "index.html%3Ffoo=bar" isn't even recognized as an HTML file!
-   Perhaps this should be controlled by an option, but for now I'm
-   leaving the question marks.
-
-   This is the original docstring of this function:
-
-   FILE should be a relative link to a local file.  It should be
-   quoted as HTML because it will be used in HTML context.  However,
-   we need to quote ? as %3F to avoid passing part of the file name as
-   the parameter.  (This is not a problem when viewing locally, but is
-   if the downloaded and converted tree is served by an HTTP
-   server.)  */
+/* Quote FILE for use as local reference to an HTML file.
 
-/* Quote string as HTML. */
+   We quote ? as %3F to avoid passing part of the file name as the
+   parameter when browsing the converted file through HTTP.  However,
+   it is safe to do this only when `--html-extension' is turned on.
+   This is because converting "index.html?foo=bar" to
+   "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.  */
 
 static char *
 local_quote_string (const char *file)
 {
-  return html_quote_string (file);
-
-#if 0
   const char *file_sans_qmark;
-  int qm = count_char (file, '?');
+  int qm;
+
+  if (!opt.html_extension)
+    return html_quote_string (file);
+
+  qm = count_char (file, '?');
 
   if (qm)
     {
@@ -2106,7 +2157,6 @@ local_quote_string (const char *file)
     file_sans_qmark = file;
 
   return html_quote_string (file_sans_qmark);
-#endif
 }
 
 /* We're storing "modes" of type downloaded_file_t in the hash table.