Author: brane
Date: Wed Jun 25 20:20:05 2025
New Revision: 1926725
URL: http://svn.apache.org/viewvc?rev=1926725&view=rev
Log:
On the user-defined-authn branch: Parse authentication parameters so that
users don't have to bother with that (and most likely get it wrong, too).
* CMakeLists.txt (SOURCES): Add src/syntax.c.
* serf.h: Include apr_hash.h
(serf_authn_get_realm_func_t,
serf_authn_handle_func_t): Change authn_parameters to a dictionary.
Update the docstrings.
* serf_private.h
(serf__parse_authn_parameters,
serf__tolower_inplace, serf__tolower): Declare prototypes.
* auth/auth.c
(store_header_in_dict): Use serf__tolower_inplace() to fold the scheme.
(serf_authn_register_scheme,
serf_authn_unregister_scheme): Use serf__tolower() to make the scheme key.
* auth/auth_user_defined.c
(serf__authn_user__handle): Parse the incoming authentication parameters.
* src/genctype.py: New; stolen from Subversion.
* src/syntax.c: New; implements serf__parse_authn_parameters(),
serf__tolower_inplace() and serf__tolower().
* test/test_auth.c
(user_authn_get_realm,
user_authn_handle,
user_authn_credentials): Update test callbacks.
(user_authentication): Accept a 'scope' instead of a 'tweak'.
* test/test_internal.c
(struct expected_attrs, parse_parameters): New; common test implementation.
(test_parse_parameters,
test_parse_bad_parameters,
test_parse_repeated_parameters,
test_parameter_case_folding): New test cases.
(test_internal): Register test cases.
Added:
serf/branches/user-defined-authn/src/genctype.py (with props)
serf/branches/user-defined-authn/src/syntax.c (with props)
Modified:
serf/branches/user-defined-authn/CMakeLists.txt
serf/branches/user-defined-authn/auth/auth.c
serf/branches/user-defined-authn/auth/auth_user_defined.c
serf/branches/user-defined-authn/serf.h
serf/branches/user-defined-authn/serf_private.h
serf/branches/user-defined-authn/test/test_auth.c
serf/branches/user-defined-authn/test/test_internal.c
serf/branches/user-defined-authn/test/test_serf.h
Modified: serf/branches/user-defined-authn/CMakeLists.txt
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/CMakeLists.txt?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/CMakeLists.txt (original)
+++ serf/branches/user-defined-authn/CMakeLists.txt Wed Jun 25 20:20:05 2025
@@ -137,6 +137,7 @@ list(APPEND SOURCES
"src/outgoing_request.c"
"src/pump.c"
"src/ssltunnel.c"
+ "src/syntax.c"
"auth/auth.c"
"auth/auth_basic.c"
"auth/auth_digest.c"
Modified: serf/branches/user-defined-authn/auth/auth.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/auth/auth.c?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/auth/auth.c (original)
+++ serf/branches/user-defined-authn/auth/auth.c Wed Jun 25 20:20:05 2025
@@ -264,9 +264,7 @@ static int store_header_in_dict(void *ba
auth_name = apr_pstrmemdup(ab->pool, header, strlen(header));
/* Convert scheme name to lower case to enable case insensitive matching.
*/
- for (c = auth_name; *c != '\0'; c++)
- *c = (char)apr_tolower(*c);
-
+ serf__tolower_inplace(auth_name);
apr_hash_set(ab->hdrs, auth_name, APR_HASH_KEY_STRING,
apr_pstrdup(ab->pool, header));
@@ -673,7 +671,6 @@ apr_status_t serf_authn_register_scheme(
apr_status_t status;
unsigned int scheme_type;
const char *key;
- char *cp;
int index;
serf__log(LOGLVL_INFO, LOGCOMP_AUTHN, __FILE__, config,
@@ -683,11 +680,8 @@ apr_status_t serf_authn_register_scheme(
authn_scheme = apr_palloc(result_pool, sizeof(*authn_scheme));
/* Generate a lower-case key for the scheme. */
- key = cp = apr_pstrdup(result_pool, name);
- while (*cp) {
- *cp = apr_tolower(*cp);
- ++cp;
- }
+ key = serf__tolower(name, result_pool);
+
authn_scheme->name = apr_pstrdup(result_pool, name);
authn_scheme->key = key;
/* user_scheme->type = ?; Will be updated later, under lock. */
@@ -780,18 +774,13 @@ apr_status_t serf_authn_unregister_schem
apr_status_t lock_status;
apr_status_t status;
const char *key;
- char *cp;
int index;
serf__log(LOGLVL_INFO, LOGCOMP_AUTHN, __FILE__, config,
"Unregistering user-defined scheme %s", name);
/* Generate a lower-case key for the scheme. */
- key = cp = apr_pstrdup(scratch_pool, name);
- while (*cp) {
- *cp = apr_tolower(*cp);
- ++cp;
- }
+ key = serf__tolower(name, scratch_pool);
lock_status = lock_authn_schemes(config);
if (lock_status) {
Modified: serf/branches/user-defined-authn/auth/auth_user_defined.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/auth/auth_user_defined.c?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/auth/auth_user_defined.c (original)
+++ serf/branches/user-defined-authn/auth/auth_user_defined.c Wed Jun 25
20:20:05 2025
@@ -158,6 +158,7 @@ serf__authn_user__handle(const serf__aut
struct authn_baton_wrapper *authn_baton;
char *username, *password;
apr_pool_t *scratch_pool;
+ apr_hash_t *auth_param;
apr_status_t status;
status = validate_handler(conn->config, scheme, code, "handle-auth",
@@ -198,12 +199,13 @@ serf__authn_user__handle(const serf__aut
apr_pool_create(&scratch_pool, pool);
status = APR_SUCCESS;
+ auth_param = serf__parse_authn_parameters(auth_attr, scratch_pool);
if (scheme->user_flags & SERF_AUTHN_FLAG_CREDS) {
const char *realm_name;
status = scheme->user_get_realm_func(&realm_name,
scheme->user_baton,
authn_baton->user_authn_baton,
- auth_hdr, auth_attr,
+ auth_hdr, auth_param,
scratch_pool, scratch_pool);
if (!status) {
const char *const realm = serf__construct_realm(
@@ -222,7 +224,7 @@ serf__authn_user__handle(const serf__aut
status = scheme->user_handle_func(scheme->user_baton,
authn_baton->user_authn_baton, code,
- auth_hdr, auth_attr,
+ auth_hdr, auth_param,
SERF__HEADER_FROM_CODE(code),
username, password,
request, response,
Modified: serf/branches/user-defined-authn/serf.h
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf.h?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf.h (original)
+++ serf/branches/user-defined-authn/serf.h Wed Jun 25 20:20:05 2025
@@ -30,6 +30,7 @@
#include <apr_errno.h>
#include <apr_allocator.h>
#include <apr_pools.h>
+#include <apr_hash.h>
#include <apr_network_io.h>
#include <apr_time.h>
#include <apr_poll.h>
@@ -1029,11 +1030,12 @@ typedef apr_status_t
*
* @a authn_baton is the pointer returned from the init-connection callback.
*
- * @a authn_header and @a authn_attributes contain the value of the
- * authentication header (WWW-Authenticate or Proxy-Authenticate) recevied in
- * a server response. @a authn_header contains the scheme name, i.e., "scheme
- * <atributes>", whereas @a authn_attributes contains only the attributes
- * without the scheme name.
+ * @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.
*
* If the scheme flag @a SERF_AUTHN_FLAG_PIPE is *not* set, pipelining will be
* disabled on the connection after this callback succeeds.
@@ -1047,7 +1049,7 @@ typedef apr_status_t
void *baton,
void *authn_baton,
const char *authn_header,
- const char *authn_attributes,
+ apr_hash_t *authn_parameters,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
@@ -1057,7 +1059,7 @@ typedef apr_status_t
* Called after the init-conn function has succeeded to prepare (cache) the
* credentials for this connection, usually in @a auth_baton.
*
- * @a baton, @a authn_baton, @a authn_header and @a authn_attributers have the
+ * @a baton, @a authn_baton, @a authn_header and @a authn_parameters have the
* same meaning as in the get-realm function; @a code is the same as in the
* init-conn function.
*
@@ -1080,7 +1082,7 @@ typedef apr_status_t
void *authn_baton,
int code,
const char *authn_header,
- const char *authn_attributes,
+ apr_hash_t *authn_parameters,
const char *response_header,
const char *username,
const char *password,
Modified: serf/branches/user-defined-authn/serf_private.h
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf_private.h?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf_private.h (original)
+++ serf/branches/user-defined-authn/serf_private.h Wed Jun 25 20:20:05 2025
@@ -747,6 +747,23 @@ apr_status_t serf__handle_auth_response(
able to cleanup stale objects from time to time. */
serf__authn_info_t *serf__get_authn_info_for_server(serf_connection_t *conn);
+
+/* 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.
+
+ The keys in the dictionary will be folded to lowercase.
+
+ See: https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6 */
+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
+ case-folding table as serf__parse_authn_attributes() does for keys.*/
+void serf__tolower_inplace(char *dst);
+
+/* Like serf__tolower_inplace, but allocates a new string from the pool. */
+const char *serf__tolower(const char *src, apr_pool_t *pool);
+
/* from context.c */
void serf__context_progress_delta(void *progress_baton, apr_off_t read,
apr_off_t written);
Added: serf/branches/user-defined-authn/src/genctype.py
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/src/genctype.py?rev=1926725&view=auto
==============================================================================
--- serf/branches/user-defined-authn/src/genctype.py (added)
+++ serf/branches/user-defined-authn/src/genctype.py Wed Jun 25 20:20:05 2025
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# ======================================================================
+# This file was stolen and slightly modified from Subversion @ r882257.
+
+"""getctype.py - Generate the character classification table.
+"""
+
+# Table of ASCII character names
+names = ('nul', 'soh', 'stx', 'etx', 'eot', 'enq', 'ack', 'bel',
+ 'bs', 'ht', 'nl', 'vt', 'np', 'cr', 'so', 'si',
+ 'dle', 'dc1', 'dc2', 'dc3', 'dc4', 'nak', 'syn', 'etb',
+ 'can', 'em', 'sub', 'esc', 'fs', 'gs', 'rs', 'us',
+ 'sp', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 'del')
+
+# All whitespace characters:
+# horizontal tab, vertical tab, new line, form feed, carriage return, space
+whitespace = frozenset((9, 10, 11, 12, 13, 32))
+
+# Bytes not valid in UTF-8 sequences
+utf8_invalid = frozenset((0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF))
+
+# HTTP classes: whitespace and token punctuation
+http_space = (9, 32)
+http_token_punct = frozenset((
+ 33, 35, 36, 37, 38, 39, 42, 43, 45, 46, 94, 95, 96, 124, 126))
+# ! # $ % & ' * + - . ^ _ ` | ~
+
+print(' /* **** DO NOT EDIT! ****')
+print(' This table was generated by genctype.py, make changes there. */')
+
+for c in range(256):
+ bits = []
+
+ # Ascii subrange
+ if c < 128:
+ bits.append('CT_ASCII')
+
+ if len(names[c]) == 1:
+ name = names[c].center(3)
+ else:
+ name = names[c].ljust(3)
+
+ # Control characters
+ if c < 32 or c == 127:
+ bits.append('CT_CNTRL')
+
+ # Whitespace characters
+ if c in whitespace:
+ bits.append('CT_SPACE')
+ if c in http_space:
+ bits.append('CT_HTTP_SPACE')
+
+ # Punctuation marks
+ if c >= 33 and c < 48 \
+ or c >= 58 and c < 65 \
+ 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')
+
+ # 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')
+
+ # UTF-8 multibyte sequences
+ else:
+ name = hex(c)[1:]
+
+ # Lead bytes (start of sequence)
+ if c > 0xC0 and c < 0xFE and c not in utf8_invalid:
+ bits.append('CT_UTF8_LEAD')
+
+ # Continuation bytes
+ elif (c & 0xC0) == 0x80:
+ bits.append('CT_UTF8_CONT')
+
+ if len(bits) == 0:
+ flags = '0'
+ else:
+ flags = ' | '.join(bits)
+ print(' /* %s */ %s,' % (name, flags))
Propchange: serf/branches/user-defined-authn/src/genctype.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: serf/branches/user-defined-authn/src/genctype.py
------------------------------------------------------------------------------
svn:executable = *
Added: serf/branches/user-defined-authn/src/syntax.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/src/syntax.c?rev=1926725&view=auto
==============================================================================
--- serf/branches/user-defined-authn/src/syntax.c (added)
+++ serf/branches/user-defined-authn/src/syntax.c Wed Jun 25 20:20:05 2025
@@ -0,0 +1,506 @@
+/* ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <apr_pools.h>
+#include <apr_hash.h>
+
+#include "serf.h"
+#include "serf_private.h"
+
+
+/* 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
+
+/* Only space and the horizontal tab are treated as whitespace. */
+#define CT_HTTP_SPACE 0x1000
+
+/* Characters that are allowed in tokens, accorting to RFC 9110, are the
+ 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
+
+
+/* ASCII + UTF-8 character table, stolen wholesale from Subversion. */
+static const unsigned short char_table[256] =
+{
+ /* **** DO NOT EDIT! ****
+ This table was generated by genctype.py, make changes there. */
+ /* nul */ CT_ASCII | CT_CNTRL,
+ /* soh */ CT_ASCII | CT_CNTRL,
+ /* stx */ CT_ASCII | CT_CNTRL,
+ /* etx */ CT_ASCII | CT_CNTRL,
+ /* eot */ CT_ASCII | CT_CNTRL,
+ /* enq */ CT_ASCII | CT_CNTRL,
+ /* 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,
+ /* nl */ CT_ASCII | CT_CNTRL | CT_SPACE,
+ /* vt */ CT_ASCII | CT_CNTRL | CT_SPACE,
+ /* np */ CT_ASCII | CT_CNTRL | CT_SPACE,
+ /* cr */ CT_ASCII | CT_CNTRL | CT_SPACE,
+ /* so */ CT_ASCII | CT_CNTRL,
+ /* si */ CT_ASCII | CT_CNTRL,
+ /* dle */ CT_ASCII | CT_CNTRL,
+ /* dc1 */ CT_ASCII | CT_CNTRL,
+ /* dc2 */ CT_ASCII | CT_CNTRL,
+ /* dc3 */ CT_ASCII | CT_CNTRL,
+ /* dc4 */ CT_ASCII | CT_CNTRL,
+ /* nak */ CT_ASCII | CT_CNTRL,
+ /* syn */ CT_ASCII | CT_CNTRL,
+ /* etb */ CT_ASCII | CT_CNTRL,
+ /* can */ CT_ASCII | CT_CNTRL,
+ /* em */ CT_ASCII | CT_CNTRL,
+ /* sub */ CT_ASCII | CT_CNTRL,
+ /* esc */ CT_ASCII | CT_CNTRL,
+ /* fs */ CT_ASCII | CT_CNTRL,
+ /* 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,
+ /* " */ 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_ASCII | CT_PUNCT,
+ /* * */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+ /* + */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+ /* , */ 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_ASCII | CT_PUNCT,
+ /* < */ CT_ASCII | CT_PUNCT,
+ /* = */ CT_ASCII | CT_PUNCT,
+ /* > */ 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,
+ /* [ */ 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_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+ /* } */ CT_ASCII | CT_PUNCT,
+ /* ~ */ CT_ASCII | CT_PUNCT | CT_HTTP_TOKEN,
+ /* del */ CT_ASCII | CT_CNTRL,
+ /* x80 */ CT_UTF8_CONT,
+ /* x81 */ CT_UTF8_CONT,
+ /* x82 */ CT_UTF8_CONT,
+ /* x83 */ CT_UTF8_CONT,
+ /* x84 */ CT_UTF8_CONT,
+ /* x85 */ CT_UTF8_CONT,
+ /* x86 */ CT_UTF8_CONT,
+ /* x87 */ CT_UTF8_CONT,
+ /* x88 */ CT_UTF8_CONT,
+ /* x89 */ CT_UTF8_CONT,
+ /* x8a */ CT_UTF8_CONT,
+ /* x8b */ CT_UTF8_CONT,
+ /* x8c */ CT_UTF8_CONT,
+ /* x8d */ CT_UTF8_CONT,
+ /* x8e */ CT_UTF8_CONT,
+ /* x8f */ CT_UTF8_CONT,
+ /* x90 */ CT_UTF8_CONT,
+ /* x91 */ CT_UTF8_CONT,
+ /* x92 */ CT_UTF8_CONT,
+ /* x93 */ CT_UTF8_CONT,
+ /* x94 */ CT_UTF8_CONT,
+ /* x95 */ CT_UTF8_CONT,
+ /* x96 */ CT_UTF8_CONT,
+ /* x97 */ CT_UTF8_CONT,
+ /* x98 */ CT_UTF8_CONT,
+ /* x99 */ CT_UTF8_CONT,
+ /* x9a */ CT_UTF8_CONT,
+ /* x9b */ CT_UTF8_CONT,
+ /* x9c */ CT_UTF8_CONT,
+ /* x9d */ CT_UTF8_CONT,
+ /* x9e */ CT_UTF8_CONT,
+ /* x9f */ CT_UTF8_CONT,
+ /* xa0 */ CT_UTF8_CONT,
+ /* xa1 */ CT_UTF8_CONT,
+ /* xa2 */ CT_UTF8_CONT,
+ /* xa3 */ CT_UTF8_CONT,
+ /* xa4 */ CT_UTF8_CONT,
+ /* xa5 */ CT_UTF8_CONT,
+ /* xa6 */ CT_UTF8_CONT,
+ /* xa7 */ CT_UTF8_CONT,
+ /* xa8 */ CT_UTF8_CONT,
+ /* xa9 */ CT_UTF8_CONT,
+ /* xaa */ CT_UTF8_CONT,
+ /* xab */ CT_UTF8_CONT,
+ /* xac */ CT_UTF8_CONT,
+ /* xad */ CT_UTF8_CONT,
+ /* xae */ CT_UTF8_CONT,
+ /* xaf */ CT_UTF8_CONT,
+ /* xb0 */ CT_UTF8_CONT,
+ /* xb1 */ CT_UTF8_CONT,
+ /* xb2 */ CT_UTF8_CONT,
+ /* xb3 */ CT_UTF8_CONT,
+ /* xb4 */ CT_UTF8_CONT,
+ /* xb5 */ CT_UTF8_CONT,
+ /* xb6 */ CT_UTF8_CONT,
+ /* xb7 */ CT_UTF8_CONT,
+ /* xb8 */ CT_UTF8_CONT,
+ /* xb9 */ CT_UTF8_CONT,
+ /* xba */ CT_UTF8_CONT,
+ /* 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,
+ /* xc8 */ CT_UTF8_LEAD,
+ /* xc9 */ CT_UTF8_LEAD,
+ /* xca */ CT_UTF8_LEAD,
+ /* xcb */ CT_UTF8_LEAD,
+ /* xcc */ CT_UTF8_LEAD,
+ /* xcd */ CT_UTF8_LEAD,
+ /* xce */ CT_UTF8_LEAD,
+ /* xcf */ CT_UTF8_LEAD,
+ /* xd0 */ CT_UTF8_LEAD,
+ /* xd1 */ CT_UTF8_LEAD,
+ /* xd2 */ CT_UTF8_LEAD,
+ /* xd3 */ CT_UTF8_LEAD,
+ /* xd4 */ CT_UTF8_LEAD,
+ /* xd5 */ CT_UTF8_LEAD,
+ /* xd6 */ CT_UTF8_LEAD,
+ /* xd7 */ CT_UTF8_LEAD,
+ /* xd8 */ CT_UTF8_LEAD,
+ /* xd9 */ CT_UTF8_LEAD,
+ /* xda */ CT_UTF8_LEAD,
+ /* xdb */ CT_UTF8_LEAD,
+ /* xdc */ CT_UTF8_LEAD,
+ /* xdd */ CT_UTF8_LEAD,
+ /* xde */ CT_UTF8_LEAD,
+ /* xdf */ CT_UTF8_LEAD,
+ /* xe0 */ 0,
+ /* xe1 */ CT_UTF8_LEAD,
+ /* xe2 */ CT_UTF8_LEAD,
+ /* xe3 */ CT_UTF8_LEAD,
+ /* xe4 */ CT_UTF8_LEAD,
+ /* xe5 */ CT_UTF8_LEAD,
+ /* xe6 */ CT_UTF8_LEAD,
+ /* xe7 */ CT_UTF8_LEAD,
+ /* xe8 */ CT_UTF8_LEAD,
+ /* xe9 */ CT_UTF8_LEAD,
+ /* xea */ CT_UTF8_LEAD,
+ /* xeb */ CT_UTF8_LEAD,
+ /* xec */ CT_UTF8_LEAD,
+ /* xed */ CT_UTF8_LEAD,
+ /* xee */ CT_UTF8_LEAD,
+ /* xef */ CT_UTF8_LEAD,
+ /* xf0 */ 0,
+ /* xf1 */ CT_UTF8_LEAD,
+ /* xf2 */ CT_UTF8_LEAD,
+ /* xf3 */ CT_UTF8_LEAD,
+ /* xf4 */ CT_UTF8_LEAD,
+ /* xf5 */ CT_UTF8_LEAD,
+ /* xf6 */ CT_UTF8_LEAD,
+ /* xf7 */ CT_UTF8_LEAD,
+ /* xf8 */ 0,
+ /* xf9 */ CT_UTF8_LEAD,
+ /* xfa */ CT_UTF8_LEAD,
+ /* xfb */ CT_UTF8_LEAD,
+ /* xfc */ 0,
+ /* xfd */ CT_UTF8_LEAD,
+ /* xfe */ 0,
+ /* xff */ 0
+};
+
+/* Character class lookup */
+static APR_INLINE int ct_isspace(char c)
+{
+ return char_table[(unsigned char)c] & CT_HTTP_SPACE;
+}
+
+static APR_INLINE int ct_istoken(char c)
+{
+ return char_table[(unsigned char)c] & CT_HTTP_TOKEN;
+}
+
+
+/* Uppercase-lowercase table, also stolen wholesale from Subversion.
+ Folds uppercase ASCII letters into lowercase and ignores the rest. */
+static const unsigned char casefold_table[256] =
+ {
+ /* Identity, except {65:90} => {97:122} */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+ };
+
+/* Fold ASCII to lowercase. */
+static APR_INLINE char ct_tolower(char c)
+{
+ return (char) casefold_table[(unsigned char)c];
+}
+
+
+static const char *skip_space(const char *src)
+{
+ while (ct_isspace(*src))
+ ++src;
+ return src;
+}
+
+#if 0
+static const char *skip_comment(const char *src)
+{
+ if (*src != '(')
+ return NULL;
+
+ ++src;
+ while (*src && *src != ')')
+ {
+ if (*src == '(') {
+ src = skip_comment(src);
+ if (!src)
+ return NULL;
+ }
+ else {
+ if (*src == '\\')
+ ++src; /* Skip escape from quoted-pair */
+ if (*src)
+ ++src;
+ }
+ }
+
+ if (!*src)
+ return NULL;
+ return src + 1;
+}
+#endif
+
+static const char *copy_quoted_string(char **dst, const char *src)
+{
+ if (*src != '"')
+ return NULL;
+
+ ++src;
+ while (*src && *src != '"')
+ {
+ if (*src == '\\')
+ ++src; /* Skip escape from quoted-pair */
+ if (*src)
+ *((*dst)++) = *src++;
+ }
+
+ if (!*src)
+ return NULL;
+ return src + 1;
+}
+
+static const char *copy_token_key(char **dst, const char *src)
+{
+ if (!ct_istoken(*src))
+ return NULL;
+
+ do { *((*dst)++) = ct_tolower(*src++); } while (ct_istoken(*src));
+ return src;
+}
+
+static const char *copy_token(char **dst, const char *src)
+{
+ if (!ct_istoken(*src))
+ return NULL;
+
+ do { *((*dst)++) = *src++; } while (ct_istoken(*src));
+ return src;
+}
+
+
+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;
+ bool want_comma = false;
+
+ while (src && *src)
+ {
+ const char *key;
+ apr_ssize_t keylen;
+ const char *value;
+
+ /* Skip spaces and the separator. */
+ src = skip_space(src);
+ if (want_comma) {
+ if (*src != ',')
+ break;
+ ++src;
+ if (*src)
+ src = skip_space(src);
+ }
+ if (!*src)
+ break;
+
+ /* Pars the key, a lower-cased token. */
+ key = dst;
+ src = copy_token_key(&dst, src);
+ if (!src || key == dst || *src != '=')
+ break;
+ keylen = dst - key;
+ *dst++ = '\0';
+
+ /* Parse the value, either a token or a quoted string. */
+ ++src;
+ value = dst;
+ if (*src == '"')
+ src = copy_quoted_string(&dst, src);
+ else if (ct_istoken(*src))
+ src = copy_token(&dst, src);
+ if (!src || value == dst)
+ break;
+ *dst++ = '\0';
+
+ /* Must be at the end of the string or at a valid separator. */
+ if (*src && *src != ',' && !ct_isspace(*src))
+ break;
+
+ /* Put the new key/value pair into the dict. */
+ apr_hash_set(dict, key, keylen, value);
+ want_comma = true;
+ }
+
+ return dict;
+}
+
+
+void serf__tolower_inplace(char *dst)
+{
+ while(*dst) {
+ *dst = ct_tolower(*dst);
+ ++dst;
+ }
+}
+
+
+const char *serf__tolower(const char *src, apr_pool_t *pool)
+{
+ const size_t len = strlen(src) + 1;
+ size_t i;
+
+ char *dst = apr_palloc(pool, len);
+ for (i = 0; i < len; ++i)
+ dst[i] = ct_tolower(src[i]); /* The NUL byte is copied, too. */
+ return dst;
+}
Propchange: serf/branches/user-defined-authn/src/syntax.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: serf/branches/user-defined-authn/test/test_auth.c
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/test_auth.c?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/test_auth.c (original)
+++ serf/branches/user-defined-authn/test/test_auth.c Wed Jun 25 20:20:05 2025
@@ -707,33 +707,26 @@ static apr_status_t user_authn_get_realm
void *baton,
void *authn_baton,
const char *authn_header,
- const char *authn_attributes,
+ apr_hash_t *authn_parameters,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- const char *end;
- apr_size_t length;
+ const char *name;
USER_AUTHN_COUNT(baton, get_realm);
test__log(TEST_VERBOSE, __FILE__,
- "user_authn_get_realm, header %s, attrs %s\n",
- authn_header, authn_attributes);
+ "user_authn_get_realm, header %s\n", authn_header);
if (strncasecmp(authn_header, "TweedleDee", 10)) {
*realm_name = "Wonderland";
return APR_SUCCESS;
}
- if (strncasecmp(authn_attributes, "scope=", 6))
+ name = apr_hash_get(authn_parameters, "scope", 5);
+ if (!name)
return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
- authn_attributes += 6;
- if ((end = strchr(authn_attributes, ' '))) {
- length = end - authn_attributes;
- } else {
- length = strlen(authn_attributes);
- }
- *realm_name = apr_pstrndup(result_pool, authn_attributes, length);
+ *realm_name = apr_pstrdup(result_pool, name);
return APR_SUCCESS;
}
@@ -741,7 +734,7 @@ static apr_status_t user_authn_handle(vo
void *authn_baton,
int code,
const char *authn_header,
- const char *authn_attributes,
+ apr_hash_t *authn_parameters,
const char *response_header,
const char *username,
const char *password,
@@ -821,15 +814,17 @@ user_authn_credentials(char **username,
if (strncmp(user_authn_prefix, authn_type, strlen(user_authn_prefix)) != 0)
return REPORT_TEST_SUITE_ERROR();
- realm_name = realm + strlen(realm) - strlen("Alice");
- if (strcmp("Alice", realm_name) != 0)
+ realm_name = strrchr(realm, ' ');
+ if (!realm_name
+ || (strcmp(" Alice", realm_name)
+ && strcmp(" Cheshire", realm_name)))
return REPORT_TEST_SUITE_ERROR();
*username = NULL;
*password = apr_pstrdup(pool, authn_type);
test__log(TEST_VERBOSE, __FILE__,
"user credentials, realm %s, password %s\n",
- realm, *password);
+ realm_name + 1, *password);
return APR_SUCCESS;
}
@@ -837,7 +832,7 @@ user_authn_credentials(char **username,
static void user_authentication(CuTest *tc,
int close_conn,
int use_pipelining,
- const char *tweak)
+ const char *scope)
{
test_baton_t *tb = tc->testBaton;
handler_baton_t handler_ctx;
@@ -889,9 +884,9 @@ static void user_authentication(CuTest *
serf_config_credentials_callback(tb->context, user_authn_credentials);
/* Adjust the authentication header. */
- if (tweak)
+ if (scope)
hdr_value = apr_pstrcat(tb->pool, hdr_value,
- " tweak=", tweak, NULL);
+ ", scope=", scope, NULL);
/* Use non-standard case WWW-Authenticate header and scheme name to test
for case insensitive comparisons. */
@@ -966,7 +961,7 @@ static void test_user_authentication(CuT
user_authentication(tc,
0 /* don't close connection */,
1 /* allow pipelining during authn */,
- 0 /* no authn header tweaks */);
+ 0 /* no custom scope */);
}
static void test_user_authentication_tweaked(CuTest *tc)
@@ -982,7 +977,7 @@ static void test_user_authentication_kee
user_authentication(tc,
1 /* close connection */,
1 /* allow pipelining during authn */,
- 0 /* no authn header tweaks */);
+ 0 /* no custom scope */);
}
static void test_user_authentication_pipelining_off(CuTest *tc)
@@ -990,7 +985,7 @@ static void test_user_authentication_pip
user_authentication(tc,
0 /* don't close connection */,
0 /* don't allow pipelining during authn */,
- 0 /* no authn header tweaks */);
+ 0 /* no custom scope */);
}
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=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/test_internal.c (original)
+++ serf/branches/user-defined-authn/test/test_internal.c Wed Jun 25 20:20:05
2025
@@ -465,6 +465,88 @@ static void test_narrowing_conversions(C
CuAssertIntEquals(tc, -1, val);
}
+
+struct expected_attrs
+{
+ const char *token;
+ const char *value;
+};
+
+static void parse_parameters(CuTest *tc, const char *attrs,
+ const struct expected_attrs expected[])
+{
+ test_baton_t *const tb = tc->testBaton;
+ apr_hash_t *const dict = serf__parse_authn_parameters(attrs, tb->pool);
+ const short attr_count = apr_hash_count(dict);
+ int i;
+
+ for (i = 0; expected[i].token; ++i)
+ {
+ const char *token = expected[i].token;
+ const char *value = apr_hash_get(dict, token, APR_HASH_KEY_STRING);
+ CuAssertStrEquals(tc, expected[i].value, value);
+ }
+ CuAssertIntEquals(tc, i, attr_count);
+}
+
+static void test_parse_parameters(CuTest *tc)
+{
+ static const struct expected_attrs expected[] = {
+ { "realm", "Wonderland" },
+ { "scope", "Alice" },
+ { "!#$%&'*+-.^_`|~", "(\"\\)"},
+ { NULL, NULL }
+ };
+
+ parse_parameters(tc,
+ "Realm=\"Wonderland\","
+ "ScOpE=Alice , "
+ "!#$%&'*+-.^_`|~=\"(\\\"\\\\)\"",
+ expected);
+}
+
+static void test_parse_bad_parameters(CuTest *tc)
+{
+ 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);
+}
+
+static void test_parse_repeated_parameters(CuTest *tc)
+{
+ static const struct expected_attrs expected[] = {
+ { "key", "value2" },
+ { NULL, NULL }
+ };
+
+ parse_parameters(tc, "key=value1, key=value2", expected);
+}
+
+static void test_parameter_case_folding(CuTest *tc)
+{
+ static const struct expected_attrs expected[] = {
+ { "01234abcdefghijklmnopqrstuvwxyz56789", "Val" },
+ { NULL, NULL }
+ };
+
+ parse_parameters(tc, "01234abcdefghijklmnopqrstuvwxyz56789=Val", expected);
+ parse_parameters(tc, "01234ABCDEFGHIJKLMNOPQRSTUVWXYZ56789=Val", expected);
+}
+
+
CuSuite *test_internal(void)
{
CuSuite *suite = CuSuiteNew();
@@ -479,6 +561,10 @@ CuSuite *test_internal(void)
SUITE_ADD_TEST(suite, test_header_buckets_remove);
SUITE_ADD_TEST(suite, test_runtime_versions);
SUITE_ADD_TEST(suite, test_narrowing_conversions);
+ 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_parameter_case_folding);
return suite;
}
Modified: serf/branches/user-defined-authn/test/test_serf.h
URL:
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/test_serf.h?rev=1926725&r1=1926724&r2=1926725&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/test_serf.h (original)
+++ serf/branches/user-defined-authn/test/test_serf.h Wed Jun 25 20:20:05 2025
@@ -33,7 +33,7 @@
/* Test logging facilities, set flag to 1 to enable console logging for
the test suite. */
-#define TEST_VERBOSE 0
+#define TEST_VERBOSE 01
/* Preferred proxy port */
#define PROXY_PORT 23456