/* 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.
*/
/* Server core module... This module provides support for really basic * server operations, including options and commands which control the * operation of other modules. Consider this the bureaucracy module. * * The core module also defines handlers, etc., to handle just enough * to allow a server with the core module ONLY to actually serve documents. * * This file could almost be mod_core.c, except for the stuff which affects * the http_conf_globals.
*/
/* we know core's module_index is 0 */ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
/* Provide ap_document_root_check storage and default value = true */
AP_DECLARE_DATA int ap_document_root_check = 1;
/* magic pointer for ErrorDocument xxx "default" */ staticchar errordocument_default;
/* Global state allocated out of pconf: variables here MUST be * cleared/reset in reset_config(), a pconf cleanup, to avoid the
* variable getting reused after the pool is cleared. */ static apr_array_header_t *saved_server_config_defines = NULL; static apr_table_t *server_config_defined_vars = NULL;
AP_DECLARE_DATA constchar *ap_runtime_dir = NULL;
AP_DECLARE_DATA int ap_main_state = AP_SQ_MS_INITIAL_STARTUP;
AP_DECLARE_DATA int ap_run_mode = AP_SQ_RM_UNKNOWN;
AP_DECLARE_DATA int ap_config_generation = 0;
/* Create this conf by duplicating the base, replacing elements * (or creating copies for merging) where new-> values exist.
*/
conf = (core_dir_config *)apr_pmemdup(a, base, sizeof(core_dir_config));
if (new->opts & OPT_UNSET) { /* there was no explicit setting of new->opts, so we merge * preserve the invariant (opts_add & opts_remove) == 0
*/
conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
conf->opts_remove = (conf->opts_remove & ~new->opts_add)
| new->opts_remove;
conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
/* If Includes was enabled with exec in the base config, but * was enabled without exec in the new config, then disable
* exec in the merged set. */ if (((base->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC))
== (OPT_INCLUDES|OPT_INC_WITH_EXEC))
&& ((new->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC))
== OPT_INCLUDES)) {
conf->opts &= ~OPT_INC_WITH_EXEC;
}
} else { /* otherwise we just copy, because an explicit opts setting * overrides all earlier +/- modifiers
*/
conf->opts = new->opts;
conf->opts_add = new->opts_add;
conf->opts_remove = new->opts_remove;
}
if (!(new->override & OR_UNSET)) {
conf->override = new->override;
}
if (!(new->override_opts & OPT_UNSET)) {
conf->override_opts = new->override_opts;
}
if (new->override_list != NULL) {
conf->override_list = new->override_list;
}
if (conf->response_code_exprs == NULL) {
conf->response_code_exprs = new->response_code_exprs;
} elseif (new->response_code_exprs != NULL) {
conf->response_code_exprs = apr_hash_overlay(a,
new->response_code_exprs, conf->response_code_exprs);
} /* Otherwise we simply use the base->response_code_exprs array
*/
if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
conf->hostname_lookups = new->hostname_lookups;
}
if (new->content_md5 != AP_CONTENT_MD5_UNSET) {
conf->content_md5 = new->content_md5;
}
if (new->accept_path_info != AP_ACCEPT_PATHINFO_UNSET) {
conf->accept_path_info = new->accept_path_info;
}
if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
conf->use_canonical_name = new->use_canonical_name;
}
if (new->use_canonical_phys_port != USE_CANONICAL_PHYS_PORT_UNSET) {
conf->use_canonical_phys_port = new->use_canonical_phys_port;
}
#ifdef RLIMIT_CPU if (new->limit_cpu) {
conf->limit_cpu = new->limit_cpu;
} #endif
#ifdef RLIMIT_NPROC if (new->limit_nproc) {
conf->limit_nproc = new->limit_nproc;
} #endif
if (new->limit_req_body != AP_LIMIT_REQ_BODY_UNSET) {
conf->limit_req_body = new->limit_req_body;
}
if (new->limit_xml_body != AP_LIMIT_UNSET)
conf->limit_xml_body = new->limit_xml_body;
if (!conf->sec_file) {
conf->sec_file = new->sec_file;
} elseif (new->sec_file) { /* If we merge, the merge-result must have its own array
*/
conf->sec_file = apr_array_append(a, base->sec_file, new->sec_file);
} /* Otherwise we simply use the base->sec_file array
*/
if (!conf->sec_if) {
conf->sec_if = new->sec_if;
} elseif (new->sec_if) { /* If we merge, the merge-result must have its own array
*/
conf->sec_if = apr_array_append(a, base->sec_if, new->sec_if);
} /* Otherwise we simply use the base->sec_if array
*/
if (new->server_signature != srv_sig_unset) {
conf->server_signature = new->server_signature;
}
if (!is_virtual) {
conf->ap_document_root = DOCUMENT_LOCATION;
conf->access_name = DEFAULT_ACCESS_FNAME;
/* A mapping only makes sense in the global context */
conf->accf_map = apr_table_make(a, 5); #if APR_HAS_SO_ACCEPTFILTER
apr_table_setn(conf->accf_map, "http", ACCEPT_FILTER_NAME);
apr_table_setn(conf->accf_map, "https", "dataready"); #elifdefined(WIN32) /* 'data' is disabled on Windows due to a DoS vuln (PR 59970) */
apr_table_setn(conf->accf_map, "http", "connect");
apr_table_setn(conf->accf_map, "https", "connect"); #else
apr_table_setn(conf->accf_map, "http", "data");
apr_table_setn(conf->accf_map, "https", "data"); #endif
conf->flush_max_threshold = AP_FLUSH_MAX_THRESHOLD;
conf->flush_max_pipelined = AP_FLUSH_MAX_PIPELINED;
} else { /* Use main ErrorLogFormat while the vhost is loading */
core_server_config *main_conf =
ap_get_core_module_config(ap_server_conf->module_config);
conf->error_log_format = main_conf->error_log_format;
conf->flush_max_pipelined = -1;
}
/* initialization, no special case for global context */
/* We need to do a stable sort, qsort isn't stable. So to make it stable * we'll be maintaining the original index into the list, and using it * as the minor key during sorting. The major key is the number of * components (where the root component is zero).
*/ struct reorder_sort_rec {
ap_conf_vector_t *elt; int orig_index;
};
/* a regex always sorts after a non-regex
*/ if (!core_a->r && core_b->r) { return -1;
} elseif (core_a->r && !core_b->r) { return 1;
}
/* we always sort next by the number of components
*/ if (core_a->d_components < core_b->d_components) { return -1;
} elseif (core_a->d_components > core_b->d_components) { return 1;
}
/* They have the same number of components, we now have to compare * the minor key to maintain the original order (from the config.)
*/ return a->orig_index - b->orig_index;
}
if (!nelts) { /* simple case of already being sorted... */ /* We're not checking this condition to be fast... we're checking * it to avoid trying to palloc zero bytes, which can trigger some * memory debuggers to barf
*/ return;
}
/* we have to allocate tmp space to do a stable sort */
apr_pool_create(&tmp, p);
apr_pool_tag(tmp, "core_reorder_directories");
sortbin = apr_palloc(tmp, sec_dir->nelts * sizeof(*sortbin)); for (i = 0; i < nelts; ++i) {
sortbin[i].orig_index = i;
sortbin[i].elt = elts[i];
}
/* and now copy back to the original array */ for (i = 0; i < nelts; ++i) {
elts[i] = sortbin[i].elt;
}
apr_pool_destroy(tmp);
}
/***************************************************************** * * There are some elements of the core config structures in which * other modules have a legitimate interest (this is ugly, but necessary * to preserve NCSA back-compatibility). So, we have a bunch of accessors * here...
*/
/* * Optional function coming from mod_authn_core, used for * retrieving the type of authorization
*/ static APR_OPTIONAL_FN_TYPE(authn_ap_auth_type) *authn_ap_auth_type;
/* * Optional function coming from mod_authn_core, used for * retrieving the authorization realm
*/ static APR_OPTIONAL_FN_TYPE(authn_ap_auth_name) *authn_ap_auth_name;
/* * Optional function coming from mod_access_compat, used to determine how access control interacts with authentication/authorization
*/ static APR_OPTIONAL_FN_TYPE(access_compat_ap_satisfies) *access_compat_ap_satisfies;
/* Should probably just get rid of this... the only code that cares is * part of the core anyway (and in fact, it isn't publicised to other * modules).
*/
/* alas, duplication required as we return not-const */ return apr_pstrdup(r->pool, response);
}
/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */ static APR_INLINE int do_double_reverse (int double_reverse, constchar *remote_host,
apr_sockaddr_t *client_addr,
apr_pool_t *pool)
{
apr_sockaddr_t *sa;
apr_status_t rv;
if (double_reverse) { /* already done */ return double_reverse;
}
if (remote_host == NULL || remote_host[0] == '\0') { /* single reverse failed, so don't bother */ return -1;
}
rv = apr_sockaddr_info_get(&sa, remote_host, APR_UNSPEC, 0, 0, pool); if (rv == APR_SUCCESS) { while (sa) { if (apr_sockaddr_equal(sa, client_addr)) { return 1;
}
sa = sa->next;
}
}
return -1;
}
AP_DECLARE(constchar *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type, int *str_is_ip)
{ int hostname_lookups; int ignored_str_is_ip;
if (!str_is_ip) { /* caller doesn't want to know */
str_is_ip = &ignored_str_is_ip;
}
*str_is_ip = 0;
/* If we haven't checked the host name, and we want to */ if (dir_config) {
hostname_lookups = ((core_dir_config *)ap_get_core_module_config(dir_config))
->hostname_lookups;
if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
hostname_lookups = HOSTNAME_LOOKUP_OFF;
}
} else { /* the default */
hostname_lookups = HOSTNAME_LOOKUP_OFF;
}
/* if failed, set it to the NULL string to indicate error */ if (conn->remote_host == NULL) {
conn->remote_host = "";
}
}
if (type == REMOTE_DOUBLE_REV) {
conn->double_reverse = do_double_reverse(conn->double_reverse,
conn->remote_host,
conn->client_addr, conn->pool); if (conn->double_reverse == -1) { return NULL;
}
}
/* * Return the desired information; either the remote DNS name, if found, * or either NULL (if the hostname was requested) or the IP address * (if any identifier was requested).
*/ if (conn->remote_host != NULL && conn->remote_host[0] != '\0') { return conn->remote_host;
} else { if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) { return NULL;
} else {
*str_is_ip = 1; return conn->client_ip;
}
}
}
AP_DECLARE(constchar *) ap_get_useragent_host(request_rec *r, int type, int *str_is_ip)
{
conn_rec *conn = r->connection; int hostname_lookups; int ignored_str_is_ip;
/* Guard here when examining the host before the read_request hook * has populated an r->useragent_addr
*/ if (!r->useragent_addr || (r->useragent_addr == conn->client_addr)) { return ap_get_remote_host(conn, r->per_dir_config, type, str_is_ip);
}
if (!str_is_ip) { /* caller doesn't want to know */
str_is_ip = &ignored_str_is_ip;
}
*str_is_ip = 0;
/* if failed, set it to the NULL string to indicate error */ if (r->useragent_host == NULL) {
r->useragent_host = "";
}
}
if (type == REMOTE_DOUBLE_REV) {
r->double_reverse = do_double_reverse(r->double_reverse,
r->useragent_host,
r->useragent_addr, r->pool); if (r->double_reverse == -1) { return NULL;
}
}
/* * Return the desired information; either the remote DNS name, if found, * or either NULL (if the hostname was requested) or the IP address * (if any identifier was requested).
*/ if (r->useragent_host != NULL && r->useragent_host[0] != '\0') { return r->useragent_host;
} else { if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) { return NULL;
} else {
*str_is_ip = 1; return r->useragent_ip;
}
}
}
/* * Optional function coming from mod_ident, used for looking up ident user
*/ static APR_OPTIONAL_FN_TYPE(ap_ident_lookup) *ident_lookup;
/* There are two options regarding what the "name" of a server is. The * "canonical" name as defined by ServerName and Port, or the "client's * name" as supplied by a possible Host: header or full URI. * * The DNS option to UseCanonicalName causes this routine to do a * reverse lookup on the local IP address of the connection and use * that for the ServerName. This makes its value more reliable while * at the same time allowing Demon's magic virtual hosting to work. * The assumption is that DNS lookups are sufficiently quick... * -- fanf 1998-10-03
*/
AP_DECLARE(constchar *) ap_get_server_name(request_rec *r)
{
conn_rec *conn = r->connection;
core_dir_config *d; constchar *retval;
d = (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
/* * Get the current server name from the request for the purposes * of using in a URL. If the server name is an IPv6 literal * address, it will be returned in URL format (e.g., "[fe80::1]").
*/
AP_DECLARE(constchar *) ap_get_server_name_for_url(request_rec *r)
{ constchar *plain_server_name = ap_get_server_name(r);
switch (d->use_canonical_name) { case USE_CANONICAL_NAME_OFF: case USE_CANONICAL_NAME_DNS: case USE_CANONICAL_NAME_UNSET: if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
port = r->parsed_uri.port_str ? r->parsed_uri.port :
r->connection->local_addr->port ? r->connection->local_addr->port :
r->server->port ? r->server->port :
ap_default_port(r); else/* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
port = r->parsed_uri.port_str ? r->parsed_uri.port :
r->server->port ? r->server->port :
ap_default_port(r); break; case USE_CANONICAL_NAME_ON: /* With UseCanonicalName on (and in all versions prior to 1.3) * Apache will use the hostname and port specified in the * ServerName directive to construct a canonical name for the * server. (If no port was specified in the ServerName * directive, Apache uses the port supplied by the client if * any is supplied, and finally the default port for the protocol * used.
*/ if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
port = r->server->port ? r->server->port :
r->connection->local_addr->port ? r->connection->local_addr->port :
ap_default_port(r); else/* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
port = r->server->port ? r->server->port :
ap_default_port(r); break; default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00110) "ap_get_server_port: Invalid UCN Option somehow");
port = ap_default_port(r); break;
}
/***************************************************************** * * Commands... this module handles almost all of the NCSA httpd.conf * commands, but most of the old srm.conf is in the modules.
*/
/* returns a parent if it matches the given directive */ staticconst ap_directive_t * find_parent(const ap_directive_t *dirp, constchar *what)
{ while (dirp->parent != NULL) {
dirp = dirp->parent;
/* ### it would be nice to have atom-ized directives */ if (ap_cstr_casecmp(dirp->directive, what) == 0) return dirp;
}
if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE) { if (cmd->path != NULL) { return apr_pstrcat(cmd->pool, cmd->cmd->name, gt, " cannot occur within directory context", NULL);
} if (cmd->cmd->req_override & EXEC_ON_READ) { /* EXEC_ON_READ must be NOT_IN_DIR_LOC_FILE, if not, it will * (deliberately) segfault below in the individual tests...
*/ return NULL;
}
}
s = ap_strchr_c(word, '$'); if (!s) { return word;
}
/* well, actually something to do */
ep = word + strlen(word);
spc = 0;
result = current = &(sresult[spc++]);
current->next = NULL;
current->string = word;
current->len = s - word;
outlen = current->len;
do { /* prepare next entry */ if (current->len) {
current->next = (spc < SMALL_EXPANSION)
? &(sresult[spc++])
: (struct sll *)apr_palloc(p, sizeof(*current->next));
current = current->next;
current->next = NULL;
current->len = 0;
}
if (*s == '$') { if (s[1] == '{' && (e = ap_strchr_c(s+2, '}'))) { char *name = apr_pstrmemdup(p, s+2, e-s-2);
word = NULL; if (server_config_defined_vars)
word = apr_table_get(server_config_defined_vars, name); if (!word)
word = apr_pstrdup(p, getenv(name)); if (word) {
current->string = word;
current->len = strlen(word);
outlen += current->len;
} else { if (ap_strchr(name, ':') == 0)
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(00111) "Config variable ${%s} is not defined",
name);
current->string = s;
current->len = e - s + 1;
outlen += current->len;
}
s = e + 1;
} else {
current->string = s++;
current->len = 1;
++outlen;
}
} else {
word = s;
s = ap_strchr_c(s, '$');
current->string = word;
current->len = s ? s - word : ep - word;
outlen += current->len;
}
} while (s && *s);
/* assemble result */
res_buf = cp = apr_palloc(p, outlen + 1); do { if (result->len) {
memcpy(cp, result->string, result->len);
cp += result->len;
}
result = result->next;
} while (result);
res_buf[outlen] = '\0';
/* * Make sure we can revert the effects of Define/UnDefine when restarting. * This function must be called once per loading of the config, before * ap_server_config_defines is changed. This may be during reading of the * config, which is even before the pre_config hook is run (due to * EXEC_ON_READ for Define/UnDefine).
*/ staticvoid init_config_defines(apr_pool_t *pconf)
{
saved_server_config_defines = ap_server_config_defines; /* Use apr_array_copy instead of apr_array_copy_hdr because it does not * protect from the way unset_define removes entries.
*/
ap_server_config_defines = apr_array_copy(pconf, ap_server_config_defines);
}
staticconstchar *set_define(cmd_parms *cmd, void *dummy, constchar *name, constchar *value)
{ constchar *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); if (err) return err; if (ap_strchr_c(name, ':') != NULL) { return"Variable name must not contain ':'";
}
if (!saved_server_config_defines) {
init_config_defines(cmd->pool);
} if (!ap_exists_config_define(name)) {
*(constchar **)apr_array_push(ap_server_config_defines) = name;
} if (value) { if (!server_config_defined_vars) {
server_config_defined_vars = apr_table_make(cmd->pool, 5);
}
apr_table_setn(server_config_defined_vars, name, value);
}
return NULL;
}
staticconstchar *unset_define(cmd_parms *cmd, void *dummy, constchar *name)
{ int i; constchar **defines; constchar *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); if (err) return err; if (ap_strchr_c(name, ':') != NULL) { return"Variable name must not contain ':'";
}
if (!saved_server_config_defines) {
init_config_defines(cmd->pool);
}
defines = (constchar **)ap_server_config_defines->elts; for (i = 0; i < ap_server_config_defines->nelts; i++) { if (strcmp(defines[i], name) == 0) {
defines[i] = *(constchar **)apr_array_pop(ap_server_config_defines); break;
}
}
if (server_config_defined_vars) {
apr_table_unset(server_config_defined_vars, name);
}
return NULL;
}
staticconstchar *generate_error(cmd_parms *cmd, void *dummy, constchar *arg)
{ if (!arg || !*arg) { return"The Error directive was used with no message.";
}
if (*arg == '"' || *arg == '\'') { /* strip off quotes */
apr_size_t len = strlen(arg); char last = *(arg + len - 1);
if (*arg == last) { return apr_pstrndup(cmd->pool, arg + 1, len - 2);
}
}
/* When ap_document_root_check is false; skip all the stuff below */ if (!ap_document_root_check) {
conf->ap_document_root = arg; return NULL;
}
/* Make it absolute, relative to ServerRoot */
arg = ap_server_root_relative(cmd->pool, arg); if (arg == NULL) { return"DocumentRoot must be a directory";
}
/* TODO: ap_configtestonly */ if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS
|| !ap_is_directory(cmd->temp_pool, arg)) { if (cmd->server->is_virtual) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0,
cmd->pool, APLOGNO(00112) "Warning: DocumentRoot [%s] does not exist",
arg);
conf->ap_document_root = arg;
} else { return apr_psprintf(cmd->pool, "DocumentRoot '%s' is not a directory, or is not readable",
arg);
}
} return NULL;
}
AP_DECLARE(void) ap_custom_response(request_rec *r, int status, constchar *string)
{
core_request_config *conf = ap_get_core_module_config(r->request_config); int idx;
/* 1st parameter should be a 3 digit number, which we recognize; * convert it into an array index
*/
error_number = atoi(errno_str);
idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
/* Heuristic to determine second argument. */ if (ap_strchr_c(msg,' '))
what = MSG; elseif (msg[0] == '/')
what = LOCAL_PATH; elseif (ap_is_url(msg))
what = REMOTE_PATH; else
what = MSG;
/* The entry should be ignored if it is a full URL for a 401 error */
if (error_number == 401 && what == REMOTE_PATH) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server, APLOGNO(00113) "%s:%d cannot use a full URL in a 401 ErrorDocument " "directive --- ignoring!", cmd->directive->filename, cmd->directive->line_num);
} else { /* Store it... */ if (conf->response_code_exprs == NULL) {
conf->response_code_exprs = apr_hash_make(cmd->pool);
}
if (ap_cstr_casecmp(msg, "default") == 0) { /* special case: ErrorDocument 404 default restores the * canned server error response
*/
apr_hash_set(conf->response_code_exprs,
apr_pmemdup(cmd->pool, &index_number, sizeof(index_number)), sizeof(index_number), &errordocument_default);
} else {
ap_expr_info_t *expr; constchar *expr_err = NULL;
/* hack. Prefix a " if it is a msg; as that is what * http_protocol.c relies on to distinguish between * a msg and a (local) path.
*/ constchar *response =
(what == MSG) ? apr_pstrcat(cmd->pool, "\"", msg, NULL) :
apr_pstrdup(cmd->pool, msg);
/* Throw a warning if we're in <Location> or <Files> */ if (ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_FILES)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00114) "Useless use of AllowOverride in line %d of %s.",
cmd->directive->line_num, cmd->directive->filename);
} if ((err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS)) != NULL) return err;
d->override = OR_NONE; while (l[0]) {
w = ap_getword_conf(cmd->temp_pool, &l);
k = w;
v = strchr(k, '='); if (v) {
*v++ = '\0';
}
staticconstchar *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
{
core_dir_config *d = d_; int i; constchar *err;
/* Throw a warning if we're in <Location> or <Files> */ if (ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_FILES)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00115) "Useless use of AllowOverrideList at %s:%d",
cmd->directive->filename, cmd->directive->line_num);
} if ((err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS)) != NULL) return err;
for (i = 0; i < argc; i++) { if (!ap_cstr_casecmp(argv[i], "None")) { if (argc != 1) { return"'None' not allowed with other directives in " "AllowOverrideList";
} return NULL;
} else { const command_rec *result = NULL;
module *mod = ap_top_module;
result = ap_find_command_in_modules(argv[i], &mod); if (result == NULL) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
APLOGNO(00116) "Discarding unrecognized " "directive `%s' in AllowOverrideList at %s:%d",
argv[i], cmd->directive->filename,
cmd->directive->line_num); continue;
} elseif ((result->req_override & (OR_ALL|ACCESS_CONF)) == 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
APLOGNO(02304) "Discarding directive `%s' not " "allowed in AllowOverrideList at %s:%d",
argv[i], cmd->directive->filename,
cmd->directive->line_num); continue;
} else {
apr_table_setn(d->override_list, argv[i], "1");
}
}
}
return NULL;
}
staticconstchar *set_options(cmd_parms *cmd, void *d_, constchar *l)
{
core_dir_config *d = d_;
allow_options_t opt; int first = 1; int merge = 0; int all_none = 0; char action;
if (*w == '+' || *w == '-') {
action = *(w++); if (!merge && !first && !all_none) { return"Either all Options must start with + or -, or no Option may.";
}
merge = 1;
} elseif (first) {
d->opts = OPT_NONE;
} elseif (merge) { return"Either all Options must start with + or -, or no Option may.";
}
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 ist noch experimentell.