diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2016-12-05 22:19:16 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2016-12-05 22:19:16 +0300 |
commit | 89e9332e2bacdba1cf44aabfcfc082c0de62871c (patch) | |
tree | 156ad5e5b00e6966642b2d600dafa5f0cc1d43ac /server/util.c | |
parent | f51547f19e44fc1f511837443cb92ba28c189b9c (diff) | |
parent | adb6f181257af28ee67af15fc49d2699a0080d4c (diff) | |
download | apache2-89e9332e2bacdba1cf44aabfcfc082c0de62871c.tar.gz |
Merge branch 'master' of git://anonscm.debian.org/pkg-apache/apache2
Diffstat (limited to 'server/util.c')
-rw-r--r-- | server/util.c | 340 |
1 files changed, 316 insertions, 24 deletions
diff --git a/server/util.c b/server/util.c index 2b603000..06da7897 100644 --- a/server/util.c +++ b/server/util.c @@ -96,7 +96,6 @@ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX - /* * Examine a field value (such as a media-/content-type) string and return * it sans any parameters; e.g., strip off any ';charset=foo' and the like. @@ -252,7 +251,7 @@ AP_DECLARE(int) ap_os_is_path_absolute(apr_pool_t *p, const char *dir) AP_DECLARE(int) ap_is_matchexp(const char *str) { - register int x; + int x; for (x = 0; str[x]; x++) if ((str[x] == '*') || (str[x] == '?')) @@ -528,7 +527,7 @@ AP_DECLARE(void) ap_getparents(char *name) while (name[l] != '\0') { if (name[l] == '.' && name[l + 1] == '.' && IS_SLASH(name[l + 2]) && (l == 0 || IS_SLASH(name[l - 1]))) { - register int m = l + 3, n; + int m = l + 3, n; l = l - 2; if (l >= 0) { @@ -654,7 +653,7 @@ AP_DECLARE(char *) ap_make_dirstr_parent(apr_pool_t *p, const char *s) AP_DECLARE(int) ap_count_dirs(const char *path) { - register int x, n; + int x, n; for (x = 0, n = 0; path[x]; x++) if (path[x] == '/') @@ -821,6 +820,60 @@ AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line) return res; } +AP_DECLARE(char *) ap_getword_conf2_nc(apr_pool_t *p, char **line) +{ + return ap_getword_conf2(p, (const char **) line); +} + +AP_DECLARE(char *) ap_getword_conf2(apr_pool_t *p, const char **line) +{ + const char *str = *line, *strend; + char *res; + char quote; + int count = 1; + + while (apr_isspace(*str)) + ++str; + + if (!*str) { + *line = str; + return ""; + } + + if ((quote = *str) == '"' || quote == '\'') + return ap_getword_conf(p, line); + + if (quote == '{') { + strend = str + 1; + while (*strend) { + if (*strend == '}' && !--count) + break; + if (*strend == '{') + ++count; + if (*strend == '\\' && strend[1] && strend[1] == '\\') { + ++strend; + } + ++strend; + } + res = substring_conf(p, str + 1, strend - str - 1, 0); + + if (*strend == '}') + ++strend; + } + else { + strend = str; + while (*strend && !apr_isspace(*strend)) + ++strend; + + res = substring_conf(p, str, strend - str, 0); + } + + while (apr_isspace(*strend)) + ++strend; + *line = strend; + return res; +} + AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp) { #ifdef DEBUG @@ -970,20 +1023,20 @@ AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp, /* Read one line from open ap_configfile_t, strip LF, increase line number */ /* If custom handler does not define a getstr() function, read char by char */ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize, - ap_configfile_t *cfp) + apr_size_t offset, ap_configfile_t *cfp) { apr_status_t rc; /* If a "get string" function is defined, use it */ if (cfp->getstr != NULL) { char *cp; - char *cbuf = buf; - apr_size_t cbufsize = bufsize; + char *cbuf = buf + offset; + apr_size_t cbufsize = bufsize - offset; while (1) { ++cfp->line_number; rc = cfp->getstr(cbuf, cbufsize, cfp->param); if (rc == APR_EOF) { - if (cbuf != buf) { + if (cbuf != buf + offset) { *cbuf = '\0'; break; } @@ -1001,11 +1054,11 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize, */ cp = cbuf; cp += strlen(cp); - if (cp > cbuf && cp[-1] == LF) { + if (cp > buf && cp[-1] == LF) { cp--; - if (cp > cbuf && cp[-1] == CR) + if (cp > buf && cp[-1] == CR) cp--; - if (cp > cbuf && cp[-1] == '\\') { + if (cp > buf && cp[-1] == '\\') { cp--; /* * line continuation requested - @@ -1023,19 +1076,19 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize, } } else { /* No "get string" function defined; read character by character */ - apr_size_t i = 0; + apr_size_t i = offset; if (bufsize < 2) { /* too small, assume caller is crazy */ return APR_EINVAL; } - buf[0] = '\0'; + buf[offset] = '\0'; while (1) { char c; rc = cfp->getch(&c, cfp->param); if (rc == APR_EOF) { - if (i > 0) + if (i > offset) break; else return APR_EOF; @@ -1053,11 +1106,11 @@ static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize, break; } } - else if (i >= bufsize - 2) { - return APR_ENOSPC; - } buf[i] = c; ++i; + if (i >= bufsize - 1) { + return APR_ENOSPC; + } } buf[i] = '\0'; } @@ -1091,7 +1144,7 @@ static int cfg_trim_line(char *buf) AP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, apr_size_t bufsize, ap_configfile_t *cfp) { - apr_status_t rc = ap_cfg_getline_core(buf, bufsize, cfp); + apr_status_t rc = ap_cfg_getline_core(buf, bufsize, 0, cfp); if (rc == APR_SUCCESS) cfg_trim_line(buf); return rc; @@ -1118,7 +1171,7 @@ AP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb, } for (;;) { - rc = ap_cfg_getline_core(vb->buf + vb->strlen, vb->avail - vb->strlen, cfp); + rc = ap_cfg_getline_core(vb->buf, vb->avail, vb->strlen, cfp); if (rc == APR_ENOSPC || rc == APR_SUCCESS) vb->strlen += strlen(vb->buf + vb->strlen); if (rc != APR_ENOSPC) @@ -1451,6 +1504,95 @@ AP_DECLARE(int) ap_find_etag_weak(apr_pool_t *p, const char *line, return find_list_item(p, line, tok, AP_ETAG_WEAK); } +/* Grab a list of tokens of the format 1#token (from RFC7230) */ +AP_DECLARE(const char *) ap_parse_token_list_strict(apr_pool_t *p, + const char *str_in, + apr_array_header_t **tokens, + int skip_invalid) +{ + int in_leading_space = 1; + int in_trailing_space = 0; + int string_end = 0; + const char *tok_begin; + const char *cur; + + if (!str_in) { + return NULL; + } + + tok_begin = cur = str_in; + + while (!string_end) { + const unsigned char c = (unsigned char)*cur; + + if (!TEST_CHAR(c, T_HTTP_TOKEN_STOP) && c != '\0') { + /* Non-separator character; we are finished with leading + * whitespace. We must never have encountered any trailing + * whitespace before the delimiter (comma) */ + in_leading_space = 0; + if (in_trailing_space) { + return "Encountered illegal whitespace in token"; + } + } + else if (c == ' ' || c == '\t') { + /* "Linear whitespace" only includes ASCII CRLF, space, and tab; + * we can't get a CRLF since headers are split on them already, + * so only look for a space or a tab */ + if (in_leading_space) { + /* We're still in leading whitespace */ + ++tok_begin; + } + else { + /* We must be in trailing whitespace */ + ++in_trailing_space; + } + } + else if (c == ',' || c == '\0') { + if (!in_leading_space) { + /* If we're out of the leading space, we know we've read some + * characters of a token */ + if (*tokens == NULL) { + *tokens = apr_array_make(p, 4, sizeof(char *)); + } + APR_ARRAY_PUSH(*tokens, char *) = + apr_pstrmemdup((*tokens)->pool, tok_begin, + (cur - tok_begin) - in_trailing_space); + } + /* We're allowed to have null elements, just don't add them to the + * array */ + + tok_begin = cur + 1; + in_leading_space = 1; + in_trailing_space = 0; + string_end = (c == '\0'); + } + else { + /* Encountered illegal separator char */ + if (skip_invalid) { + /* Skip to the next separator */ + const char *temp; + temp = ap_strchr_c(cur, ','); + if(!temp) { + temp = ap_strchr_c(cur, '\0'); + } + + /* Act like we haven't seen a token so we reset */ + cur = temp - 1; + in_leading_space = 1; + in_trailing_space = 0; + } + else { + return apr_psprintf(p, "Encountered illegal separator " + "'\\x%.2x'", (unsigned int)c); + } + } + + ++cur; + } + + return NULL; +} + /* 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 @@ -1585,7 +1727,7 @@ AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str) static char x2c(const char *what) { - register char digit; + char digit; #if !APR_CHARSET_EBCDIC digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 @@ -1617,7 +1759,7 @@ static char x2c(const char *what) static int unescape_url(char *url, const char *forbid, const char *reserved) { - register int badesc, badpath; + int badesc, badpath; char *x, *y; badesc = 0; @@ -2100,11 +2242,11 @@ AP_DECLARE(char *) ap_make_full_path(apr_pool_t *a, const char *src1, */ AP_DECLARE(int) ap_is_url(const char *u) { - register int x; + int x; for (x = 0; u[x] != ':'; x++) { if ((!u[x]) || - ((!apr_isalpha(u[x])) && (!apr_isdigit(u[x])) && + ((!apr_isalnum(u[x])) && (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) { return 0; } @@ -2521,7 +2663,7 @@ AP_DECLARE(int) ap_parse_form_data(request_rec *r, ap_filter_t *f, APR_BLOCK_READ, HUGE_STRING_LEN); if (rv != APR_SUCCESS) { apr_brigade_destroy(bb); - return (rv == AP_FILTER_ERROR) ? rv : HTTP_BAD_REQUEST; + return ap_map_http_request_error(rv, HTTP_BAD_REQUEST); } for (bucket = APR_BRIGADE_FIRST(bb); @@ -3005,3 +3147,153 @@ AP_DECLARE(char *) ap_get_exec_line(apr_pool_t *p, return apr_pstrndup(p, buf, k); } + +AP_DECLARE(int) ap_array_str_index(const apr_array_header_t *array, + const char *s, + int start) +{ + if (start >= 0) { + int i; + + for (i = start; i < array->nelts; i++) { + const char *p = APR_ARRAY_IDX(array, i, const char *); + if (!strcmp(p, s)) { + return i; + } + } + } + + return -1; +} + +AP_DECLARE(int) ap_array_str_contains(const apr_array_header_t *array, + const char *s) +{ + return (ap_array_str_index(array, s, 0) >= 0); +} + +#if !APR_CHARSET_EBCDIC +/* + * Our own known-fast translation table for casecmp by character. + * Only ASCII alpha characters 41-5A are folded to 61-7A, other + * octets (such as extended latin alphabetics) are never case-folded. + * NOTE: Other than Alpha A-Z/a-z, each code point is unique! + */ +static const short ucharmap[] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, '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', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, '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', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; +#else /* APR_CHARSET_EBCDIC */ +/* + * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison, + * provides unique identity of every char value (strict ISO-646 + * conformance, arbitrary election of an ISO-8859-1 ordering, and + * very arbitrary control code assignments into C1 to achieve + * identity and a reversible mapping of code points), + * then folding the equivalences of ASCII 41-5A into 61-7A, + * presenting comparison results in a somewhat ISO/IEC 10646 + * (ASCII-like) order, depending on the EBCDIC code page in use. + * + * NOTE: Other than Alpha A-Z/a-z, each code point is unique! + */ +static const short ucharmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, + 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, + 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, + 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, + 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, + 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, + 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, + 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, + 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, + 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, + 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, + 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, + 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, + 0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F +}; +#endif + +AP_DECLARE(int) ap_cstr_casecmp(const char *s1, const char *s2) +{ + const unsigned char *str1 = (const unsigned char *)s1; + const unsigned char *str2 = (const unsigned char *)s2; + for (;;) + { + const int c1 = (int)(*str1); + const int c2 = (int)(*str2); + const int cmp = ucharmap[c1] - ucharmap[c2]; + /* Not necessary to test for !c2, this is caught by cmp */ + if (cmp || !c1) + return cmp; + str1++; + str2++; + } +} + +AP_DECLARE(int) ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n) +{ + const unsigned char *str1 = (const unsigned char *)s1; + const unsigned char *str2 = (const unsigned char *)s2; + while (n--) + { + const int c1 = (int)(*str1); + const int c2 = (int)(*str2); + const int cmp = ucharmap[c1] - ucharmap[c2]; + /* Not necessary to test for !c2, this is caught by cmp */ + if (cmp || !c1) + return cmp; + str1++; + str2++; + } + return 0; +} + |