soup_header_g_string_append_param: if @value is a token, don't quote it
authorDan Winship <danw@gnome.org>
Tue, 6 Apr 2010 16:05:26 +0000 (12:05 -0400)
committerDan Winship <danw@gnome.org>
Fri, 9 Apr 2010 23:51:33 +0000 (19:51 -0400)
also add soup_header_g_string_append_param_quoted(), for places that
need to guarantee they're adding a quoted-string, not a token, even if
a token would be syntactically correct. (eg, digest auth, where lots of
implementations are very very picky)

libsoup/soup-auth-digest.c
libsoup/soup-auth-domain-digest.c
libsoup/soup-headers.c
libsoup/soup-headers.h
tests/header-parsing.c
tests/sniffing-test.c

index f9c88bc..90718c6 100644 (file)
@@ -436,30 +436,30 @@ get_authorization (SoupAuth *auth, SoupMessage *msg)
 
        out = g_string_new ("Digest ");
 
-       soup_header_g_string_append_param (out, "username", priv->user);
+       soup_header_g_string_append_param_quoted (out, "username", priv->user);
        g_string_append (out, ", ");
-       soup_header_g_string_append_param (out, "realm", auth->realm);
+       soup_header_g_string_append_param_quoted (out, "realm", auth->realm);
        g_string_append (out, ", ");
-       soup_header_g_string_append_param (out, "nonce", priv->nonce);
+       soup_header_g_string_append_param_quoted (out, "nonce", priv->nonce);
        g_string_append (out, ", ");
-       soup_header_g_string_append_param (out, "uri", url);
+       soup_header_g_string_append_param_quoted (out, "uri", url);
        g_string_append (out, ", ");
        algorithm = soup_auth_digest_get_algorithm (priv->algorithm);
        g_string_append_printf (out, "algorithm=%s", algorithm);
        g_free (algorithm);
        g_string_append (out, ", ");
-       soup_header_g_string_append_param (out, "response", response);
+       soup_header_g_string_append_param_quoted (out, "response", response);
 
        if (priv->opaque) {
                g_string_append (out, ", ");
-               soup_header_g_string_append_param (out, "opaque", priv->opaque);
+               soup_header_g_string_append_param_quoted (out, "opaque", priv->opaque);
        }
 
        if (priv->qop) {
                char *qop = soup_auth_digest_get_qop (priv->qop);
 
                g_string_append (out, ", ");
-               soup_header_g_string_append_param (out, "cnonce", priv->cnonce);
+               soup_header_g_string_append_param_quoted (out, "cnonce", priv->cnonce);
                g_string_append_printf (out, ", nc=%.8x, qop=%s",
                                        priv->nc, qop);
                g_free (qop);
index f4a7f41..cee7745 100644 (file)
@@ -374,7 +374,7 @@ challenge (SoupAuthDomain *domain, SoupMessage *msg)
        GString *str;
 
        str = g_string_new ("Digest ");
-       soup_header_g_string_append_param (str, "realm", soup_auth_domain_get_realm (domain));
+       soup_header_g_string_append_param_quoted (str, "realm", soup_auth_domain_get_realm (domain));
        g_string_append_printf (str, ", nonce=\"%lu%lu\"", 
                                (unsigned long) msg,
                                (unsigned long) time (0));
index 9835392..5e73a3c 100644 (file)
@@ -795,21 +795,42 @@ soup_header_free_param_list (GHashTable *param_list)
 }
 
 static void
-append_param_rfc2231 (GString *string, const char *value)
+append_param_rfc2231 (GString    *string,
+                     const char *name,
+                     const char *value)
 {
        char *encoded;
 
+       g_string_append (string, name);
        g_string_append (string, "*=UTF-8''");
        encoded = soup_uri_encode (value, " *'%()<>@,;:\\\"/[]?=");
        g_string_append (string, encoded);
        g_free (encoded);
 }
 
-static void
-append_param_quoted (GString *string, const char *value)
+/**
+ * soup_header_g_string_append_param_quoted:
+ * @string: a #GString being used to construct an HTTP header value
+ * @name: a parameter name
+ * @value: a parameter value
+ *
+ * Appends something like <literal>@name="@value"</literal> to
+ * @string, taking care to escape any quotes or backslashes in @value.
+ *
+ * Since: 2.32
+ **/
+void
+soup_header_g_string_append_param_quoted (GString    *string,
+                                         const char *name,
+                                         const char *value)
 {
        int len;
 
+       g_return_if_fail (string != NULL);
+       g_return_if_fail (name != NULL);
+       g_return_if_fail (value != NULL);
+
+       g_string_append (string, name);
        g_string_append (string, "=\"");
        while (*value) {
                while (*value == '\\' || *value == '"') {
@@ -829,9 +850,9 @@ append_param_quoted (GString *string, const char *value)
  * @name: a parameter name
  * @value: a parameter value, or %NULL
  *
- * Appends something like <literal>@name="@value"</literal> to
- * @string, taking care to appropriately escape any quotes or
- * backslashes in @value.
+ * Appends something like <literal>@name=@value</literal> to @string,
+ * taking care to quote @value if needed, and if so, to escape any
+ * quotes or backslashes in @value.
  *
  * Alternatively, if @value is a non-ASCII UTF-8 string, it will be
  * appended using RFC2231 syntax. Although in theory this is supposed
@@ -844,26 +865,38 @@ append_param_quoted (GString *string, const char *value)
  * Since: 2.26
  **/
 void
-soup_header_g_string_append_param (GString *string, const char *name,
+soup_header_g_string_append_param (GString    *string,
+                                  const char *name,
                                   const char *value)
 {
        const char *v;
+       gboolean token = TRUE;
 
        g_return_if_fail (string != NULL);
        g_return_if_fail (name != NULL);
 
-       g_string_append (string, name);
-       if (!value)
+       if (!value) {
+               g_string_append (string, name);
                return;
+       }
 
        for (v = value; *v; v++) {
                if (*v & 0x80) {
                        if (g_utf8_validate (value, -1, NULL)) {
-                               append_param_rfc2231 (string, value);
+                               append_param_rfc2231 (string, name, value);
                                return;
-                       } else
+                       } else {
+                               token = FALSE;
                                break;
-               }
+                       }
+               } else if (!soup_char_is_token (*v))
+                       token = FALSE;
        }
-       append_param_quoted (string, value);
+
+       if (token) {
+               g_string_append (string, name);
+               g_string_append_c (string, '=');
+               g_string_append (string, value);
+       } else
+               soup_header_g_string_append_param_quoted (string, name, value);
 }
index 59f0e78..cc542c3 100644 (file)
@@ -53,6 +53,9 @@ void        soup_header_free_param_list       (GHashTable       *param_list);
 void        soup_header_g_string_append_param (GString          *string,
                                               const char       *name,
                                               const char       *value);
+void        soup_header_g_string_append_param_quoted (GString    *string,
+                                                     const char *name,
+                                                     const char *value);
 
 G_END_DECLS
 
index e8799b3..bc1b8cf 100644 (file)
@@ -882,7 +882,7 @@ do_rfc2231_tests (void)
 #define CONTENT_TYPE_TEST_MIME_TYPE "text/plain"
 #define CONTENT_TYPE_TEST_ATTRIBUTE "charset"
 #define CONTENT_TYPE_TEST_VALUE     "US-ASCII"
-#define CONTENT_TYPE_TEST_HEADER    "text/plain; charset=\"US-ASCII\""
+#define CONTENT_TYPE_TEST_HEADER    "text/plain; charset=US-ASCII"
 
 #define CONTENT_TYPE_BAD_HEADER     "plain text, not text/html"
 
@@ -963,7 +963,7 @@ struct {
        { "five", "test with \xC3\xA1\xC3\xA7\xC4\x89\xC3\xA8\xC3\xB1\xC5\xA3\xC5\xA1" }
 };
 
-#define TEST_PARAMS_RESULT "one=\"foo\", two=\"test with spaces\", three=\"test with \\\"quotes\\\" and \\\\s\", four, five*=UTF-8''test%20with%20%C3%A1%C3%A7%C4%89%C3%A8%C3%B1%C5%A3%C5%A1"
+#define TEST_PARAMS_RESULT "one=foo, two=\"test with spaces\", three=\"test with \\\"quotes\\\" and \\\\s\", four, five*=UTF-8''test%20with%20%C3%A1%C3%A7%C4%89%C3%A8%C3%B1%C5%A3%C5%A1"
 
 static void
 do_append_param_tests (void)
index 9aca27b..b2296be 100644 (file)
@@ -540,7 +540,7 @@ main (int argc, char **argv)
        test_sniffing ("/multiple_headers/home.gif", "image/gif");
 
        /* Test that we keep the parameters when sniffing */
-       test_sniffing ("/type/text_html; charset=\"UTF-8\"/test.html", "text/html; charset=\"UTF-8\"");
+       test_sniffing ("/type/text_html; charset=UTF-8/test.html", "text/html; charset=UTF-8");
 
        /* Test that disabling the sniffer works correctly */