From b167818f7dded95a73f83b181fdcd322fc956cbf Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" Date: Fri, 29 Jul 2016 15:56:54 +0000 Subject: [PATCH] Introduce ap_scan_http_field_content, ap_scan_http_token and ap_get_http_token for more efficient string handling. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1754541 13f79535-47bb-0310-9956-ffa450edef68 --- include/ap_mmn.h | 4 +++- include/httpd.h | 25 +++++++++++++++++++++++++ server/util.c | 42 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 1d3b07a72d..b28637a7cf 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -534,6 +534,8 @@ * dav_get_acl_providers. * 20160608.5 (2.5.0-dev) Add ap_proxy_check_backend(), and tmp_bb to struct * proxy_conn_rec. + * 20160508.6 (2.5.0-dev) Add ap_scan_http_field_content, ap_scan_http_token + * and ap_get_http_token */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -541,7 +543,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20160608 #endif -#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/httpd.h b/include/httpd.h index eba7b53076..931dfac53a 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1632,6 +1632,31 @@ AP_DECLARE(int) ap_find_etag_weak(apr_pool_t *p, const char *line, const char *t */ AP_DECLARE(int) ap_find_etag_strong(apr_pool_t *p, const char *line, const char *tok); +/* Scan a string for field content chars, as defined by RFC7230 section 3.2 + * including VCHAR/obs-text, as well as HT and SP + * @param ptr The string to scan + * @return A pointer to the first (non-HT) ASCII ctrl character. + * @note lws and trailing whitespace are scanned, the caller is responsible + * for trimming leading and trailing whitespace + */ +AP_DECLARE(const char *) ap_scan_http_field_content(const char *ptr); + +/* Scan a string for token characters, as defined by RFC7230 section 3.2.6 + * @param ptr The string to scan + * @return A pointer to the first non-token character. + */ +AP_DECLARE(const char *) ap_scan_http_token(const char *ptr); + +/* Retrieve a token, advancing the pointer to the first non-token character + * and returning a copy of the token string. + * @param ptr The string to scan. On return, this points to the first non-token + * character encountered, or NULL if *ptr was not a token character + * @return A copy of the token string + * @note The caller must handle leading and trailing whitespace as applicable + * and evaluate the terminating character. + */ +AP_DECLARE(char *) ap_get_http_token(apr_pool_t *p, const char **ptr); + /** * Retrieve an array of tokens in the format "1#token" defined in RFC2616. Only * accepts ',' as a delimiter, does not accept quoted strings, and errors on diff --git a/server/util.c b/server/util.c index aab8311532..470f6c343b 100644 --- a/server/util.c +++ b/server/util.c @@ -80,7 +80,7 @@ * char in here and get it to work, because if char is signed then it * will first be sign extended. */ -#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f)) +#define TEST_CHAR(c, f) (test_char_table[(unsigned char)(c)] & (f)) /* Win32/NetWare/OS2 need to check for both forward and back slashes * in ap_getparents() and ap_escape_url. @@ -1594,6 +1594,46 @@ AP_DECLARE(const char *) ap_parse_token_list_strict(apr_pool_t *p, return NULL; } +/* Scan a string for HTTP VCHAR/obs-text characters including HT and SP + * (as used in header values, for example, in RFC 7230 section 3.2) + * returning the pointer to the first non-HT ASCII ctrl character. + */ +AP_DECLARE(const char *) ap_scan_http_field_content(const char *ptr) +{ + for ( ; !TEST_CHAR(*ptr, T_HTTP_CTRLS); ++ptr) ; + + return ptr; +} + +/* Scan a string for HTTP token characters, returning the pointer to + * the first non-token character. + */ +AP_DECLARE(const char *) ap_scan_http_token(const char *ptr) +{ + for ( ; !TEST_CHAR(*ptr, T_HTTP_TOKEN_STOP); ++ptr) ; + + return ptr; +} + +/* Retrieve a token, advancing the pointer to the first non-token character + * and returning a copy of the token string. + * The caller must handle whitespace and determine the meaning of the + * terminating character. Returns NULL if the character at **ptr is not + * a valid token character. + */ +AP_DECLARE(char *) ap_get_http_token(apr_pool_t *p, const char **ptr) +{ + const char *tok_end = ap_scan_http_token(*ptr); + char *tok; + + if (tok_end == *ptr) + return NULL; + + tok = apr_pstrmemdup(p, *ptr, tok_end - *ptr); + *ptr = tok_end; + return tok; +} + /* Retrieve a token, spacing over it and returning a pointer to * the first non-white byte afterwards. Note that these tokens * are delimited by semis and commas; and can also be delimited -- 2.50.1