/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* A bunch of functions in util.c scan strings looking for certain characters. *Tomakethatmoreefficientweencodealookuptable.Thetest_char_table *isgeneratedautomaticallybygen_test_char.c.
*/ #include"test_char.h"
/* we know core's module_index is 0 */ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
/* maximum nesting level for config directories */ #ifndef AP_MAX_FNMATCH_DIR_DEPTH #define AP_MAX_FNMATCH_DIR_DEPTH (128) #endif
/* Roy owes Rob beer. */ /* Rob owes Roy dinner. */
/* These legacy comments would make a lot more sense if Roy hadn't *replacedtheoldlater_than()routinewithutil_date.c. * *Well,okay,theystillwouldn'tmakeanysense.
*/
/* *Similartostandardstrstr()butweignorecaseinthisversion. *Basedonthestrstr()implementationfurtherbelow.
*/
AP_DECLARE(char *) ap_strcasestr(constchar *s1, constchar *s2)
{ char *p1, *p2; if (*s2 == '\0') { /* an empty s2 */ return((char *)s1);
} while(1) { for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++); if (*s1 == '\0') { return(NULL);
} /* found first character of s2, see if the rest matches */
p1 = (char *)s1;
p2 = (char *)s2; for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) { if (*p1 == '\0') { /* both strings ended together */ return((char *)s1);
}
} if (*p2 == '\0') { /* second string ended, a match */ break;
} /* didn't find a match here, try starting at next character in s1 */
s1++;
} return((char *)s1);
}
#define IS_SLASH_OR_NUL(s) (s == '\0' || AP_IS_SLASH(s))
/* *Inspiredbymod_jk'sjk_servlet_normalize().
*/
AP_DECLARE(int) ap_normalize_path(char *path, unsignedint flags)
{ int ret = 1;
apr_size_t l = 1, w = 1, n; int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0; int merge_slashes = (flags & AP_NORMALIZE_MERGE_SLASHES) != 0;
if (!AP_IS_SLASH(path[0])) { /* Besides "OPTIONS *", a request-target should start with '/' *perRFC7230section5.3,soanythingelseisinvalid.
*/ if (path[0] == '*' && path[1] == '\0') { return1;
} /* However, AP_NORMALIZE_ALLOW_RELATIVE can be used to bypass *thisrestriction(e.g.forsubrequestfilelookups).
*/ if (!(flags & AP_NORMALIZE_ALLOW_RELATIVE) || path[0] == '\0') { return0;
}
l = w = 0;
}
while (path[l] != '\0') { /* RFC-3986 section 2.3: *Forconsistency,percent-encodedoctetsintherangesof *ALPHA(%41-%5Aand%61-%7A),DIGIT(%30-%39),hyphen(%2D), *period(%2E),underscore(%5F),ortilde(%7E)should[...] *bedecodedtotheircorrespondingunreservedcharactersby *URInormalizers.
*/ if (decode_unreserved && path[l] == '%') { if (apr_isxdigit(path[l + 1]) && apr_isxdigit(path[l + 2])) { constchar c = x2c(&path[l + 1]); if (TEST_CHAR(c, T_URI_UNRESERVED)) { /* Replace last char and fall through as the current
* read position */
l += 2;
path[l] = c;
}
} else { /* Invalid encoding */
ret = 0;
}
}
if (w == 0 || AP_IS_SLASH(path[w - 1])) { /* Collapse ///// sequences to / */ if (merge_slashes && AP_IS_SLASH(path[l])) { do {
l++;
} while (AP_IS_SLASH(path[l])); continue;
}
if (path[l] == '.') { /* Remove /./ segments */ if (IS_SLASH_OR_NUL(path[l + 1])) {
l++; if (path[l]) {
l++;
} continue;
}
/* Remove /xx/../ segments (or /xx/.%2e/ when *AP_NORMALIZE_DECODE_UNRESERVEDissetsincewe *decodedonlythefirstdotabove).
*/
n = l + 1; if ((path[n] == '.' || (decode_unreserved
&& path[n] == '%'
&& path[++n] == '2'
&& (path[++n] == 'e'
|| path[n] == 'E')))
&& IS_SLASH_OR_NUL(path[n + 1])) { /* Wind w back to remove the previous segment */ if (w > 1) { do {
w--;
} while (w && !AP_IS_SLASH(path[w - 1]));
} else { /* Already at root, ignore and return a failure *ifaskedto.
*/ if (flags & AP_NORMALIZE_NOT_ABOVE_ROOT) {
ret = 0;
}
}
/* Move l forward to the next segment */
l = n + 1; if (path[l]) {
l++;
} continue;
}
}
}
/* we can't use apr_file_* directly because of linking issues on Windows */ static apr_status_t cfg_close(void *param)
{ return apr_file_close(param);
}
if (rc == APR_ENOSPC) return apr_psprintf(p, "Error reading %s at line %d: Line too long",
cfp->name, cfp->line_number);
return apr_psprintf(p, "Error reading %s at line %d: %pm",
cfp->name, cfp->line_number, &rc);
}
/* 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,
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 + 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 + offset) {
*cbuf = '\0'; break;
} else { return APR_EOF;
}
} if (rc != APR_SUCCESS) { return rc;
}
/* *checkforlinecontinuation, *i.e.match[^\\]\\[\r]\nonly
*/
cp = cbuf;
cp += strlen(cp); if (cp > buf && cp[-1] == LF) {
cp--; if (cp > buf && cp[-1] == CR)
cp--; if (cp > buf && cp[-1] == '\\') {
cp--; /* *linecontinuationrequested- *thenremovebackslashandcontinue
*/
cbufsize -= (cp-cbuf);
cbuf = cp; continue;
}
} elseif (cp - buf >= bufsize - 1) { return APR_ENOSPC;
} break;
}
} else { /* No "get string" function defined; read character by character */
apr_size_t i = offset;
if (bufsize < 2) { /* too small, assume caller is crazy */ return APR_EINVAL;
}
buf[offset] = '\0';
while (1) { char c;
rc = cfp->getch(&c, cfp->param); if (rc == APR_EOF) { if (i > offset) break; else return APR_EOF;
} if (rc != APR_SUCCESS) return rc; if (c == LF) {
++cfp->line_number; /* check for line continuation */ if (i > 0 && buf[i-1] == '\\') {
i--; continue;
} else { break;
}
}
buf[i] = c;
++i; if (i >= bufsize - 1) { return APR_ENOSPC;
}
}
buf[i] = '\0';
} return APR_SUCCESS;
}
staticint cfg_trim_line(char *buf)
{ char *start, *end; /* *Leadingandtrailingwhitespaceiseliminatedcompletely
*/
start = buf; while (apr_isspace(*start))
++start; /* blast trailing whitespace */
end = &start[strlen(start)]; while (--end >= start && apr_isspace(*end))
*end = '\0'; /* Zap leading whitespace by shifting */ if (start != buf)
memmove(buf, start, end - start + 2); #ifdef DEBUG_CFG_LINES
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, APLOGNO(00555) "Read config: '%s'", buf); #endif return end - start + 1;
}
/* 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 */
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, 0, cfp); if (rc == APR_SUCCESS)
cfg_trim_line(buf); return rc;
}
for (;;) {
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) break; if (vb->avail >= max_len) return APR_ENOSPC;
new_len = vb->avail * 2; if (new_len > max_len)
new_len = max_len;
ap_varbuf_grow(vb, new_len);
--cfp->line_number;
} if (vb->strlen > max_len) return APR_ENOSPC; if (rc == APR_SUCCESS)
vb->strlen = cfg_trim_line(vb->buf); return rc;
}
/* Size an HTTP header field list item, as separated by a comma. *Thereturnvalueisapointertothebeginningofthenon-emptylistitem *withintheoriginalstring(orNULLifthereisnone)andtheaddress *offieldisshiftedtothenextnon-comma,non-whitespacecharacter. *lenisthelengthoftheitemexcludinganybeginningwhitespace.
*/
AP_DECLARE(constchar *) ap_size_list_item(constchar **field, int *len)
{ constunsignedchar *ptr = (constunsignedchar *)*field; constunsignedchar *token; int in_qpair, in_qstr, in_com;
/* Find first non-comma, non-whitespace byte */
while (*ptr == ',' || apr_isspace(*ptr))
++ptr;
token = ptr;
/* Find the end of this item, skipping over dead bits */
/* Retrieve an HTTP header field list item, as separated by a comma, *whilestrippinginsignificantwhitespaceandlowercasinganythingnotin *aquotedstringorcomment.Thereturnvalueisanewstringcontaining *theconvertedlistitem(orNULLifnone)andtheaddresspointedtoby *fieldisshiftedtothenextnon-comma,non-whitespace.
*/
AP_DECLARE(char *) ap_get_list_item(apr_pool_t *p, constchar **field)
{ constchar *tok_start; constunsignedchar *ptr; unsignedchar *pos; char *token; int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
/* Find the beginning and maximum length of the list item so that *wecanallocateabufferforthenewstringandresetthefield.
*/ if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) { return NULL;
}
token = apr_palloc(p, tok_len + 1);
/* Scan the token again, but this time copy only the good bytes. *Weskipextrawhitespaceandanywhitespacearounda'=','/', *or';'andlowercasenormalcharactersnotwithinacomment, *quoted-stringorquoted-pair.
*/ for (ptr = (constunsignedchar *)tok_start, pos = (unsignedchar *)token;
*ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
++ptr) {
/* Find an item in canonical form (lowercase, no extra spaces) within *anHTTPfieldvaluelist.Returns1iffound,0ifnotfound. *Thiswouldbemuchmoreefficientifwestoredheaderfieldsas *anarrayoflistitemsastheyarereceivedinsteadofaplainstring.
*/ staticint find_list_item(apr_pool_t *p, constchar *line, constchar *tok, ap_etag_e type)
{ constunsignedchar *pos; constunsignedchar *ptr = (constunsignedchar *)line; int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
if (!line || !tok) { return0;
} if (type == AP_ETAG_STRONG && *tok != '\"') { return0;
} if (type == AP_ETAG_WEAK) { if (*tok == 'W' && (*(tok+1)) == '/' && (*(tok+2)) == '\"') {
tok += 2;
} elseif (*tok != '\"') { return0;
}
}
do { /* loop for each item in line's list */
/* Find first non-comma, non-whitespace byte */ while (*ptr == ',' || apr_isspace(*ptr)) {
++ptr;
}
/* Account for strong or weak Etags, depending on our search */ if (type == AP_ETAG_STRONG && *ptr != '\"') { break;
} if (type == AP_ETAG_WEAK) { if (*ptr == 'W' && (*(ptr+1)) == '/' && (*(ptr+2)) == '\"') {
ptr += 2;
} elseif (*ptr != '\"') { break;
}
}
if (*ptr)
good = 1; /* until proven otherwise for this item */ else break; /* no items left and nothing good found */
/* We skip extra whitespace and any whitespace around a '=', '/', *or';'andlowercasenormalcharactersnotwithinacomment, *quoted-stringorquoted-pair.
*/ for (pos = (constunsignedchar *)tok;
*ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
++ptr) {
if (in_qpair) {
in_qpair = 0; if (good)
good = (*pos++ == *ptr);
} else { switch (*ptr) { case'\\': in_qpair = 1; if (addspace == 1)
good = good && (*pos++ == ' ');
good = good && (*pos++ == *ptr);
addspace = 0; break; case'"' : if (!in_com)
in_qstr = !in_qstr; if (addspace == 1)
good = good && (*pos++ == ' ');
good = good && (*pos++ == *ptr);
addspace = 0; break; case'(' : if (!in_qstr)
++in_com; if (addspace == 1)
good = good && (*pos++ == ' ');
good = good && (*pos++ == *ptr);
addspace = 0; break; case')' : if (in_com)
--in_com;
good = good && (*pos++ == *ptr);
addspace = 0; break; case' ' : case'\t': if (addspace || !good) break; if (in_com || in_qstr)
good = (*pos++ == *ptr); else
addspace = 1; break; case'=' : case'/' : case';' : if (!(in_com || in_qstr))
addspace = -1;
good = good && (*pos++ == *ptr); break; default : if (!good) break; if (addspace == 1)
good = (*pos++ == ' '); if (in_com || in_qstr)
good = good && (*pos++ == *ptr); else
good = good
&& (apr_tolower(*pos++) == apr_tolower(*ptr));
addspace = 0; break;
}
}
} if (good && *pos)
good = 0; /* not good if only a prefix was matched */
} while (*ptr && !good);
return good;
}
/* Find an item in canonical form (lowercase, no extra spaces) within *anHTTPfieldvaluelist.Returns1iffound,0ifnotfound. *Thiswouldbemuchmoreefficientifwestoredheaderfieldsas *anarrayoflistitemsastheyarereceivedinsteadofaplainstring.
*/
AP_DECLARE(int) ap_find_list_item(apr_pool_t *p, constchar *line, constchar *tok)
{ return find_list_item(p, line, tok, AP_ETAG_NONE);
}
/* Find a strong Etag in canonical form (lowercase, no extra spaces) within *anHTTPfieldvaluelist.Returns1iffound,0ifnotfound.
*/
AP_DECLARE(int) ap_find_etag_strong(apr_pool_t *p, constchar *line, constchar *tok)
{ return find_list_item(p, line, tok, AP_ETAG_STRONG);
}
/* Find a weak ETag in canonical form (lowercase, no extra spaces) within *anHTTPfieldvaluelist.Returns1iffound,0ifnotfound.
*/
AP_DECLARE(int) ap_find_etag_weak(apr_pool_t *p, constchar *line, constchar *tok)
{ return find_list_item(p, line, tok, AP_ETAG_WEAK);
}
/* Grab a list of tokens of the format 1#token (from RFC7230) */
AP_DECLARE(constchar *) ap_parse_token_list_strict(apr_pool_t *p, constchar *str_in,
apr_array_header_t **tokens, int skip_invalid)
{ int in_leading_space = 1; int in_trailing_space = 0; int string_end = 0; constchar *tok_begin; constchar *cur;
if (!str_in) { return NULL;
}
tok_begin = cur = str_in;
while (!string_end) { constunsignedchar c = (unsignedchar)*cur;
if (!TEST_CHAR(c, T_HTTP_TOKEN_STOP)) { /* Non-separator character; we are finished with leading *whitespace.Wemustneverhaveencounteredanytrailing
* whitespace before the delimiter (comma) */
in_leading_space = 0; if (in_trailing_space) { return"Encountered illegal whitespace in token";
}
} elseif (c == ' ' || c == '\t') { /* "Linear whitespace" only includes ASCII CRLF, space, and tab; *wecan'tgetaCRLFsinceheadersaresplitonthemalready,
* 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;
}
} elseif (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 */ constchar *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'", (unsignedint)c);
}
}
++cur;
}
return NULL;
}
/* Scan a string for HTTP VCHAR/obs-text characters including HT and SP *(asusedinheadervalues,forexample,inRFC7230section3.2) *returningthepointertothefirstnon-HTASCIIctrlcharacter.
*/
AP_DECLARE(constchar *) ap_scan_http_field_content(constchar *ptr)
{ for ( ; !TEST_CHAR(*ptr, T_HTTP_CTRLS); ++ptr) ;
return ptr;
}
/* Scan a string for HTTP token characters, returning the pointer to *thefirstnon-tokencharacter.
*/
AP_DECLARE(constchar *) ap_scan_http_token(constchar *ptr)
{ for ( ; !TEST_CHAR(*ptr, T_HTTP_TOKEN_STOP); ++ptr) ;
return ptr;
}
/* Scan a string for visible ASCII (0x21-0x7E) or obstext (0x80+) *andreturnapointertothefirstctrl/spacecharacterencountered.
*/
AP_DECLARE(constchar *) ap_scan_vchar_obstext(constchar *ptr)
{ for ( ; TEST_CHAR(*ptr, T_VCHAR_OBSTEXT); ++ptr) ;
return ptr;
}
/* Retrieve a token, spacing over it and returning a pointer to *thefirstnon-whitebyteafterwards.Notethatthesetokens *aredelimitedbysemisandcommas;andcanalsobedelimited *bywhitespaceatthecaller'soption.
*/
/* c2x takes an unsigned, and expects the caller has guaranteed that *0<=what<256...whichusuallymeansthatyouhavetocastto *unsignedcharfirst,because(unsigned)(char)(x)firstgoesthrough *signedextensiontoanintbeforetheunsignedcast. * *Thereasonforthisassumptionistoassistgcccodegeneration-- *theunsignedchar->unsignedextensionisalreadydoneearlierin *bothusesofthiscode,sothere'snoneedtowastetimedoingit *again.
*/ staticconstchar c2x_table[] = "0123456789abcdef";
/* Compute how many characters need to be escaped */
s = (constunsignedchar *)str; for (; *s; ++s) { if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
escapes++;
}
}
/* Compute the length of the input string, including NULL */
length = s - (constunsignedchar *)str + 1;
/* Fast path: nothing to escape */ if (escapes == 0) { return apr_pmemdup(p, str, length);
}
/* Each escaped character needs up to 3 extra bytes (0 --> \x00) */
ret = apr_palloc(p, length + 3 * escapes);
d = (unsignedchar *)ret;
s = (constunsignedchar *)str; for (; *s; ++s) { if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
*d++ = '\\'; switch(*s) { case'\b':
*d++ = 'b'; break; case'\n':
*d++ = 'n'; break; case'\r':
*d++ = 'r'; break; case'\t':
*d++ = 't'; break; case'\v':
*d++ = 'v'; break; case'\\': case'"':
*d++ = *s; break; default:
c2x(*s, 'x', d);
d += 3;
}
} else {
*d++ = *s;
}
}
*d = '\0';
if (!server_hostname)
server_hostname = apr_pstrdup(a, "127.0.0.1");
ap_log_perror(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, a, APLOGNO(00558) "%s: Could not reliably determine the server's fully qualified " "domain name, using %s. Set the 'ServerName' directive globally " "to suppress this message",
ap_server_argv0, server_hostname);
/* How large will the string become, once we escaped all the quotes? *Thetrickycasesare *-an`instring`thatisalreadylongerthan`ptrdiff_t` *canhold(whichisanundefinedcaseinC,asCdefinesptrdiff_tas *asigneddifferencebetweenpointersintothesamearrayandoneindex *beyond). *-an`instring`that,includingthe`extra`charswewanttoadd,becomes *evenlargerthanapr_size_tcanhandle. *SincethisfunctionwasnotdesignedtoeverreturnNULLforfailure,we *canonlytriggerahardassertionfailure.Itseemsmoreaprogramming *mistake(orfailuretoverifytheinputcausingthis)thatleadstothis *situation.
*/
ap_assert(inchr - instring > 0);
size = ((apr_size_t)(inchr - instring)) + 1;
ap_assert(size + extra > size);
/* sanity check - we only support forms for now */
ct = apr_table_get(r->headers_in, "Content-Type"); if (!ct || ap_cstr_casecmpn("application/x-www-form-urlencoded", ct, 33)) { return ap_discard_request_body(r);
}
if (new_len < 2 * vb->avail && vb->avail < VARBUF_MAX_SIZE/2) { /* at least double the size, to avoid repeated reallocations */
new_len = 2 * vb->avail;
} elseif (new_len > VARBUF_MAX_SIZE) {
apr_abortfunc_t abort_fn = apr_pool_abort_get(vb->pool);
ap_assert(abort_fn != NULL);
abort_fn(APR_ENOMEM); return;
}
new_len++; /* add space for trailing \0 */ if (new_len <= VARBUF_SMALL_SIZE) {
new_len = APR_ALIGN_DEFAULT(new_len); new = apr_palloc(vb->pool, new_len); if (vb->avail && vb->strlen != 0) {
AP_DEBUG_ASSERT(vb->buf != NULL);
AP_DEBUG_ASSERT(vb->buf != varbuf_empty); if (new == vb->buf + vb->avail + 1) { /* We are lucky: the new memory lies directly after our old *buffer,wecannowuseboth.
*/
vb->avail += new_len; return;
} else { /* copy up to vb->strlen + 1 bytes */
memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ?
vb->avail + 1 : vb->strlen + 1);
}
} else {
*new = '\0';
}
vb->avail = new_len - 1;
vb->buf = new; return;
}
/* The required block is rather larger. Use allocator directly so that
* the memory can be freed independently from the pool. */
allocator = apr_pool_allocator_get(vb->pool); /* Happens if APR was compiled with APR_POOL_DEBUG */ if (allocator == NULL) {
apr_allocator_create(&allocator);
ap_assert(allocator != NULL);
} if (new_len <= VARBUF_MAX_SIZE)
new_node = apr_allocator_alloc(allocator,
new_len + APR_ALIGN_DEFAULT(sizeof(*new_info))); if (!new_node) {
apr_abortfunc_t abort_fn = apr_pool_abort_get(vb->pool);
ap_assert(abort_fn != NULL);
abort_fn(APR_ENOMEM); return;
}
new_info = (struct ap_varbuf_info *)new_node->first_avail;
new_node->first_avail += APR_ALIGN_DEFAULT(sizeof(*new_info));
new_info->node = new_node;
new_info->allocator = allocator; new = new_node->first_avail;
AP_DEBUG_ASSERT(new_node->endp - new_node->first_avail >= new_len);
new_len = new_node->endp - new_node->first_avail;
/* Create an apr_thread_t for the main child thread to set up its Thread *LocalStorage.Sinceit'sdetachedandwon'tapr_thread_exit(),destroy *itspoolbeforeexitingviaacleanupofthegivenpool.
*/ if ((rv = apr_threadattr_create(&attr, pool))
|| (rv = apr_threadattr_detach_set(attr, 1))
|| (rv = ap_thread_current_create(thread, attr, pool))) {
*thread = NULL; return rv;
}
AP_DECLARE(void) ap_get_sload(ap_sload_t *ld)
{ int i, j, server_limit, thread_limit; int ready = 0; int busy = 0; int total;
ap_generation_t mpm_generation;
if (++w->depth > AP_MAX_FNMATCH_DIR_DEPTH) { return apr_psprintf(w->p, "%sDirectory '%s' exceeds the maximum include " "directory nesting level of %u. You have " "probably a recursion somewhere.", w->prefix ? w->prefix : "", path,
AP_MAX_FNMATCH_DIR_DEPTH);
}
/* *Nowrecursethese...wehandleerrorsandsubdirectories *viatherecursion,whichisnice
*/ for (current = 0; current < candidates->nelts; ++current) {
fnew = &((fnames *) candidates->elts)[current];
error = ap_dir_nofnmatch(w, fnew->fname); if (error) { return error;
}
}
}
w->depth--;
return NULL;
} elseif (w->flags & AP_DIR_FLAG_OPTIONAL) { /* If the optional flag is set (like for IncludeOptional) we can *toleratethatnofileordirectoryispresentandbailout.
*/
apr_finfo_t finfo; if (apr_stat(&finfo, fname, APR_FINFO_TYPE, w->ptemp) != APR_SUCCESS
|| finfo.filetype == APR_NOFILE) return NULL;
}
if (!(w->flags & AP_DIR_FLAG_OPTIONAL)) { return apr_psprintf(w->p, "%sNo matches for the wildcard '%s' in '%s', failing",
w->prefix ? w->prefix : "", fname, path);
}
}
return NULL;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.105Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.