]> sjero.net Git - wget/blobdiff - src/url.c
[svn] Use new macros xnew, xnew0, xnew_array, and xnew0_array in various places.
[wget] / src / url.c
index 37917eddaf450108913ea4664d40130f8923d98f..40482b75adf6bca8ecf3992f258f7cf26584d232 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -641,48 +641,52 @@ static char *parse_errors[] = {
 static int
 is_valid_ipv4_address (const char *str, const char *end)
 {
-  int saw_digit, octets;
-  int val;
+  int saw_digit = 0;
+  int octets = 0;
+  int val = 0;
 
-  saw_digit = 0;
-  octets = 0;
-  val = 0;
-
-  while (str < end) {
-    int ch = *str++;
+  while (str < end)
+    {
+      int ch = *str++;
 
-    if (ch >= '0' && ch <= '9') {
-      val = val * 10 + (ch - '0');
+      if (ch >= '0' && ch <= '9')
+       {
+         val = val * 10 + (ch - '0');
 
-      if (val > 255)
-        return 0;
-      if (saw_digit == 0) {
-        if (++octets > 4)
-          return 0;
-        saw_digit = 1;
-      }
-    } else if (ch == '.' && saw_digit == 1) {
-      if (octets == 4)
-        return 0;
-      val = 0;
-      saw_digit = 0;
-    } else
-      return 0;
-  }
+         if (val > 255)
+           return 0;
+         if (saw_digit == 0)
+           {
+             if (++octets > 4)
+               return 0;
+             saw_digit = 1;
+           }
+       }
+      else if (ch == '.' && saw_digit == 1)
+       {
+         if (octets == 4)
+           return 0;
+         val = 0;
+         saw_digit = 0;
+       }
+      else
+       return 0;
+    }
   if (octets < 4)
     return 0;
   
   return 1;
 }
 
-static const int NS_INADDRSZ  = 4;
-static const int NS_IN6ADDRSZ = 16;
-static const int NS_INT16SZ   = 2;
-
 static int
 is_valid_ipv6_address (const char *str, const char *end)
 {
-  static const char xdigits[] = "0123456789abcdef";
+  enum {
+    NS_INADDRSZ  = 4,
+    NS_IN6ADDRSZ = 16,
+    NS_INT16SZ   = 2
+  };
+
   const char *curtok;
   int tp;
   const char *colonp;
@@ -707,62 +711,67 @@ is_valid_ipv6_address (const char *str, const char *end)
   saw_xdigit = 0;
   val = 0;
 
-  while (str < end) {
-    int ch = *str++;
-    const char *pch;
+  while (str < end)
+    {
+      int ch = *str++;
 
-    /* if ch is a number, add it to val. */
-    pch = strchr(xdigits, ch);
-    if (pch != NULL) {
-      val <<= 4;
-      val |= (pch - xdigits);
-      if (val > 0xffff)
-       return 0;
-      saw_xdigit = 1;
-      continue;
+      /* if ch is a number, add it to val. */
+      if (ISXDIGIT (ch))
+       {
+         val <<= 4;
+         val |= XDIGIT_TO_NUM (ch);
+         if (val > 0xffff)
+           return 0;
+         saw_xdigit = 1;
+         continue;
+       }
+
+      /* if ch is a colon ... */
+      if (ch == ':')
+       {
+         curtok = str;
+         if (saw_xdigit == 0)
+           {
+             if (colonp != NULL)
+               return 0;
+             colonp = str + tp;
+             continue;
+           }
+         else if (str == end)
+           return 0;
+         if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
+           return 0;
+         tp += NS_INT16SZ;
+         saw_xdigit = 0;
+         val = 0;
+         continue;
+       }
+
+      /* if ch is a dot ... */
+      if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ)
+         && is_valid_ipv4_address (curtok, end) == 1)
+       {
+         tp += NS_INADDRSZ;
+         saw_xdigit = 0;
+         break;
+       }
+    
+      return 0;
     }
 
-    /* if ch is a colon ... */
-    if (ch == ':') {
-      curtok = str;
-      if (saw_xdigit == 0) {
-       if (colonp != NULL)
-         return 0;
-       colonp = str + tp;
-       continue;
-      } else if (str == end) {
-       return 0;
-      }
-      if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
+  if (saw_xdigit == 1)
+    {
+      if (tp > NS_IN6ADDRSZ - NS_INT16SZ) 
        return 0;
       tp += NS_INT16SZ;
-      saw_xdigit = 0;
-      val = 0;
-      continue;
     }
 
-    /* if ch is a dot ... */
-    if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ) &&
-       is_valid_ipv4_address(curtok, end) == 1) {
-      tp += NS_INADDRSZ;
-      saw_xdigit = 0;
-      break;
+  if (colonp != NULL)
+    {
+      if (tp == NS_IN6ADDRSZ) 
+       return 0;
+      tp = NS_IN6ADDRSZ;
     }
-    
-    return 0;
-  }
-
-  if (saw_xdigit == 1) {
-    if (tp > NS_IN6ADDRSZ - NS_INT16SZ) 
-      return 0;
-    tp += NS_INT16SZ;
-  }
-
-  if (colonp != NULL) {
-    if (tp == NS_IN6ADDRSZ) 
-      return 0;
-    tp = NS_IN6ADDRSZ;
-  }
 
   if (tp != NS_IN6ADDRSZ)
     return 0;
@@ -962,9 +971,7 @@ url_parse (const char *url, int *error)
        }
     }
 
-  u = (struct url *)xmalloc (sizeof (struct url));
-  memset (u, 0, sizeof (*u));
-
+  u = xnew0 (struct url);
   u->scheme = scheme;
   u->host   = strdupdelim (host_b, host_e);
   u->port   = port;
@@ -1350,7 +1357,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))
@@ -1418,14 +1425,15 @@ UWC,  C,  C,  C,   C,  C,  C,  C,   /* NUL SOH STX ETX  EOT ENQ ACK BEL */
 
 /* Quote path element, characters in [b, e), as file name, and append
    the quoted string to DEST.  Each character is quoted as per
-   file_unsafe_char and the corresponding table.  */
+   file_unsafe_char and the corresponding table.
+
+   If ESCAPED_P is non-zero, the path element is considered to be
+   URL-escaped and will be unescaped prior to inspection.  */
 
 static void
-append_uri_pathel (const char *b, const char *e, struct growable *dest)
+append_uri_pathel (const char *b, const char *e, int escaped_p,
+                  struct growable *dest)
 {
-  char *pathel;
-  int pathlen;
-
   const char *p;
   int quoted, outlen;
 
@@ -1438,32 +1446,37 @@ append_uri_pathel (const char *b, const char *e, struct growable *dest)
     mask |= filechr_control;
 
   /* Copy [b, e) to PATHEL and URL-unescape it. */
-  BOUNDED_TO_ALLOCA (b, e, pathel);
-  url_unescape (pathel);
-  pathlen = strlen (pathel);
+  if (escaped_p)
+    {
+      char *unescaped;
+      BOUNDED_TO_ALLOCA (b, e, unescaped);
+      url_unescape (unescaped);
+      b = unescaped;
+      e = unescaped + strlen (unescaped);
+    }
 
-  /* Go through PATHEL and check how many characters we'll need to
-     add for file quoting. */
+  /* Walk the PATHEL string and check how many characters we'll need
+     to add for file quoting.  */
   quoted = 0;
-  for (p = pathel; *p; p++)
+  for (p = b; p < e; p++)
     if (FILE_CHAR_TEST (*p, mask))
       ++quoted;
 
-  /* p - pathel is the string length.  Each quoted char means two
-     additional characters in the string, hence 2*quoted.  */
-  outlen = (p - pathel) + (2 * quoted);
+  /* e-b is the string length.  Each quoted char means two additional
+     characters in the string, hence 2*quoted.  */
+  outlen = (e - b) + (2 * quoted);
   GROW (dest, outlen);
 
   if (!quoted)
     {
       /* If there's nothing to quote, we don't need to go through the
         string the second time.  */
-      memcpy (TAIL (dest), pathel, outlen);
+      memcpy (TAIL (dest), b, outlen);
     }
   else
     {
       char *q = TAIL (dest);
-      for (p = pathel; *p; p++)
+      for (p = b; p < e; p++)
        {
          if (!FILE_CHAR_TEST (*p, mask))
            *q++ = *p;
@@ -1509,14 +1522,12 @@ 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)
        append_char ('/', dest);
-      append_uri_pathel (pathel, next, dest);
+      append_uri_pathel (pathel, next, 1, dest);
     }
 }
 
@@ -1565,14 +1576,14 @@ url_file_name (const struct url *u)
   if (fnres.tail)
     append_char ('/', &fnres);
   u_file = *u->file ? u->file : "index.html";
-  append_uri_pathel (u_file, u_file + strlen (u_file), &fnres);
+  append_uri_pathel (u_file, u_file + strlen (u_file), 0, &fnres);
 
   /* Append "?query" to the file name. */
   u_query = u->query && *u->query ? u->query : NULL;
   if (u_query)
     {
       append_char (FN_QUERY_SEP, &fnres);
-      append_uri_pathel (u_query, u_query + strlen (u_query), &fnres);
+      append_uri_pathel (u_query, u_query + strlen (u_query), 1, &fnres);
     }
 
   /* Zero-terminate the file name. */