Main Page | Modules | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

core.c

Go to the documentation of this file.
00001 /* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
00002  * applicable.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "apr.h"
00018 #include "apr_strings.h"
00019 #include "apr_lib.h"
00020 #include "apr_fnmatch.h"
00021 #include "apr_hash.h"
00022 #include "apr_thread_proc.h"    /* for RLIMIT stuff */
00023 #include "apr_hooks.h"
00024 
00025 #define APR_WANT_IOVEC
00026 #define APR_WANT_STRFUNC
00027 #define APR_WANT_MEMFUNC
00028 #include "apr_want.h"
00029 
00030 #define CORE_PRIVATE
00031 #include "ap_config.h"
00032 #include "httpd.h"
00033 #include "http_config.h"
00034 #include "http_core.h"
00035 #include "http_protocol.h" /* For index_of_response().  Grump. */
00036 #include "http_request.h"
00037 #include "http_vhost.h"
00038 #include "http_main.h"     /* For the default_handler below... */
00039 #include "http_log.h"
00040 #include "rfc1413.h"
00041 #include "util_md5.h"
00042 #include "http_connection.h"
00043 #include "apr_buckets.h"
00044 #include "util_filter.h"
00045 #include "util_ebcdic.h"
00046 #include "mpm.h"
00047 #include "mpm_common.h"
00048 #include "scoreboard.h"
00049 #include "mod_core.h"
00050 #include "mod_proxy.h"
00051 #include "ap_listen.h"
00052 
00053 /* LimitRequestBody handling */
00054 #define AP_LIMIT_REQ_BODY_UNSET         ((apr_off_t) -1)
00055 #define AP_DEFAULT_LIMIT_REQ_BODY       ((apr_off_t) 0)
00056 
00057 /* LimitXMLRequestBody handling */
00058 #define AP_LIMIT_UNSET                  ((long) -1)
00059 #define AP_DEFAULT_LIMIT_XML_BODY       ((size_t)1000000)
00060 
00061 #define AP_MIN_SENDFILE_BYTES           (256)
00062 
00063 /* maximum include nesting level */
00064 #ifndef AP_MAX_INCLUDE_DEPTH
00065 #define AP_MAX_INCLUDE_DEPTH            (128)
00066 #endif
00067 
00068 APR_HOOK_STRUCT(
00069     APR_HOOK_LINK(get_mgmt_items)
00070 )
00071 
00072 AP_IMPLEMENT_HOOK_RUN_ALL(int, get_mgmt_items,
00073                           (apr_pool_t *p, const char *val, apr_hash_t *ht),
00074                           (p, val, ht), OK, DECLINED)
00075 
00076 /* Server core module... This module provides support for really basic
00077  * server operations, including options and commands which control the
00078  * operation of other modules.  Consider this the bureaucracy module.
00079  *
00080  * The core module also defines handlers, etc., do handle just enough
00081  * to allow a server with the core module ONLY to actually serve documents
00082  * (though it slaps DefaultType on all of 'em); this was useful in testing,
00083  * but may not be worth preserving.
00084  *
00085  * This file could almost be mod_core.c, except for the stuff which affects
00086  * the http_conf_globals.
00087  */
00088 
00089 /* Handles for core filters */
00090 AP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle;
00091 AP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle;
00092 AP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle;
00093 AP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle;
00094 AP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle;
00095 
00096 /* magic pointer for ErrorDocument xxx "default" */
00097 static char errordocument_default;
00098 
00099 static void *create_core_dir_config(apr_pool_t *a, char *dir)
00100 {
00101     core_dir_config *conf;
00102     int i;
00103 
00104     conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
00105 
00106     /* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
00107 
00108     conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
00109     conf->opts_add = conf->opts_remove = OPT_NONE;
00110     conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
00111 
00112     conf->content_md5 = 2;
00113     conf->accept_path_info = 3;
00114 
00115     conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
00116 
00117     conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
00118     conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
00119     conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
00120     for (i = 0; i < METHODS; ++i) {
00121         conf->satisfy[i] = SATISFY_NOSPEC;
00122     }
00123 
00124 #ifdef RLIMIT_CPU
00125     conf->limit_cpu = NULL;
00126 #endif
00127 #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
00128     conf->limit_mem = NULL;
00129 #endif
00130 #ifdef RLIMIT_NPROC
00131     conf->limit_nproc = NULL;
00132 #endif
00133 
00134     conf->limit_req_body = AP_LIMIT_REQ_BODY_UNSET;
00135     conf->limit_xml_body = AP_LIMIT_UNSET;
00136     conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
00137 
00138     conf->server_signature = srv_sig_unset;
00139 
00140     conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
00141     conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
00142 
00143     /* Overriding all negotiation
00144      */
00145     conf->mime_type = NULL;
00146     conf->handler = NULL;
00147     conf->output_filters = NULL;
00148     conf->input_filters = NULL;
00149 
00150     /*
00151      * Flag for use of inodes in ETags.
00152      */
00153     conf->etag_bits = ETAG_UNSET;
00154     conf->etag_add = ETAG_UNSET;
00155     conf->etag_remove = ETAG_UNSET;
00156 
00157     conf->enable_mmap = ENABLE_MMAP_UNSET;
00158     conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
00159     conf->allow_encoded_slashes = 0;
00160 
00161     return (void *)conf;
00162 }
00163 
00164 /*
00165  * Overlay one hash table of ct_output_filters onto another
00166  */
00167 static void *merge_ct_filters(apr_pool_t *p,
00168                               const void *key,
00169                               apr_ssize_t klen,
00170                               const void *overlay_val,
00171                               const void *base_val,
00172                               const void *data)
00173 {
00174     ap_filter_rec_t *cur;
00175     const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
00176     const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
00177 
00178     cur = NULL;
00179 
00180     while (overlay_info) {
00181         ap_filter_rec_t *new;
00182 
00183         new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
00184         new->name = apr_pstrdup(p, overlay_info->name);
00185         new->next = cur;
00186         cur = new;
00187         overlay_info = overlay_info->next;
00188     }
00189 
00190     while (base_info) {
00191         ap_filter_rec_t *f;
00192         int found = 0;
00193 
00194         /* We can't have dups. */
00195         f = cur;
00196         while (f) {
00197             if (!strcasecmp(base_info->name, f->name)) {
00198                 found = 1;
00199                 break;
00200             }
00201 
00202             f = f->next;
00203         }
00204 
00205         if (!found) {
00206             f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
00207             f->name = apr_pstrdup(p, base_info->name);
00208             f->next = cur;
00209             cur = f;
00210         }
00211 
00212         base_info = base_info->next;
00213     }
00214 
00215     return cur;
00216 }
00217 
00218 static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
00219 {
00220     core_dir_config *base = (core_dir_config *)basev;
00221     core_dir_config *new = (core_dir_config *)newv;
00222     core_dir_config *conf;
00223     int i;
00224 
00225     /* Create this conf by duplicating the base, replacing elements
00226      * (or creating copies for merging) where new-> values exist.
00227      */
00228     conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
00229     memcpy(conf, base, sizeof(core_dir_config));
00230 
00231     conf->d = new->d;
00232     conf->d_is_fnmatch = new->d_is_fnmatch;
00233     conf->d_components = new->d_components;
00234     conf->r = new->r;
00235 
00236     if (new->opts & OPT_UNSET) {
00237         /* there was no explicit setting of new->opts, so we merge
00238          * preserve the invariant (opts_add & opts_remove) == 0
00239          */
00240         conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
00241         conf->opts_remove = (conf->opts_remove & ~new->opts_add)
00242                             | new->opts_remove;
00243         conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
00244         if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
00245             conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
00246         }
00247     }
00248     else {
00249         /* otherwise we just copy, because an explicit opts setting
00250          * overrides all earlier +/- modifiers
00251          */
00252         conf->opts = new->opts;
00253         conf->opts_add = new->opts_add;
00254         conf->opts_remove = new->opts_remove;
00255     }
00256 
00257     if (!(new->override & OR_UNSET)) {
00258         conf->override = new->override;
00259     }
00260 
00261     if (new->ap_default_type) {
00262         conf->ap_default_type = new->ap_default_type;
00263     }
00264 
00265     if (new->ap_auth_type) {
00266         conf->ap_auth_type = new->ap_auth_type;
00267     }
00268 
00269     if (new->ap_auth_name) {
00270         conf->ap_auth_name = new->ap_auth_name;
00271     }
00272 
00273     if (new->ap_requires) {
00274         conf->ap_requires = new->ap_requires;
00275     }
00276 
00277     if (conf->response_code_strings == NULL) {
00278         conf->response_code_strings = new->response_code_strings;
00279     }
00280     else if (new->response_code_strings != NULL) {
00281         /* If we merge, the merge-result must have it's own array
00282          */
00283         conf->response_code_strings = apr_palloc(a,
00284             sizeof(*conf->response_code_strings) * RESPONSE_CODES);
00285         memcpy(conf->response_code_strings, base->response_code_strings,
00286                sizeof(*conf->response_code_strings) * RESPONSE_CODES);
00287 
00288         for (i = 0; i < RESPONSE_CODES; ++i) {
00289             if (new->response_code_strings[i] != NULL) {
00290                 conf->response_code_strings[i] = new->response_code_strings[i];
00291             }
00292         }
00293     }
00294     /* Otherwise we simply use the base->response_code_strings array
00295      */
00296 
00297     if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
00298         conf->hostname_lookups = new->hostname_lookups;
00299     }
00300 
00301     if ((new->do_rfc1413 & 2) == 0) {
00302         conf->do_rfc1413 = new->do_rfc1413;
00303     }
00304 
00305     if ((new->content_md5 & 2) == 0) {
00306         conf->content_md5 = new->content_md5;
00307     }
00308 
00309     if (new->accept_path_info != 3) {
00310         conf->accept_path_info = new->accept_path_info;
00311     }
00312 
00313     if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
00314         conf->use_canonical_name = new->use_canonical_name;
00315     }
00316 
00317 #ifdef RLIMIT_CPU
00318     if (new->limit_cpu) {
00319         conf->limit_cpu = new->limit_cpu;
00320     }
00321 #endif
00322 
00323 #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
00324     if (new->limit_mem) {
00325         conf->limit_mem = new->limit_mem;
00326     }
00327 #endif
00328 
00329 #ifdef RLIMIT_NPROC
00330     if (new->limit_nproc) {
00331         conf->limit_nproc = new->limit_nproc;
00332     }
00333 #endif
00334 
00335     if (new->limit_req_body != AP_LIMIT_REQ_BODY_UNSET) {
00336         conf->limit_req_body = new->limit_req_body;
00337     }
00338 
00339     if (new->limit_xml_body != AP_LIMIT_UNSET)
00340         conf->limit_xml_body = new->limit_xml_body;
00341     else
00342         conf->limit_xml_body = base->limit_xml_body;
00343 
00344     if (!conf->sec_file) {
00345         conf->sec_file = new->sec_file;
00346     }
00347     else if (new->sec_file) {
00348         /* If we merge, the merge-result must have it's own array
00349          */
00350         conf->sec_file = apr_array_append(a, base->sec_file, new->sec_file);
00351     }
00352     /* Otherwise we simply use the base->sec_file array
00353      */
00354 
00355     /* use a separate ->satisfy[] array either way */
00356     conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
00357     for (i = 0; i < METHODS; ++i) {
00358         if (new->satisfy[i] != SATISFY_NOSPEC) {
00359             conf->satisfy[i] = new->satisfy[i];
00360         } else {
00361             conf->satisfy[i] = base->satisfy[i];
00362         }
00363     }
00364 
00365     if (new->server_signature != srv_sig_unset) {
00366         conf->server_signature = new->server_signature;
00367     }
00368 
00369     if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
00370         conf->add_default_charset = new->add_default_charset;
00371         conf->add_default_charset_name = new->add_default_charset_name;
00372     }
00373 
00374     /* Overriding all negotiation
00375      */
00376     if (new->mime_type) {
00377         conf->mime_type = new->mime_type;
00378     }
00379 
00380     if (new->handler) {
00381         conf->handler = new->handler;
00382     }
00383 
00384     if (new->output_filters) {
00385         conf->output_filters = new->output_filters;
00386     }
00387 
00388     if (new->input_filters) {
00389         conf->input_filters = new->input_filters;
00390     }
00391 
00392     if (conf->ct_output_filters && new->ct_output_filters) {
00393         conf->ct_output_filters = apr_hash_merge(a,
00394                                                  new->ct_output_filters,
00395                                                  conf->ct_output_filters,
00396                                                  merge_ct_filters,
00397                                                  NULL);
00398     }
00399     else if (new->ct_output_filters) {
00400         conf->ct_output_filters = apr_hash_copy(a, new->ct_output_filters);
00401     }
00402     else if (conf->ct_output_filters) {
00403         /* That memcpy above isn't enough. */
00404         conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
00405     }
00406 
00407     /*
00408      * Now merge the setting of the FileETag directive.
00409      */
00410     if (new->etag_bits == ETAG_UNSET) {
00411         conf->etag_add =
00412             (conf->etag_add & (~ new->etag_remove)) | new->etag_add;
00413         conf->etag_remove =
00414             (conf->opts_remove & (~ new->etag_add)) | new->etag_remove;
00415         conf->etag_bits =
00416             (conf->etag_bits & (~ conf->etag_remove)) | conf->etag_add;
00417     }
00418     else {
00419         conf->etag_bits = new->etag_bits;
00420         conf->etag_add = new->etag_add;
00421         conf->etag_remove = new->etag_remove;
00422     }
00423 
00424     if (conf->etag_bits != ETAG_NONE) {
00425         conf->etag_bits &= (~ ETAG_NONE);
00426     }
00427 
00428     if (new->enable_mmap != ENABLE_MMAP_UNSET) {
00429         conf->enable_mmap = new->enable_mmap;
00430     }
00431 
00432     if (new->enable_sendfile != ENABLE_SENDFILE_UNSET) {
00433         conf->enable_sendfile = new->enable_sendfile;
00434     }
00435 
00436     conf->allow_encoded_slashes = new->allow_encoded_slashes;
00437     
00438     return (void*)conf;
00439 }
00440 
00441 static void *create_core_server_config(apr_pool_t *a, server_rec *s)
00442 {
00443     core_server_config *conf;
00444     int is_virtual = s->is_virtual;
00445 
00446     conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
00447 
00448 #ifdef GPROF
00449     conf->gprof_dir = NULL;
00450 #endif
00451 
00452     conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
00453     conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
00454     conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
00455     conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
00456 
00457     /* recursion stopper */
00458     conf->redirect_limit = 0; /* 0 == unset */
00459     conf->subreq_limit = 0;
00460 
00461     return (void *)conf;
00462 }
00463 
00464 static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
00465 {
00466     core_server_config *base = (core_server_config *)basev;
00467     core_server_config *virt = (core_server_config *)virtv;
00468     core_server_config *conf;
00469 
00470     conf = (core_server_config *)apr_palloc(p, sizeof(core_server_config));
00471     memcpy(conf, virt, sizeof(core_server_config));
00472 
00473     if (!conf->access_name) {
00474         conf->access_name = base->access_name;
00475     }
00476 
00477     if (!conf->ap_document_root) {
00478         conf->ap_document_root = base->ap_document_root;
00479     }
00480 
00481     conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
00482     conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
00483 
00484     conf->redirect_limit = virt->redirect_limit
00485                            ? virt->redirect_limit
00486                            : base->redirect_limit;
00487 
00488     conf->subreq_limit = virt->subreq_limit
00489                          ? virt->subreq_limit
00490                          : base->subreq_limit;
00491 
00492     return conf;
00493 }
00494 
00495 /* Add per-directory configuration entry (for <directory> section);
00496  * these are part of the core server config.
00497  */
00498 
00499 AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
00500 {
00501     core_server_config *sconf = ap_get_module_config(s->module_config,
00502                                                      &core_module);
00503     void **new_space = (void **)apr_array_push(sconf->sec_dir);
00504 
00505     *new_space = dir_config;
00506 }
00507 
00508 AP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config)
00509 {
00510     core_server_config *sconf = ap_get_module_config(s->module_config,
00511                                                      &core_module);
00512     void **new_space = (void **)apr_array_push(sconf->sec_url);
00513 
00514     *new_space = url_config;
00515 }
00516 
00517 AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
00518 {
00519     void **new_space = (void **)apr_array_push(conf->sec_file);
00520 
00521     *new_space = url_config;
00522 }
00523 
00524 /* We need to do a stable sort, qsort isn't stable.  So to make it stable
00525  * we'll be maintaining the original index into the list, and using it
00526  * as the minor key during sorting.  The major key is the number of
00527  * components (where the root component is zero).
00528  */
00529 struct reorder_sort_rec {
00530     ap_conf_vector_t *elt;
00531     int orig_index;
00532 };
00533 
00534 static int reorder_sorter(const void *va, const void *vb)
00535 {
00536     const struct reorder_sort_rec *a = va;
00537     const struct reorder_sort_rec *b = vb;
00538     core_dir_config *core_a;
00539     core_dir_config *core_b;
00540 
00541     core_a = ap_get_module_config(a->elt, &core_module);
00542     core_b = ap_get_module_config(b->elt, &core_module);
00543 
00544     /* a regex always sorts after a non-regex
00545      */
00546     if (!core_a->r && core_b->r) {
00547         return -1;
00548     }
00549     else if (core_a->r && !core_b->r) {
00550         return 1;
00551     }
00552 
00553     /* we always sort next by the number of components
00554      */
00555     if (core_a->d_components < core_b->d_components) {
00556         return -1;
00557     }
00558     else if (core_a->d_components > core_b->d_components) {
00559         return 1;
00560     }
00561 
00562     /* They have the same number of components, we now have to compare
00563      * the minor key to maintain the original order (from the config.)
00564      */
00565     return a->orig_index - b->orig_index;
00566 }
00567 
00568 void ap_core_reorder_directories(apr_pool_t *p, server_rec *s)
00569 {
00570     core_server_config *sconf;
00571     apr_array_header_t *sec_dir;
00572     struct reorder_sort_rec *sortbin;
00573     int nelts;
00574     ap_conf_vector_t **elts;
00575     int i;
00576     apr_pool_t *tmp;
00577 
00578     sconf = ap_get_module_config(s->module_config, &core_module);
00579     sec_dir = sconf->sec_dir;
00580     nelts = sec_dir->nelts;
00581     elts = (ap_conf_vector_t **)sec_dir->elts;
00582 
00583     if (!nelts) {
00584         /* simple case of already being sorted... */
00585         /* We're not checking this condition to be fast... we're checking
00586          * it to avoid trying to palloc zero bytes, which can trigger some
00587          * memory debuggers to barf
00588          */
00589         return;
00590     }
00591 
00592     /* we have to allocate tmp space to do a stable sort */
00593     apr_pool_create(&tmp, p);
00594     sortbin = apr_palloc(tmp, sec_dir->nelts * sizeof(*sortbin));
00595     for (i = 0; i < nelts; ++i) {
00596         sortbin[i].orig_index = i;
00597         sortbin[i].elt = elts[i];
00598     }
00599 
00600     qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
00601 
00602     /* and now copy back to the original array */
00603     for (i = 0; i < nelts; ++i) {
00604         elts[i] = sortbin[i].elt;
00605     }
00606 
00607     apr_pool_destroy(tmp);
00608 }
00609 
00610 /*****************************************************************
00611  *
00612  * There are some elements of the core config structures in which
00613  * other modules have a legitimate interest (this is ugly, but necessary
00614  * to preserve NCSA back-compatibility).  So, we have a bunch of accessors
00615  * here...
00616  */
00617 
00618 AP_DECLARE(int) ap_allow_options(request_rec *r)
00619 {
00620     core_dir_config *conf =
00621       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
00622 
00623     return conf->opts;
00624 }
00625 
00626 AP_DECLARE(int) ap_allow_overrides(request_rec *r)
00627 {
00628     core_dir_config *conf;
00629     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00630                                                    &core_module);
00631 
00632     return conf->override;
00633 }
00634 
00635 AP_DECLARE(const char *) ap_auth_type(request_rec *r)
00636 {
00637     core_dir_config *conf;
00638 
00639     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00640                                                    &core_module);
00641 
00642     return conf->ap_auth_type;
00643 }
00644 
00645 AP_DECLARE(const char *) ap_auth_name(request_rec *r)
00646 {
00647     core_dir_config *conf;
00648 
00649     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00650                                                    &core_module);
00651 
00652     return conf->ap_auth_name;
00653 }
00654 
00655 AP_DECLARE(const char *) ap_default_type(request_rec *r)
00656 {
00657     core_dir_config *conf;
00658 
00659     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00660                                                    &core_module);
00661 
00662     return conf->ap_default_type
00663                ? conf->ap_default_type
00664                : DEFAULT_CONTENT_TYPE;
00665 }
00666 
00667 AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
00668 {
00669     core_server_config *conf;
00670 
00671     conf = (core_server_config *)ap_get_module_config(r->server->module_config,
00672                                                       &core_module);
00673 
00674     return conf->ap_document_root;
00675 }
00676 
00677 AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r)
00678 {
00679     core_dir_config *conf;
00680 
00681     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00682                                                    &core_module);
00683 
00684     return conf->ap_requires;
00685 }
00686 
00687 AP_DECLARE(int) ap_satisfies(request_rec *r)
00688 {
00689     core_dir_config *conf;
00690 
00691     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00692                                                    &core_module);
00693 
00694     return conf->satisfy[r->method_number];
00695 }
00696 
00697 /* Should probably just get rid of this... the only code that cares is
00698  * part of the core anyway (and in fact, it isn't publicised to other
00699  * modules).
00700  */
00701 
00702 char *ap_response_code_string(request_rec *r, int error_index)
00703 {
00704     core_dir_config *dirconf;
00705     core_request_config *reqconf;
00706 
00707     /* check for string registered via ap_custom_response() first */
00708     reqconf = (core_request_config *)ap_get_module_config(r->request_config,
00709                                                           &core_module);
00710     if (reqconf->response_code_strings != NULL &&
00711         reqconf->response_code_strings[error_index] != NULL) {
00712         return reqconf->response_code_strings[error_index];
00713     }
00714 
00715     /* check for string specified via ErrorDocument */
00716     dirconf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00717                                                       &core_module);
00718 
00719     if (dirconf->response_code_strings == NULL) {
00720         return NULL;
00721     }
00722 
00723     if (dirconf->response_code_strings[error_index] == &errordocument_default) {
00724         return NULL;
00725     }
00726 
00727     return dirconf->response_code_strings[error_index];
00728 }
00729 
00730 
00731 /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
00732 static APR_INLINE void do_double_reverse (conn_rec *conn)
00733 {
00734     apr_sockaddr_t *sa;
00735     apr_status_t rv;
00736 
00737     if (conn->double_reverse) {
00738         /* already done */
00739         return;
00740     }
00741 
00742     if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
00743         /* single reverse failed, so don't bother */
00744         conn->double_reverse = -1;
00745         return;
00746     }
00747 
00748     rv = apr_sockaddr_info_get(&sa, conn->remote_host, APR_UNSPEC, 0, 0, conn->pool);
00749     if (rv == APR_SUCCESS) {
00750         while (sa) {
00751             if (apr_sockaddr_equal(sa, conn->remote_addr)) {
00752                 conn->double_reverse = 1;
00753                 return;
00754             }
00755 
00756             sa = sa->next;
00757         }
00758     }
00759 
00760     conn->double_reverse = -1;
00761 }
00762 
00763 AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
00764                                             int type, int *str_is_ip)
00765 {
00766     int hostname_lookups;
00767 
00768     if (str_is_ip) { /* if caller wants to know */
00769         *str_is_ip = 0;
00770     }
00771 
00772     /* If we haven't checked the host name, and we want to */
00773     if (dir_config) {
00774         hostname_lookups =
00775             ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
00776             ->hostname_lookups;
00777 
00778         if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
00779             hostname_lookups = HOSTNAME_LOOKUP_OFF;
00780         }
00781     }
00782     else {
00783         /* the default */
00784         hostname_lookups = HOSTNAME_LOOKUP_OFF;
00785     }
00786 
00787     if (type != REMOTE_NOLOOKUP
00788         && conn->remote_host == NULL
00789         && (type == REMOTE_DOUBLE_REV
00790         || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
00791 
00792         if (apr_getnameinfo(&conn->remote_host, conn->remote_addr, 0)
00793             == APR_SUCCESS) {
00794             ap_str_tolower(conn->remote_host);
00795 
00796             if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
00797                 do_double_reverse(conn);
00798                 if (conn->double_reverse != 1) {
00799                     conn->remote_host = NULL;
00800                 }
00801             }
00802         }
00803 
00804         /* if failed, set it to the NULL string to indicate error */
00805         if (conn->remote_host == NULL) {
00806             conn->remote_host = "";
00807         }
00808     }
00809 
00810     if (type == REMOTE_DOUBLE_REV) {
00811         do_double_reverse(conn);
00812         if (conn->double_reverse == -1) {
00813             return NULL;
00814         }
00815     }
00816 
00817     /*
00818      * Return the desired information; either the remote DNS name, if found,
00819      * or either NULL (if the hostname was requested) or the IP address
00820      * (if any identifier was requested).
00821      */
00822     if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
00823         return conn->remote_host;
00824     }
00825     else {
00826         if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
00827             return NULL;
00828         }
00829         else {
00830             if (str_is_ip) { /* if caller wants to know */
00831                 *str_is_ip = 1;
00832             }
00833 
00834             return conn->remote_ip;
00835         }
00836     }
00837 }
00838 
00839 AP_DECLARE(const char *) ap_get_remote_logname(request_rec *r)
00840 {
00841     core_dir_config *dir_conf;
00842 
00843     if (r->connection->remote_logname != NULL) {
00844         return r->connection->remote_logname;
00845     }
00846 
00847     /* If we haven't checked the identity, and we want to */
00848     dir_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00849                                                        &core_module);
00850 
00851     if (dir_conf->do_rfc1413 & 1) {
00852         return ap_rfc1413(r->connection, r->server);
00853     }
00854     else {
00855         return NULL;
00856     }
00857 }
00858 
00859 /* There are two options regarding what the "name" of a server is.  The
00860  * "canonical" name as defined by ServerName and Port, or the "client's
00861  * name" as supplied by a possible Host: header or full URI.  We never
00862  * trust the port passed in the client's headers, we always use the
00863  * port of the actual socket.
00864  *
00865  * The DNS option to UseCanonicalName causes this routine to do a
00866  * reverse lookup on the local IP address of the connection and use
00867  * that for the ServerName. This makes its value more reliable while
00868  * at the same time allowing Demon's magic virtual hosting to work.
00869  * The assumption is that DNS lookups are sufficiently quick...
00870  * -- fanf 1998-10-03
00871  */
00872 AP_DECLARE(const char *) ap_get_server_name(request_rec *r)
00873 {
00874     conn_rec *conn = r->connection;
00875     core_dir_config *d;
00876 
00877     d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
00878                                                 &core_module);
00879 
00880     if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
00881         return r->hostname ? r->hostname : r->server->server_hostname;
00882     }
00883 
00884     if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
00885         if (conn->local_host == NULL) {
00886             if (apr_getnameinfo(&conn->local_host,
00887                                 conn->local_addr, 0) != APR_SUCCESS)
00888                 conn->local_host = apr_pstrdup(conn->pool,
00889                                                r->server->server_hostname);
00890             else {
00891                 ap_str_tolower(conn->local_host);
00892             }
00893         }
00894 
00895         return conn->local_host;
00896     }
00897 
00898     /* default */
00899     return r->server->server_hostname;
00900 }
00901 
00902 /*
00903  * Get the current server name from the request for the purposes
00904  * of using in a URL.  If the server name is an IPv6 literal
00905  * address, it will be returned in URL format (e.g., "[fe80::1]").
00906  */
00907 static const char *get_server_name_for_url(request_rec *r)
00908 {
00909     const char *plain_server_name = ap_get_server_name(r);
00910 
00911 #if APR_HAVE_IPV6
00912     if (ap_strchr_c(plain_server_name, ':')) { /* IPv6 literal? */
00913         return apr_psprintf(r->pool, "[%s]", plain_server_name);
00914     }
00915 #endif
00916     return plain_server_name;
00917 }
00918 
00919 AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)
00920 {
00921     apr_port_t port;
00922     core_dir_config *d =
00923       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
00924 
00925     if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
00926         || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
00927 
00928         /* With UseCanonicalName off Apache will form self-referential
00929          * URLs using the hostname and port supplied by the client if
00930          * any are supplied (otherwise it will use the canonical name).
00931          */
00932         port = r->parsed_uri.port_str ? r->parsed_uri.port :
00933                r->server->port ? r->server->port :
00934                ap_default_port(r);
00935     }
00936     else { /* d->use_canonical_name == USE_CANONICAL_NAME_ON */
00937 
00938         /* With UseCanonicalName on (and in all versions prior to 1.3)
00939          * Apache will use the hostname and port specified in the
00940          * ServerName directive to construct a canonical name for the
00941          * server. (If no port was specified in the ServerName
00942          * directive, Apache uses the port supplied by the client if
00943          * any is supplied, and finally the default port for the protocol
00944          * used.
00945          */
00946         port = r->server->port ? r->server->port :
00947                r->connection->local_addr->port ? r->connection->local_addr->port :
00948                ap_default_port(r);
00949     }
00950 
00951     /* default */
00952     return port;
00953 }
00954 
00955 AP_DECLARE(char *) ap_construct_url(apr_pool_t *p, const char *uri,
00956                                     request_rec *r)
00957 {
00958     unsigned port = ap_get_server_port(r);
00959     const char *host = get_server_name_for_url(r);
00960 
00961     if (ap_is_default_port(port, r)) {
00962         return apr_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
00963     }
00964 
00965     return apr_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
00966 }
00967 
00968 AP_DECLARE(apr_off_t) ap_get_limit_req_body(const request_rec *r)
00969 {
00970     core_dir_config *d =
00971       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
00972 
00973     if (d->limit_req_body == AP_LIMIT_REQ_BODY_UNSET) {
00974         return AP_DEFAULT_LIMIT_REQ_BODY;
00975     }
00976 
00977     return d->limit_req_body;
00978 }
00979 
00980 
00981 /*****************************************************************
00982  *
00983  * Commands... this module handles almost all of the NCSA httpd.conf
00984  * commands, but most of the old srm.conf is in the the modules.
00985  */
00986 
00987 
00988 /* returns a parent if it matches the given directive */
00989 static const ap_directive_t * find_parent(const ap_directive_t *dirp,
00990                                           const char *what)
00991 {
00992     while (dirp->parent != NULL) {
00993         dirp = dirp->parent;
00994 
00995         /* ### it would be nice to have atom-ized directives */
00996         if (strcasecmp(dirp->directive, what) == 0)
00997             return dirp;
00998     }
00999 
01000     return NULL;
01001 }
01002 
01003 AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd,
01004                                               unsigned forbidden)
01005 {
01006     const char *gt = (cmd->cmd->name[0] == '<'
01007                       && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
01008                          ? ">" : "";
01009     const ap_directive_t *found;
01010 
01011     if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
01012         return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
01013                            " cannot occur within <VirtualHost> section", NULL);
01014     }
01015 
01016     if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
01017         return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
01018                            " cannot occur within <Limit> section", NULL);
01019     }
01020 
01021     if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE) {
01022         if (cmd->path != NULL) {
01023             return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
01024                             " cannot occur within <Directory/Location/Files> "
01025                             "section", NULL);
01026         }
01027         if (cmd->cmd->req_override & EXEC_ON_READ) {
01028             /* EXEC_ON_READ must be NOT_IN_DIR_LOC_FILE, if not, it will
01029              * (deliberately) segfault below in the individual tests...
01030              */
01031             return NULL;
01032         }
01033     }
01034     
01035     if (((forbidden & NOT_IN_DIRECTORY)
01036          && ((found = find_parent(cmd->directive, "<Directory"))
01037              || (found = find_parent(cmd->directive, "<DirectoryMatch"))))
01038         || ((forbidden & NOT_IN_LOCATION)
01039             && ((found = find_parent(cmd->directive, "<Location"))
01040                 || (found = find_parent(cmd->directive, "<LocationMatch"))))
01041         || ((forbidden & NOT_IN_FILES)
01042             && ((found = find_parent(cmd->directive, "<Files"))
01043                 || (found = find_parent(cmd->directive, "<FilesMatch"))))) {
01044         return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
01045                            " cannot occur within ", found->directive,
01046                            "> section", NULL);
01047     }
01048 
01049     return NULL;
01050 }
01051 
01052 static const char *set_access_name(cmd_parms *cmd, void *dummy,
01053                                    const char *arg)
01054 {
01055     void *sconf = cmd->server->module_config;
01056     core_server_config *conf = ap_get_module_config(sconf, &core_module);
01057 
01058     const char *err = ap_check_cmd_context(cmd,
01059                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
01060     if (err != NULL) {
01061         return err;
01062     }
01063 
01064     conf->access_name = apr_pstrdup(cmd->pool, arg);
01065     return NULL;
01066 }
01067 
01068 #ifdef GPROF
01069 static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, const char *arg)
01070 {
01071     void *sconf = cmd->server->module_config;
01072     core_server_config *conf = ap_get_module_config(sconf, &core_module);
01073 
01074     const char *err = ap_check_cmd_context(cmd,
01075                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
01076     if (err != NULL) {
01077         return err;
01078     }
01079 
01080     conf->gprof_dir = apr_pstrdup(cmd->pool, arg);
01081     return NULL;
01082 }
01083 #endif /*GPROF*/
01084 
01085 static const char *set_add_default_charset(cmd_parms *cmd,
01086                                            void *d_, const char *arg)
01087 {
01088     core_dir_config *d = d_;
01089 
01090     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01091     if (err != NULL) {
01092         return err;
01093     }
01094 
01095     if (!strcasecmp(arg, "Off")) {
01096        d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
01097     }
01098     else if (!strcasecmp(arg, "On")) {
01099        d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
01100        d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
01101     }
01102     else {
01103        d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
01104        d->add_default_charset_name = arg;
01105     }
01106 
01107     return NULL;
01108 }
01109 
01110 static const char *set_document_root(cmd_parms *cmd, void *dummy,
01111                                      const char *arg)
01112 {
01113     void *sconf = cmd->server->module_config;
01114     core_server_config *conf = ap_get_module_config(sconf, &core_module);
01115 
01116     const char *err = ap_check_cmd_context(cmd,
01117                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
01118     if (err != NULL) {
01119         return err;
01120     }
01121 
01122     /* TODO: ap_configtestonly && ap_docrootcheck && */
01123     /* XXX Shouldn't this be relative to ServerRoot ??? */
01124     if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
01125                            APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS
01126         || !ap_is_directory(cmd->pool, arg)) {
01127         if (cmd->server->is_virtual) {
01128             ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0,
01129                           cmd->pool,
01130                           "Warning: DocumentRoot [%s] does not exist",
01131                           arg);
01132             conf->ap_document_root = arg;
01133         }
01134         else {
01135             return "DocumentRoot must be a directory";
01136         }
01137     }
01138     return NULL;
01139 }
01140 
01141 AP_DECLARE(void) ap_custom_response(request_rec *r, int status,
01142                                     const char *string)
01143 {
01144     core_request_config *conf =
01145         ap_get_module_config(r->request_config, &core_module);
01146     int idx;
01147 
01148     if (conf->response_code_strings == NULL) {
01149         conf->response_code_strings =
01150             apr_pcalloc(r->pool,
01151                         sizeof(*conf->response_code_strings) * RESPONSE_CODES);
01152     }
01153 
01154     idx = ap_index_of_response(status);
01155 
01156     conf->response_code_strings[idx] =
01157        ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ?
01158        apr_pstrdup(r->pool, string) : apr_pstrcat(r->pool, "\"", string, NULL);
01159 }
01160 
01161 static const char *set_error_document(cmd_parms *cmd, void *conf_,
01162                                       const char *errno_str, const char *msg)
01163 {
01164     core_dir_config *conf = conf_;
01165     int error_number, index_number, idx500;
01166     enum { MSG, LOCAL_PATH, REMOTE_PATH } what = MSG;
01167 
01168     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01169     if (err != NULL) {
01170         return err;
01171     }
01172 
01173     /* 1st parameter should be a 3 digit number, which we recognize;
01174      * convert it into an array index
01175      */
01176     error_number = atoi(errno_str);
01177     idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
01178 
01179     if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
01180         index_number = idx500;
01181     }
01182     else if ((index_number = ap_index_of_response(error_number)) == idx500) {
01183         return apr_pstrcat(cmd->pool, "Unsupported HTTP response code ",
01184                            errno_str, NULL);
01185     }
01186 
01187     /* Heuristic to determine second argument. */
01188     if (ap_strchr_c(msg,' '))
01189         what = MSG;
01190     else if (msg[0] == '/')
01191         what = LOCAL_PATH;
01192     else if (ap_is_url(msg))
01193         what = REMOTE_PATH;
01194     else
01195         what = MSG;
01196 
01197     /* The entry should be ignored if it is a full URL for a 401 error */
01198 
01199     if (error_number == 401 && what == REMOTE_PATH) {
01200         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server,
01201                      "cannot use a full URL in a 401 ErrorDocument "
01202                      "directive --- ignoring!");
01203     }
01204     else { /* Store it... */
01205         if (conf->response_code_strings == NULL) {
01206             conf->response_code_strings =
01207                 apr_pcalloc(cmd->pool,
01208                             sizeof(*conf->response_code_strings) *
01209                             RESPONSE_CODES);
01210         }
01211 
01212         if (strcmp(msg, "default") == 0) {
01213             /* special case: ErrorDocument 404 default restores the
01214              * canned server error response
01215              */
01216             conf->response_code_strings[index_number] = &errordocument_default;
01217         }
01218         else {
01219             /* hack. Prefix a " if it is a msg; as that is what
01220              * http_protocol.c relies on to distinguish between
01221              * a msg and a (local) path.
01222              */
01223             conf->response_code_strings[index_number] = (what == MSG) ?
01224                     apr_pstrcat(cmd->pool, "\"",msg,NULL) :
01225                     apr_pstrdup(cmd->pool, msg);
01226         }
01227     }
01228 
01229     return NULL;
01230 }
01231 
01232 static const char *set_override(cmd_parms *cmd, void *d_, const char *l)
01233 {
01234     core_dir_config *d = d_;
01235     char *w;
01236 
01237     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01238     if (err != NULL) {
01239         return err;
01240     }
01241 
01242     d->override = OR_NONE;
01243     while (l[0]) {
01244         w = ap_getword_conf(cmd->pool, &l);
01245         if (!strcasecmp(w, "Limit")) {
01246             d->override |= OR_LIMIT;
01247         }
01248         else if (!strcasecmp(w, "Options")) {
01249             d->override |= OR_OPTIONS;
01250         }
01251         else if (!strcasecmp(w, "FileInfo")) {
01252             d->override |= OR_FILEINFO;
01253         }
01254         else if (!strcasecmp(w, "AuthConfig")) {
01255             d->override |= OR_AUTHCFG;
01256         }
01257         else if (!strcasecmp(w, "Indexes")) {
01258             d->override |= OR_INDEXES;
01259         }
01260         else if (!strcasecmp(w, "None")) {
01261             d->override = OR_NONE;
01262         }
01263         else if (!strcasecmp(w, "All")) {
01264             d->override = OR_ALL;
01265         }
01266         else {
01267             return apr_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
01268         }
01269 
01270         d->override &= ~OR_UNSET;
01271     }
01272 
01273     return NULL;
01274 }
01275 
01276 static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
01277 {
01278     core_dir_config *d = d_;
01279     allow_options_t opt;
01280     int first = 1;
01281     char action;
01282 
01283     while (l[0]) {
01284         char *w = ap_getword_conf(cmd->pool, &l);
01285         action = '\0';
01286 
01287         if (*w == '+' || *w == '-') {
01288             action = *(w++);
01289         }
01290         else if (first) {
01291               d->opts = OPT_NONE;
01292             first = 0;
01293         }
01294 
01295         if (!strcasecmp(w, "Indexes")) {
01296             opt = OPT_INDEXES;
01297         }
01298         else if (!strcasecmp(w, "Includes")) {
01299             opt = OPT_INCLUDES;
01300         }
01301         else if (!strcasecmp(w, "IncludesNOEXEC")) {
01302             opt = (OPT_INCLUDES | OPT_INCNOEXEC);
01303         }
01304         else if (!strcasecmp(w, "FollowSymLinks")) {
01305             opt = OPT_SYM_LINKS;
01306         }
01307         else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
01308             opt = OPT_SYM_OWNER;
01309         }
01310         else if (!strcasecmp(w, "execCGI")) {
01311             opt = OPT_EXECCGI;
01312         }
01313         else if (!strcasecmp(w, "MultiViews")) {
01314             opt = OPT_MULTI;
01315         }
01316         else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
01317             opt = OPT_MULTI|OPT_EXECCGI;
01318         }
01319         else if (!strcasecmp(w, "None")) {
01320             opt = OPT_NONE;
01321         }
01322         else if (!strcasecmp(w, "All")) {
01323             opt = OPT_ALL;
01324         }
01325         else {
01326             return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
01327         }
01328 
01329         /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
01330         if (action == '-') {
01331             d->opts_remove |= opt;
01332             d->opts_add &= ~opt;
01333             d->opts &= ~opt;
01334         }
01335         else if (action == '+') {
01336             d->opts_add |= opt;
01337             d->opts_remove &= ~opt;
01338             d->opts |= opt;
01339         }
01340         else {
01341             d->opts |= opt;
01342         }
01343     }
01344 
01345     return NULL;
01346 }
01347 
01348 /*
01349  * Note what data should be used when forming file ETag values.
01350  * It would be nicer to do this as an ITERATE, but then we couldn't
01351  * remember the +/- state properly.
01352  */
01353 static const char *set_etag_bits(cmd_parms *cmd, void *mconfig,
01354                                  const char *args_p)
01355 {
01356     core_dir_config *cfg;
01357     etag_components_t bit;
01358     char action;
01359     char *token;
01360     const char *args;
01361     int valid;
01362     int first;
01363     int explicit;
01364 
01365     cfg = (core_dir_config *)mconfig;
01366 
01367     args = args_p;
01368     first = 1;
01369     explicit = 0;
01370     while (args[0] != '\0') {
01371         action = '*';
01372         bit = ETAG_UNSET;
01373         valid = 1;
01374         token = ap_getword_conf(cmd->pool, &args);
01375         if ((*token == '+') || (*token == '-')) {
01376             action = *token;
01377             token++;
01378         }
01379         else {
01380             /*
01381              * The occurrence of an absolute setting wipes
01382              * out any previous relative ones.  The first such
01383              * occurrence forgets any inherited ones, too.
01384              */
01385             if (first) {
01386                 cfg->etag_bits = ETAG_UNSET;
01387                 cfg->etag_add = ETAG_UNSET;
01388                 cfg->etag_remove = ETAG_UNSET;
01389                 first = 0;
01390             }
01391         }
01392 
01393         if (strcasecmp(token, "None") == 0) {
01394             if (action != '*') {
01395                 valid = 0;
01396             }
01397             else {
01398                 cfg->etag_bits = bit = ETAG_NONE;
01399                 explicit = 1;
01400             }
01401         }
01402         else if (strcasecmp(token, "All") == 0) {
01403             if (action != '*') {
01404                 valid = 0;
01405             }
01406             else {
01407                 explicit = 1;
01408                 cfg->etag_bits = bit = ETAG_ALL;
01409             }
01410         }
01411         else if (strcasecmp(token, "Size") == 0) {
01412             bit = ETAG_SIZE;
01413         }
01414         else if ((strcasecmp(token, "LMTime") == 0)
01415                  || (strcasecmp(token, "MTime") == 0)
01416                  || (strcasecmp(token, "LastModified") == 0)) {
01417             bit = ETAG_MTIME;
01418         }
01419         else if (strcasecmp(token, "INode") == 0) {
01420             bit = ETAG_INODE;
01421         }
01422         else {
01423             return apr_pstrcat(cmd->pool, "Unknown keyword '",
01424                                token, "' for ", cmd->cmd->name,
01425                                " directive", NULL);
01426         }
01427 
01428         if (! valid) {
01429             return apr_pstrcat(cmd->pool, cmd->cmd->name, " keyword '",
01430                                token, "' cannot be used with '+' or '-'",
01431                                NULL);
01432         }
01433 
01434         if (action == '+') {
01435             /*
01436              * Make sure it's in the 'add' list and absent from the
01437              * 'subtract' list.
01438              */
01439             cfg->etag_add |= bit;
01440             cfg->etag_remove &= (~ bit);
01441         }
01442         else if (action == '-') {
01443             cfg->etag_remove |= bit;
01444             cfg->etag_add &= (~ bit);
01445         }
01446         else {
01447             /*
01448              * Non-relative values wipe out any + or - values
01449              * accumulated so far.
01450              */
01451             cfg->etag_bits |= bit;
01452             cfg->etag_add = ETAG_UNSET;
01453             cfg->etag_remove = ETAG_UNSET;
01454             explicit = 1;
01455         }
01456     }
01457 
01458     /*
01459      * Any setting at all will clear the 'None' and 'Unset' bits.
01460      */
01461 
01462     if (cfg->etag_add != ETAG_UNSET) {
01463         cfg->etag_add &= (~ ETAG_UNSET);
01464     }
01465 
01466     if (cfg->etag_remove != ETAG_UNSET) {
01467         cfg->etag_remove &= (~ ETAG_UNSET);
01468     }
01469 
01470     if (explicit) {
01471         cfg->etag_bits &= (~ ETAG_UNSET);
01472 
01473         if ((cfg->etag_bits & ETAG_NONE) != ETAG_NONE) {
01474             cfg->etag_bits &= (~ ETAG_NONE);
01475         }
01476     }
01477 
01478     return NULL;
01479 }
01480 
01481 static const char *set_enable_mmap(cmd_parms *cmd, void *d_,
01482                                    const char *arg)
01483 {
01484     core_dir_config *d = d_;
01485     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01486 
01487     if (err != NULL) {
01488         return err;
01489     }
01490 
01491     if (strcasecmp(arg, "on") == 0) {
01492         d->enable_mmap = ENABLE_MMAP_ON;
01493     }
01494     else if (strcasecmp(arg, "off") == 0) {
01495         d->enable_mmap = ENABLE_MMAP_OFF;
01496     }
01497     else {
01498         return "parameter must be 'on' or 'off'";
01499     }
01500 
01501     return NULL;
01502 }
01503 
01504 static const char *set_enable_sendfile(cmd_parms *cmd, void *d_,
01505                                    const char *arg)
01506 {
01507     core_dir_config *d = d_;
01508     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01509 
01510     if (err != NULL) {
01511         return err;
01512     }
01513 
01514     if (strcasecmp(arg, "on") == 0) {
01515         d->enable_sendfile = ENABLE_SENDFILE_ON;
01516     }
01517     else if (strcasecmp(arg, "off") == 0) {
01518         d->enable_sendfile = ENABLE_SENDFILE_OFF;
01519     }
01520     else {
01521         return "parameter must be 'on' or 'off'";
01522     }
01523 
01524     return NULL;
01525 }
01526 
01527 static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
01528 {
01529     core_dir_config *c = c_;
01530     int satisfy = SATISFY_NOSPEC;
01531     int i;
01532 
01533     if (!strcasecmp(arg, "all")) {
01534         satisfy = SATISFY_ALL;
01535     }
01536     else if (!strcasecmp(arg, "any")) {
01537         satisfy = SATISFY_ANY;
01538     }
01539     else {
01540         return "Satisfy either 'any' or 'all'.";
01541     }
01542 
01543     for (i = 0; i < METHODS; ++i) {
01544         if (cmd->limited & (AP_METHOD_BIT << i)) {
01545             c->satisfy[i] = satisfy;
01546         }
01547     }
01548 
01549     return NULL;
01550 }
01551 
01552 static const char *require(cmd_parms *cmd, void *c_, const char *arg)
01553 {
01554     require_line *r;
01555     core_dir_config *c = c_;
01556 
01557     if (!c->ap_requires) {
01558         c->ap_requires = apr_array_make(cmd->pool, 2, sizeof(require_line));
01559     }
01560 
01561     r = (require_line *)apr_array_push(c->ap_requires);
01562     r->requirement = apr_pstrdup(cmd->pool, arg);
01563     r->method_mask = cmd->limited;
01564 
01565     return NULL;
01566 }
01567 
01568 AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd,
01569                                                       void *dummy,
01570                                                       const char *arg)
01571 {
01572     const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
01573     void *tog = cmd->cmd->cmd_data;
01574     apr_int64_t limited = 0;
01575     const char *errmsg;
01576 
01577     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
01578     if (err != NULL) {
01579         return err;
01580     }
01581 
01582     while (limited_methods[0]) {
01583         char *method = ap_getword_conf(cmd->pool, &limited_methods);
01584         int methnum;
01585 
01586         /* check for builtin or module registered method number */
01587         methnum = ap_method_number_of(method);
01588 
01589         if (methnum == M_TRACE && !tog) {
01590             return "TRACE cannot be controlled by <Limit>";
01591         }
01592         else if (methnum == M_INVALID) {
01593             /* method has not been registered yet, but resorce restriction
01594              * is always checked before method handling, so register it.
01595              */
01596             methnum = ap_method_register(cmd->pool, method);
01597         }
01598 
01599         limited |= (AP_METHOD_BIT << methnum);
01600     }
01601 
01602     /* Killing two features with one function,
01603      * if (tog == NULL) <Limit>, else <LimitExcept>
01604      */
01605     cmd->limited = tog ? ~limited : limited;
01606 
01607     errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
01608 
01609     cmd->limited = -1;
01610 
01611     return errmsg;
01612 }
01613 
01614 /* XXX: Bogus - need to do this differently (at least OS2/Netware suffer
01615  * the same problem!!!
01616  * We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
01617  * people don't get bitten by wrong-cased regex matches
01618  */
01619 
01620 #ifdef WIN32
01621 #define USE_ICASE REG_ICASE
01622 #else
01623 #define USE_ICASE 0
01624 #endif
01625 
01626 /*
01627  * Report a missing-'>' syntax error.
01628  */
01629 static char *unclosed_directive(cmd_parms *cmd)
01630 {
01631     return apr_pstrcat(cmd->pool, cmd->cmd->name,
01632                        "> directive missing closing '>'", NULL);
01633 }
01634 
01635 static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
01636 {
01637     const char *errmsg;
01638