]> sjero.net Git - wget/blobdiff - src/url.c
[svn] Don't use trailing commas in enums.
[wget] / src / url.c
index 21005eba5e7bd6b0315005dfc24fd79996ae02c5..9f50127cbb9f7f743aef05700a0e601c8e684e78 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -198,8 +198,8 @@ url_escape_1 (const char *s, unsigned char mask, int allow_passthrough)
        {
          unsigned char c = *p1++;
          *p2++ = '%';
-         *p2++ = XNUM_TO_digit (c >> 4);
-         *p2++ = XNUM_TO_digit (c & 0xf);
+         *p2++ = XNUM_TO_DIGIT (c >> 4);
+         *p2++ = XNUM_TO_DIGIT (c & 0xf);
        }
       else
        *p2++ = *p1++;
@@ -618,28 +618,23 @@ lowercase_str (char *str)
 
 static char *parse_errors[] = {
 #define PE_NO_ERROR                    0
-  "No error",
+  N_("No error"),
 #define PE_UNSUPPORTED_SCHEME          1
-  "Unsupported scheme",
+  N_("Unsupported scheme"),
 #define PE_EMPTY_HOST                  2
-  "Empty host",
+  N_("Empty host"),
 #define PE_BAD_PORT_NUMBER             3
-  "Bad port number",
+  N_("Bad port number"),
 #define PE_INVALID_USER_NAME           4
-  "Invalid user name",
+  N_("Invalid user name"),
 #define PE_UNTERMINATED_IPV6_ADDRESS   5
-  "Unterminated IPv6 numeric address",
+  N_("Unterminated IPv6 numeric address"),
 #define PE_IPV6_NOT_SUPPORTED          6
-  "IPv6 addresses not supported",
+  N_("IPv6 addresses not supported"),
 #define PE_INVALID_IPV6_ADDRESS                7
-  "Invalid IPv6 numeric address"
+  N_("Invalid IPv6 numeric address")
 };
 
-#define SETERR(p, v) do {                      \
-  if (p)                                       \
-    *(p) = (v);                                        \
-} while (0)
-
 #ifdef ENABLE_IPV6
 /* The following two functions were adapted from glibc. */
 
@@ -800,13 +795,15 @@ url_parse (const char *url, int *error)
   int port;
   char *user = NULL, *passwd = NULL;
 
-  char *url_encoded;
+  char *url_encoded = NULL;
+
+  int error_code;
 
   scheme = url_scheme (url);
   if (scheme == SCHEME_INVALID)
     {
-      SETERR (error, PE_UNSUPPORTED_SCHEME);
-      return NULL;
+      error_code = PE_UNSUPPORTED_SCHEME;
+      goto error;
     }
 
   url_encoded = reencode_escapes (url);
@@ -843,23 +840,23 @@ url_parse (const char *url, int *error)
 
       if (!host_e)
        {
-         SETERR (error, PE_UNTERMINATED_IPV6_ADDRESS);
-         return NULL;
+         error_code = PE_UNTERMINATED_IPV6_ADDRESS;
+         goto error;
        }
 
 #ifdef ENABLE_IPV6
       /* Check if the IPv6 address is valid. */
       if (!is_valid_ipv6_address(host_b, host_e))
        {
-         SETERR (error, PE_INVALID_IPV6_ADDRESS);
-         return NULL;
+         error_code = PE_INVALID_IPV6_ADDRESS;
+         goto error;
        }
 
       /* Continue parsing after the closing ']'. */
       p = host_e + 1;
 #else
-      SETERR (error, PE_IPV6_NOT_SUPPORTED);
-      return NULL;
+      error_code = PE_IPV6_NOT_SUPPORTED;
+      goto error;
 #endif
     }
   else
@@ -870,8 +867,8 @@ url_parse (const char *url, int *error)
 
   if (host_b == host_e)
     {
-      SETERR (error, PE_EMPTY_HOST);
-      return NULL;
+      error_code = PE_EMPTY_HOST;
+      goto error;
     }
 
   port = scheme_default_port (scheme);
@@ -890,8 +887,8 @@ url_parse (const char *url, int *error)
        {
          /* http://host:/whatever */
          /*             ^         */
-         SETERR (error, PE_BAD_PORT_NUMBER);
-         return NULL;
+          error_code = PE_BAD_PORT_NUMBER;
+         goto error;
        }
 
       for (port = 0, pp = port_b; pp < port_e; pp++)
@@ -900,8 +897,8 @@ url_parse (const char *url, int *error)
            {
              /* http://host:12randomgarbage/blah */
              /*               ^                  */
-             SETERR (error, PE_BAD_PORT_NUMBER);
-             return NULL;
+              error_code = PE_BAD_PORT_NUMBER;
+              goto error;
            }
          
          port = 10 * port + (*pp - '0');
@@ -960,8 +957,8 @@ url_parse (const char *url, int *error)
       /*     uname_b   uname_e */
       if (!parse_credentials (uname_b, uname_e - 1, &user, &passwd))
        {
-         SETERR (error, PE_INVALID_USER_NAME);
-         return NULL;
+         error_code = PE_INVALID_USER_NAME;
+         goto error;
        }
     }
 
@@ -1007,13 +1004,27 @@ url_parse (const char *url, int *error)
   url_encoded = NULL;
 
   return u;
+
+ error:
+  /* Cleanup in case of error: */
+  if (url_encoded && url_encoded != url)
+    xfree (url_encoded);
+
+  /* Transmit the error code to the caller, if the caller wants to
+     know.  */
+  if (error)
+    *error = error_code;
+  return NULL;
 }
 
+/* Return the error message string from ERROR_CODE, which should have
+   been retrieved from url_parse.  The error message is translated.  */
+
 const char *
 url_error (int error_code)
 {
   assert (error_code >= 0 && error_code < countof (parse_errors));
-  return parse_errors[error_code];
+  return _(parse_errors[error_code]);
 }
 
 /* Split PATH into DIR and FILE.  PATH comes from the URL and is
@@ -1130,6 +1141,7 @@ url_escape_dir (const char *dir)
 
   for (; *h; h++, t++)
     {
+      /* url_escape_1 having converted '/' to "%2F" exactly. */
       if (*h == '%' && h[1] == '2' && h[2] == 'F')
        {
          *t = '/';
@@ -1338,7 +1350,7 @@ append_char (char ch, struct growable *dest)
 enum {
   filechr_not_unix    = 1,     /* unusable on Unix, / and \0 */
   filechr_not_windows = 2,     /* unusable on Windows, one of \|/<>?:*" */
-  filechr_control     = 4,     /* a control character, e.g. 0-31 */
+  filechr_control     = 4      /* a control character, e.g. 0-31 */
 };
 
 #define FILE_CHAR_TEST(c, mask) (filechr_table[(unsigned char)(c)] & (mask))
@@ -1497,9 +1509,7 @@ append_dir_structure (const struct url *u, struct growable *dest)
       if (cut-- > 0)
        continue;
       if (pathel == next)
-       /* Ignore empty pathels.  path_simplify should remove
-          occurrences of "//" from the path, but it has special cases
-          for starting / which generates an empty pathel here.  */
+       /* Ignore empty pathels.  */
        continue;
 
       if (dest->tail)
@@ -1611,19 +1621,23 @@ find_last_char (const char *b, const char *e, char c)
 }
 \f
 /* Resolve "." and ".." elements of PATH by destructively modifying
-   PATH.  "." is resolved by removing that path element, and ".." is
-   resolved by removing the preceding path element.  Single leading
-   and trailing slashes are preserved.
+   PATH and return non-zero if PATH has been modified, zero otherwise.
+
+   The algorithm is in spirit similar to the one described in rfc1808,
+   although implemented differently, in one pass.  To recap, path
+   elements containing only "." are removed, and ".." is taken to mean
+   "back up one element".  Single leading and trailing slashes are
+   preserved.
 
-   Return non-zero if any changes have been made.
+   This function does not handle URL escapes explicitly.  If you're
+   passing paths from URLs, make sure to unquote "%2e" and "%2E" to
+   ".", so that this function can find the dots.  (Wget's URL parser
+   calls reencode_escapes, which see.)
 
    For example, "a/b/c/./../d/.." will yield "a/b/".  More exhaustive
    test examples are provided below.  If you change anything in this
    function, run test_path_simplify to make sure you haven't broken a
-   test case.
-
-   A previous version of this function was based on path_simplify()
-   from GNU Bash, but it has been rewritten for Wget 1.8.1.  */
+   test case.  */
 
 static int
 path_simplify (char *path)
@@ -1651,10 +1665,9 @@ path_simplify (char *path)
        {
          /* Handle "../" by retreating the tortoise by one path
             element -- but not past beggining of PATH.  */
-
          if (t > path)
            {
-             /* Move backwards until B hits the beginning of the
+             /* Move backwards until T hits the beginning of the
                 previous path element or the beginning of path. */
              for (--t; t > path && t[-1] != '/'; t--)
                ;
@@ -1663,12 +1676,12 @@ path_simplify (char *path)
        }
       else if (*h == '/')
        {
-         /* Ignore empty path elements.  Supporting them is hard (in
-            which directory do you save http://x.com///y.html?), and
-            they don't bring any practical gain.  Plus, they break
-            our filesystem-influenced assumptions: allowing empty
-            path elements means that "x/y/../z" simplifies to
-            "x/y/z", whereas most people would expect "x/z".  */
+         /* Ignore empty path elements.  Supporting them well is hard
+            (where do you save "http://x.com///y.html"?), and they
+            don't bring any practical gain.  Plus, they break our
+            filesystem-influenced assumptions: allowing them would
+            make "x/y//../z" simplify to "x/y/z", whereas most people
+            would expect "x/z".  */
          ++h;
        }
       else