From 65cc42ee09df3a8f30e070b4c81e2cd8edd66a34 Mon Sep 17 00:00:00 2001
From: hniksic <devnull@localhost>
Date: Tue, 28 Feb 2006 14:32:56 -0800
Subject: [PATCH] [svn] Use the extract_param function for parsing the
 www-authenticate header.

---
 src/cookies.c |   6 +--
 src/http.c    | 116 ++++++++++----------------------------------------
 src/http.h    |   2 +-
 3 files changed, 27 insertions(+), 97 deletions(-)

diff --git a/src/cookies.c b/src/cookies.c
index b12e7e83..29f53964 100644
--- a/src/cookies.c
+++ b/src/cookies.c
@@ -347,14 +347,14 @@ parse_set_cookie (const char *set_cookie, bool silent)
   struct cookie *cookie = cookie_new ();
   param_token name, value;
 
-  if (!extract_param (&ptr, &name, &value))
+  if (!extract_param (&ptr, &name, &value, ';'))
     goto error;
   if (!value.b)
     goto error;
   cookie->attr = strdupdelim (name.b, name.e);
   cookie->value = strdupdelim (value.b, value.e);
 
-  while (extract_param (&ptr, &name, &value))
+  while (extract_param (&ptr, &name, &value, ';'))
     {
       if (TOKEN_IS (name, "domain"))
 	{
@@ -1370,7 +1370,7 @@ test_cookies (void)
 	param_token name, value;
 	const char *ptr = data;
 	int j = 0;
-	while (extract_param (&ptr, &name, &value))
+	while (extract_param (&ptr, &name, &value, ';'))
 	  {
 	    char *n = strdupdelim (name.b, name.e);
 	    char *v = strdupdelim (value.b, value.e);
diff --git a/src/http.c b/src/http.c
index 36680a5e..b9b5a60e 100644
--- a/src/http.c
+++ b/src/http.c
@@ -855,11 +855,11 @@ skip_short_body (int fd, wgint contlen)
   return true;
 }
 
-/* Extract a parameter from the HTTP header at *SOURCE and advance
-   *SOURCE to the next parameter.  Return false when there are no more
-   parameters to extract.  The name of the parameter is returned in
-   NAME, and the value in VALUE.  If the parameter has no value, the
-   token's value is zeroed out.
+/* Extract a parameter from the string (typically an HTTP header) at
+   **SOURCE and advance SOURCE to the next parameter.  Return false
+   when there are no more parameters to extract.  The name of the
+   parameter is returned in NAME, and the value in VALUE.  If the
+   parameter has no value, the token's value is zeroed out.
 
    For example, if *SOURCE points to the string "attachment;
    filename=\"foo bar\"", the first call to this function will return
@@ -868,7 +868,8 @@ skip_short_body (int fd, wgint contlen)
    call will return false, indicating no more valid tokens.  */
 
 bool
-extract_param (const char **source, param_token *name, param_token *value)
+extract_param (const char **source, param_token *name, param_token *value,
+	       char separator)
 {
   const char *p = *source;
 
@@ -881,15 +882,15 @@ extract_param (const char **source, param_token *name, param_token *value)
 
   /* Extract name. */
   name->b = p;
-  while (*p && !ISSPACE (*p) && *p != '=' && *p != ';') ++p;
+  while (*p && !ISSPACE (*p) && *p != '=' && *p != separator) ++p;
   name->e = p;
   if (name->b == name->e)
     return false;		/* empty name: error */
   while (ISSPACE (*p)) ++p;
-  if (*p == ';' || !*p)		/* no value */
+  if (*p == separator || !*p)		/* no value */
     {
       xzero (*value);
-      if (*p == ';') ++p;
+      if (*p == separator) ++p;
       *source = p;
       return true;
     }
@@ -908,8 +909,8 @@ extract_param (const char **source, param_token *name, param_token *value)
       value->e = p++;
       /* Currently at closing quote; find the end of param. */
       while (ISSPACE (*p)) ++p;
-      while (*p && *p != ';') ++p;
-      if (*p == ';')
+      while (*p && *p != separator) ++p;
+      if (*p == separator)
 	++p;
       else if (*p)
 	/* garbage after closed quote, e.g. foo="bar"baz */
@@ -918,11 +919,11 @@ extract_param (const char **source, param_token *name, param_token *value)
   else				/* unquoted */
     {
       value->b = p;
-      while (*p && *p != ';') ++p;
+      while (*p && *p != separator) ++p;
       value->e = p;
       while (value->e != value->b && ISSPACE (value->e[-1]))
         --value->e;
-      if (*p == ';') ++p;
+      if (*p == separator) ++p;
     }
   *source = p;
   return true;
@@ -935,7 +936,7 @@ static bool
 parse_content_disposition (const char *hdr, char **filename)
 {
   param_token name, value;
-  while (extract_param (&hdr, &name, &value))
+  while (extract_param (&hdr, &name, &value, ';'))
     if (BOUNDED_EQUAL_NO_CASE (name.b, name.e, "filename") && value.b != NULL)
       {
 	/* Make the file name begin at the last slash or backslash. */
@@ -2715,45 +2716,6 @@ basic_authentication_encode (const char *user, const char *passwd)
 } while (0)
 
 #ifdef ENABLE_DIGEST
-/* Parse HTTP `WWW-Authenticate:' header.  AU points to the beginning
-   of a field in such a header.  If the field is the one specified by
-   ATTR_NAME ("realm", "opaque", and "nonce" are used by the current
-   digest authorization code), extract its value in the (char*)
-   variable pointed by RET.  Returns negative on a malformed header,
-   or number of bytes that have been parsed by this call.  */
-static int
-extract_header_attr (const char *au, const char *attr_name, char **ret)
-{
-  const char *ep;
-  const char *cp = au;
-
-  if (strncmp (cp, attr_name, strlen (attr_name)) == 0)
-    {
-      cp += strlen (attr_name);
-      if (!*cp)
-        return -1;
-      SKIP_WS (cp);
-      if (*cp != '=')
-        return -1;
-      if (!*++cp)
-        return -1;
-      SKIP_WS (cp);
-      if (*cp != '\"')
-        return -1;
-      if (!*++cp)
-        return -1;
-      for (ep = cp; *ep && *ep != '\"'; ep++)
-        ;
-      if (!*ep)
-        return -1;
-      xfree_null (*ret);
-      *ret = strdupdelim (cp, ep);
-      return ep - au + 1;
-    }
-  else
-    return 0;
-}
-
 /* Dump the hexadecimal representation of HASH to BUF.  HASH should be
    an array of 16 bytes containing the hash keys, and BUF should be a
    buffer of 33 writable characters (32 for hex digits plus one for
@@ -2788,53 +2750,21 @@ digest_authentication_encode (const char *au, const char *user,
     { "nonce", &nonce }
   };
   char *res;
+  param_token name, value;
 
   realm = opaque = nonce = NULL;
 
   au += 6;                      /* skip over `Digest' */
-  while (*au)
+  while (extract_param (&au, &name, &value, ','))
     {
       int i;
-
-      SKIP_WS (au);
       for (i = 0; i < countof (options); i++)
-        {
-          int skip = extract_header_attr (au, options[i].name,
-                                          options[i].variable);
-          if (skip < 0)
-            {
-              xfree_null (realm);
-              xfree_null (opaque);
-              xfree_null (nonce);
-              return NULL;
-            }
-          else if (skip)
-            {
-              au += skip;
-              break;
-            }
-        }
-      if (i == countof (options))
-        {
-          while (*au && *au != '=')
-            au++;
-          if (*au && *++au)
-            {
-              SKIP_WS (au);
-              if (*au == '\"')
-                {
-                  au++;
-                  while (*au && *au != '\"')
-                    au++;
-                  if (*au)
-                    au++;
-                }
-            }
-        }
-      while (*au && *au != ',')
-        au++;
-      if (*au)
-        au++;
+	if (name.e - name.b == strlen (options[i].name)
+	    && 0 == strncmp (name.b, options[i].name, name.e - name.b))
+	  {
+	    *options[i].variable = strdupdelim (value.b, value.e);
+	    break;
+	  }
     }
   if (!realm || !nonce || !user || !passwd || !path || !method)
     {
diff --git a/src/http.h b/src/http.h
index 4974481a..869f2109 100644
--- a/src/http.h
+++ b/src/http.h
@@ -42,7 +42,7 @@ typedef struct {
   /* A token consists of characters in the [b, e) range. */
   const char *b, *e;
 } param_token;
-bool extract_param (const char **, param_token *, param_token *);
+bool extract_param (const char **, param_token *, param_token *, char);
 
 
 #endif /* HTTP_H */