Author: brane
Date: Thu Jun 26 03:01:58 2025
New Revision: 1926729

URL: http://svn.apache.org/viewvc?rev=1926729&view=rev
Log:
On the user-defined-authn branch: Detect and parse authn parameters that
are a single (possibly base-64) token.

* serf.h
  (serf_authn_get_realm_func_t): Update docstring for the single-token case.
* serf_private.h
  (serf__parse_authn_parameters): Likewise.

* src/genctype.py: Generate token68 bits.
* src/syntax.c: Include apr.h, for apr_uint32_t.
  (CT_WHITESPACE): Rename from CT_HTTP_SPACE, change value.
  (CT_TOKEN): Rename from CT_HTTP_TOKEN, also change value.
  (CT_TOKEN68): New; for punctuation that's allowed in a token68.
  (char_table): Change type to apr_uint32_t and update contents.
  (ct_istoken): Update the bit mask.
  (ct_istoken68, skip_token68): New.
  (serf__parse_authn_parameters): Detect a single token68 parameter.
   Detect when two parameters are not separated by a comma.

* test/test_internal.c
  (test_parse_bad_parameters): Remove the "unexpected" result, and the
   one case that now passes as a token68 parameter.
  (test_parse_single_token_parameters): New, test cases for token68.
  (test_internal): Register the new test.

Modified:
    serf/branches/user-defined-authn/serf.h
    serf/branches/user-defined-authn/serf_private.h
    serf/branches/user-defined-authn/src/genctype.py
    serf/branches/user-defined-authn/src/syntax.c
    serf/branches/user-defined-authn/test/test_internal.c

Modified: serf/branches/user-defined-authn/serf.h
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf.h?rev=1926729&r1=1926728&r2=1926729&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf.h (original)
+++ serf/branches/user-defined-authn/serf.h Thu Jun 26 03:01:58 2025
@@ -1032,10 +1032,14 @@ typedef apr_status_t
  *
  * @a authn_header and @a authn_parameters come from the authentication header
  * (WWW-Authenticate or Proxy-Authenticate) recevied in a server response.
+ *
  * @a authn_header is the header value, i.e., "scheme <parameters>";
+ *
  * @a authn_parameters is a dictionary of the authentication parameters
  * and their values, e.g., `realm="Wonderland"`. The keys are always folded
- * to lower case.
+ * to lower case. If the parameter is a single token, it is returned in the
+ * dictionary as the value of the empty string key ("").
+ * @see https://www.rfc-editor.org/rfc/rfc9110.html#section-11.2
  *
  * If the scheme flag @a SERF_AUTHN_FLAG_PIPE is *not* set, pipelining will be
  * disabled on the connection after this callback succeeds.

Modified: serf/branches/user-defined-authn/serf_private.h
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf_private.h?rev=1926729&r1=1926728&r2=1926729&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf_private.h (original)
+++ serf/branches/user-defined-authn/serf_private.h Thu Jun 26 03:01:58 2025
@@ -750,11 +750,12 @@ serf__authn_info_t *serf__get_authn_info
 
 /* Parse authentication scheme parameters from a WWW-Authenticate or
    Proxy-Authenticate header. Splits the comma-separated token=value
-   or token="quoted \" value" pairs into a dictionary.
+   or token="quoted \" value" pairs into a dictionary. If the parameters
+   are a single token, it's stored as the value of the empty string key.
 
    The keys in the dictionary will be folded to lowercase.
 
-   See: https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6 */
+   See: https://www.rfc-editor.org/rfc/rfc9110.html#section-11.2 */
 apr_hash_t *serf__parse_authn_parameters(const char *attrs, apr_pool_t *pool);
 
 /* Fold ASCII uppercase letters to lowercase, in place, using the same

Modified: serf/branches/user-defined-authn/src/genctype.py
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/src/genctype.py?rev=1926729&r1=1926728&r2=1926729&view=diff
==============================================================================
--- serf/branches/user-defined-authn/src/genctype.py (original)
+++ serf/branches/user-defined-authn/src/genctype.py Thu Jun 26 03:01:58 2025
@@ -51,10 +51,13 @@ utf8_invalid = frozenset((0xE0, 0xF0, 0x
 
 # HTTP classes: whitespace and token punctuation
 http_space = (9, 32)
-http_token_punct = frozenset((
+token_punct = frozenset((
     33, 35, 36, 37, 38, 39, 42, 43, 45, 46, 94, 95, 96, 124, 126))
 #    !   #   $   %   &   '   *   +   -   .   ^   _   `   |    ~
 
+token68_punct = frozenset((43, 45, 46, 47, 95, 126))
+#                           +   -   .   /   _   ~
+
 print('    /* **** DO NOT EDIT! ****')
 print('       This table was generated by genctype.py, make changes there. */')
 
@@ -78,7 +81,7 @@ for c in range(256):
         if c in whitespace:
             bits.append('CT_SPACE')
             if c in http_space:
-                bits.append('CT_HTTP_SPACE')
+                bits.append('CT_WHITESPACE')
 
         # Punctuation marks
         if c >= 33 and c < 48 \
@@ -86,18 +89,14 @@ for c in range(256):
            or c >= 91 and c < 97 \
            or c >= 123 and c < 127:
             bits.append('CT_PUNCT')
-            if c in http_token_punct:
-                bits.append('CT_HTTP_TOKEN')
 
         # Decimal digits
         elif c >= 48 and c < 58:
             bits.append('CT_DIGIT')
-            bits.append('CT_HTTP_TOKEN')
 
         # Uppercase letters
         elif c >= 65 and c < 91:
             bits.append('CT_UPPER')
-            bits.append('CT_HTTP_TOKEN')
             # Hexadecimal digits
             if c <= 70:
                 bits.append('CT_XALPHA')
@@ -105,11 +104,16 @@ for c in range(256):
         # Lowercase letters
         elif c >= 97 and c < 123:
             bits.append('CT_LOWER')
-            bits.append('CT_HTTP_TOKEN')
             # Hexadecimal digits
             if c <= 102:
                 bits.append('CT_XALPHA')
 
+        # token and token68
+        if c in token_punct:
+            bits.append('CT_TOKEN')
+        if c in token68_punct:
+            bits.append('CT_TOKEN68')
+
     # UTF-8 multibyte sequences
     else:
         name = hex(c)[1:]

Modified: serf/branches/user-defined-authn/src/syntax.c
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/src/syntax.c?rev=1926729&r1=1926728&r2=1926729&view=diff
==============================================================================
--- serf/branches/user-defined-authn/src/syntax.c (original)
+++ serf/branches/user-defined-authn/src/syntax.c Thu Jun 26 03:01:58 2025
@@ -18,6 +18,7 @@
  * ====================================================================
  */
 
+#include <apr.h>
 #include <apr_pools.h>
 #include <apr_hash.h>
 
@@ -26,32 +27,42 @@
 
 
 /* Character classes */
-#define CT_ASCII      0x0001
-#define CT_CNTRL      0x0002
-#define CT_SPACE      0x0004
-#define CT_PUNCT      0x0008
-#define CT_DIGIT      0x0010
-#define CT_UPPER      0x0020
-#define CT_LOWER      0x0040
-#define CT_XALPHA     0x0080
-#define CT_UTF8_CONT  0x0100
-#define CT_UTF8_LEAD  0x0200
+#define CT_ASCII        0x0001
+#define CT_CNTRL        0x0002
+#define CT_SPACE        0x0004
+#define CT_PUNCT        0x0008
+#define CT_DIGIT        0x0010
+#define CT_UPPER        0x0020
+#define CT_LOWER        0x0040
+#define CT_XALPHA       0x0080
+#define CT_UTF8_CONT    0x0100
+#define CT_UTF8_LEAD    0x0200
 
 /* Only space and the horizontal tab are treated as whitespace. */
-#define CT_HTTP_SPACE 0x1000
+#define CT_WHITESPACE 0x010000
 
-/* Characters that are allowed in tokens, accorting to RFC 9110, are the
-   ASCII digits, lowercase and uppercase letters, and the following
-   punctiation marks:
+/* A `token` is a sequence of ASCII digits, lowercase and uppercase letters,
+   and the following punctiation marks:
 
        ! # $ % & ' * + - . ^ _ ` | ~
 
-   Whitespace and all other printable ASCII characters are delimiters. */
-#define CT_HTTP_TOKEN 0x2000
+   See: https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2
+*/
+#define CT_TOKEN      0x020000
+
+/* A `token68` is a sequence of ASCII digits, lowercase and uppercase letters,
+   and the following punctiation marks:
+
+       - . _ ~ + /
+
+   followed by zero or more `=` signs.
+   See: https://www.rfc-editor.org/rfc/rfc9110.html#section-11.2
+*/
+#define CT_TOKEN68    0x040000
 
 
 /* ASCII + UTF-8 character table, stolen wholesale from Subversion. */
-static const unsigned short char_table[256] =
+static const apr_uint32_t char_table[256] =
 {
     /* **** DO NOT EDIT! ****
        This table was generated by genctype.py, make changes there. */
@@ -64,7 +75,7 @@ static const unsigned short char_table[2
     /* ack */ CT_ASCII | CT_CNTRL,
     /* bel */ CT_ASCII | CT_CNTRL,
     /* bs  */ CT_ASCII | CT_CNTRL,
-    /* ht  */ CT_ASCII | CT_CNTRL | CT_SPACE | CT_HTTP_SPACE,
+    /* ht  */ CT_ASCII | CT_CNTRL | CT_SPACE | CT_WHITESPACE,
     /* nl  */ CT_ASCII | CT_CNTRL | CT_SPACE,
     /* vt  */ CT_ASCII | CT_CNTRL | CT_SPACE,
     /* np  */ CT_ASCII | CT_CNTRL | CT_SPACE,
@@ -87,32 +98,32 @@ static const unsigned short char_table[2
     /* gs  */ CT_ASCII | CT_CNTRL,
     /* rs  */ CT_ASCII | CT_CNTRL,
     /* us  */ CT_ASCII | CT_CNTRL,
-    /* sp  */ CT_ASCII | CT_SPACE | CT_HTTP_SPACE,
-    /*  !  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+    /* sp  */ CT_ASCII | CT_SPACE | CT_WHITESPACE,
+    /*  !  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
     /*  "  */ CT_ASCII | CT_PUNCT,
-    /*  #  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  $  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  %  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  &  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  '  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+    /*  #  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  $  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  %  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  &  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  '  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
     /*  (  */ CT_ASCII | CT_PUNCT,
     /*  )  */ CT_ASCII | CT_PUNCT,
-    /*  *  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  +  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+    /*  *  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  +  */ CT_ASCII | CT_PUNCT | CT_TOKEN | CT_TOKEN68,
     /*  ,  */ CT_ASCII | CT_PUNCT,
-    /*  -  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  .  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  /  */ CT_ASCII | CT_PUNCT,
-    /*  0  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  1  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  2  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  3  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  4  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  5  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  6  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  7  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  8  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
-    /*  9  */ CT_ASCII | CT_DIGIT | CT_HTTP_TOKEN,
+    /*  -  */ CT_ASCII | CT_PUNCT | CT_TOKEN | CT_TOKEN68,
+    /*  .  */ CT_ASCII | CT_PUNCT | CT_TOKEN | CT_TOKEN68,
+    /*  /  */ CT_ASCII | CT_PUNCT | CT_TOKEN68,
+    /*  0  */ CT_ASCII | CT_DIGIT,
+    /*  1  */ CT_ASCII | CT_DIGIT,
+    /*  2  */ CT_ASCII | CT_DIGIT,
+    /*  3  */ CT_ASCII | CT_DIGIT,
+    /*  4  */ CT_ASCII | CT_DIGIT,
+    /*  5  */ CT_ASCII | CT_DIGIT,
+    /*  6  */ CT_ASCII | CT_DIGIT,
+    /*  7  */ CT_ASCII | CT_DIGIT,
+    /*  8  */ CT_ASCII | CT_DIGIT,
+    /*  9  */ CT_ASCII | CT_DIGIT,
     /*  :  */ CT_ASCII | CT_PUNCT,
     /*  ;  */ CT_ASCII | CT_PUNCT,
     /*  <  */ CT_ASCII | CT_PUNCT,
@@ -120,68 +131,68 @@ static const unsigned short char_table[2
     /*  >  */ CT_ASCII | CT_PUNCT,
     /*  ?  */ CT_ASCII | CT_PUNCT,
     /*  @  */ CT_ASCII | CT_PUNCT,
-    /*  A  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  B  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  C  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  D  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  E  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  F  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  G  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  H  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  I  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  J  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  K  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  L  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  M  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  N  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  O  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  P  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  Q  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  R  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  S  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  T  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  U  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  V  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  W  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  X  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  Y  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
-    /*  Z  */ CT_ASCII | CT_UPPER | CT_HTTP_TOKEN,
+    /*  A  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  B  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  C  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  D  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  E  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  F  */ CT_ASCII | CT_UPPER | CT_XALPHA,
+    /*  G  */ CT_ASCII | CT_UPPER,
+    /*  H  */ CT_ASCII | CT_UPPER,
+    /*  I  */ CT_ASCII | CT_UPPER,
+    /*  J  */ CT_ASCII | CT_UPPER,
+    /*  K  */ CT_ASCII | CT_UPPER,
+    /*  L  */ CT_ASCII | CT_UPPER,
+    /*  M  */ CT_ASCII | CT_UPPER,
+    /*  N  */ CT_ASCII | CT_UPPER,
+    /*  O  */ CT_ASCII | CT_UPPER,
+    /*  P  */ CT_ASCII | CT_UPPER,
+    /*  Q  */ CT_ASCII | CT_UPPER,
+    /*  R  */ CT_ASCII | CT_UPPER,
+    /*  S  */ CT_ASCII | CT_UPPER,
+    /*  T  */ CT_ASCII | CT_UPPER,
+    /*  U  */ CT_ASCII | CT_UPPER,
+    /*  V  */ CT_ASCII | CT_UPPER,
+    /*  W  */ CT_ASCII | CT_UPPER,
+    /*  X  */ CT_ASCII | CT_UPPER,
+    /*  Y  */ CT_ASCII | CT_UPPER,
+    /*  Z  */ CT_ASCII | CT_UPPER,
     /*  [  */ CT_ASCII | CT_PUNCT,
     /*  \  */ CT_ASCII | CT_PUNCT,
     /*  ]  */ CT_ASCII | CT_PUNCT,
-    /*  ^  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  _  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  `  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
-    /*  a  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  b  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  c  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  d  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  e  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  f  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN | CT_XALPHA,
-    /*  g  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  h  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  i  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  j  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  k  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  l  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  m  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  n  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  o  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  p  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  q  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  r  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  s  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  t  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  u  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  v  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  w  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  x  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  y  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
-    /*  z  */ CT_ASCII | CT_LOWER | CT_HTTP_TOKEN,
+    /*  ^  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  _  */ CT_ASCII | CT_PUNCT | CT_TOKEN | CT_TOKEN68,
+    /*  `  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
+    /*  a  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  b  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  c  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  d  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  e  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  f  */ CT_ASCII | CT_LOWER | CT_XALPHA,
+    /*  g  */ CT_ASCII | CT_LOWER,
+    /*  h  */ CT_ASCII | CT_LOWER,
+    /*  i  */ CT_ASCII | CT_LOWER,
+    /*  j  */ CT_ASCII | CT_LOWER,
+    /*  k  */ CT_ASCII | CT_LOWER,
+    /*  l  */ CT_ASCII | CT_LOWER,
+    /*  m  */ CT_ASCII | CT_LOWER,
+    /*  n  */ CT_ASCII | CT_LOWER,
+    /*  o  */ CT_ASCII | CT_LOWER,
+    /*  p  */ CT_ASCII | CT_LOWER,
+    /*  q  */ CT_ASCII | CT_LOWER,
+    /*  r  */ CT_ASCII | CT_LOWER,
+    /*  s  */ CT_ASCII | CT_LOWER,
+    /*  t  */ CT_ASCII | CT_LOWER,
+    /*  u  */ CT_ASCII | CT_LOWER,
+    /*  v  */ CT_ASCII | CT_LOWER,
+    /*  w  */ CT_ASCII | CT_LOWER,
+    /*  x  */ CT_ASCII | CT_LOWER,
+    /*  y  */ CT_ASCII | CT_LOWER,
+    /*  z  */ CT_ASCII | CT_LOWER,
     /*  {  */ CT_ASCII | CT_PUNCT,
-    /*  |  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+    /*  |  */ CT_ASCII | CT_PUNCT | CT_TOKEN,
     /*  }  */ CT_ASCII | CT_PUNCT,
-    /*  ~  */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+    /*  ~  */ CT_ASCII | CT_PUNCT | CT_TOKEN | CT_TOKEN68,
     /* del */ CT_ASCII | CT_CNTRL,
     /* x80 */ CT_UTF8_CONT,
     /* x81 */ CT_UTF8_CONT,
@@ -245,13 +256,6 @@ static const unsigned short char_table[2
     /* xbb */ CT_UTF8_CONT,
     /* xbc */ CT_UTF8_CONT,
     /* xbd */ CT_UTF8_CONT,
-    /* xbe */ CT_UTF8_CONT,
-    /* xbf */ CT_UTF8_CONT,
-    /* xc0 */ 0,
-    /* xc1 */ CT_UTF8_LEAD,
-    /* xc2 */ CT_UTF8_LEAD,
-    /* xc3 */ CT_UTF8_LEAD,
-    /* xc4 */ CT_UTF8_LEAD,
     /* xc5 */ CT_UTF8_LEAD,
     /* xc6 */ CT_UTF8_LEAD,
     /* xc7 */ CT_UTF8_LEAD,
@@ -316,12 +320,19 @@ static const unsigned short char_table[2
 /* Character class lookup */
 static APR_INLINE int ct_isspace(char c)
 {
-    return char_table[(unsigned char)c] & CT_HTTP_SPACE;
+    return char_table[(unsigned char)c] & CT_WHITESPACE;
 }
 
 static APR_INLINE int ct_istoken(char c)
 {
-    return char_table[(unsigned char)c] & CT_HTTP_TOKEN;
+    static const apr_uint32_t ct = CT_TOKEN | CT_DIGIT | CT_UPPER | CT_LOWER;
+    return ct & char_table[(unsigned char)c];
+}
+
+static APR_INLINE int ct_istoken68(char c)
+{
+    static const apr_uint32_t ct = CT_TOKEN68 | CT_DIGIT | CT_UPPER | CT_LOWER;
+    return ct & char_table[(unsigned char)c];
 }
 
 
@@ -362,6 +373,15 @@ static const char *skip_space(const char
     return src;
 }
 
+static const char *skip_token68(const char *src)
+{
+    while (ct_istoken68(*src))
+        ++src;
+    while (*src == '=')
+        ++src;
+    return src;
+}
+
 #if 0
 static const char *skip_comment(const char *src)
 {
@@ -431,10 +451,19 @@ static const char *copy_token(char **dst
 apr_hash_t *serf__parse_authn_parameters(const char *attrs, apr_pool_t *pool)
 {
     apr_hash_t *dict = apr_hash_make(pool);
-    char *dst = apr_palloc(pool, strlen(attrs));
-    const char *src = attrs;
+    char *dst = apr_palloc(pool, strlen(attrs) + 1);
+    const char *src = skip_space(attrs);
+    const char *end = skip_token68(src);
     bool want_comma = false;
 
+    /* Check if the parameters are a single token68. */
+    if (end != src && !*skip_space(end)) {
+        memcpy(dst, src, end - src);
+        dst[end - src] = '\0';
+        apr_hash_set(dict, "", 0, dst);
+        return dict;
+    }
+
     while (src && *src)
     {
         const char *key;
@@ -473,7 +502,8 @@ apr_hash_t *serf__parse_authn_parameters
         *dst++ = '\0';
 
         /* Must be at the end of the string or at a valid separator. */
-        if (*src && *src != ',' && !ct_isspace(*src))
+        src = skip_space(src);
+        if (*src && *src != ',')
             break;
 
         /* Put the new key/value pair into the dict. */

Modified: serf/branches/user-defined-authn/test/test_internal.c
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/test_internal.c?rev=1926729&r1=1926728&r2=1926729&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/test_internal.c (original)
+++ serf/branches/user-defined-authn/test/test_internal.c Thu Jun 26 03:01:58 
2025
@@ -510,19 +510,14 @@ static void test_parse_bad_parameters(Cu
     static const struct expected_attrs expected[] = {
         { NULL, NULL }
     };
-    static const struct expected_attrs unexpected[] = {
-        { "key", "value1" },
-        { NULL, NULL }
-    };
 
     parse_parameters(tc, "", expected);
     parse_parameters(tc, "\t", expected);
     parse_parameters(tc, "(comm", expected);
-    parse_parameters(tc, "key", expected);
     parse_parameters(tc, "key=\"value", expected);
     parse_parameters(tc, "key = value", expected);
     parse_parameters(tc, "key=\"value1\"key=value2", expected);
-    parse_parameters(tc, "key=value1 key=value2", unexpected);
+    parse_parameters(tc, "key=value1 key=value2", expected);
 }
 
 static void test_parse_repeated_parameters(CuTest *tc)
@@ -535,6 +530,17 @@ static void test_parse_repeated_paramete
     parse_parameters(tc, "key=value1, key=value2", expected);
 }
 
+static void test_parse_single_token_parameters(CuTest *tc)
+{
+    static const struct expected_attrs expected[] = {
+        { "", "Alice/In+Wonderland.==" },
+        { NULL, NULL }
+    };
+
+    parse_parameters(tc, "\tAlice/In+Wonderland.== ", expected);
+    parse_parameters(tc, "Alice=In+Wonderland.=", &expected[1]);
+}
+
 static void test_parameter_case_folding(CuTest *tc)
 {
     static const struct expected_attrs expected[] = {
@@ -564,6 +570,7 @@ CuSuite *test_internal(void)
     SUITE_ADD_TEST(suite, test_parse_parameters);
     SUITE_ADD_TEST(suite, test_parse_bad_parameters);
     SUITE_ADD_TEST(suite, test_parse_repeated_parameters);
+    SUITE_ADD_TEST(suite, test_parse_single_token_parameters);
     SUITE_ADD_TEST(suite, test_parameter_case_folding);
 
     return suite;


Reply via email to