00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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"
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"
00036 #include "http_request.h"
00037 #include "http_vhost.h"
00038 #include "http_main.h"
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
00054 #define AP_LIMIT_REQ_BODY_UNSET ((apr_off_t) -1)
00055 #define AP_DEFAULT_LIMIT_REQ_BODY ((apr_off_t) 0)
00056
00057
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
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
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
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
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
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;
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
00144
00145 conf->mime_type = NULL;
00146 conf->handler = NULL;
00147 conf->output_filters = NULL;
00148 conf->input_filters = NULL;
00149
00150
00151
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
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
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
00226
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
00238
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
00250
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
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
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
00349
00350 conf->sec_file = apr_array_append(a, base->sec_file, new->sec_file);
00351 }
00352
00353
00354
00355
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
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
00404 conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
00405 }
00406
00407
00408
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
00458 conf->redirect_limit = 0;
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
00496
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
00525
00526
00527
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
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
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
00563
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
00585
00586
00587
00588
00589 return;
00590 }
00591
00592
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
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
00613
00614
00615
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)
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
00698
00699
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
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
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
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
00739 return;
00740 }
00741
00742 if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
00743
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) {
00769 *str_is_ip = 0;
00770 }
00771
00772
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
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
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
00819
00820
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) {
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
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
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
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
00899 return r->server->server_hostname;
00900 }
00901
00902
00903
00904
00905
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, ':')) {
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
00929
00930
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 {
00937
00938
00939
00940
00941
00942
00943
00944
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
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
00984
00985
00986
00987
00988
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
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
01029
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
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
01123
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
01174
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
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
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 {
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
01214
01215
01216 conf->response_code_strings[index_number] = &errordocument_default;
01217 }
01218 else {
01219
01220
01221
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")) {
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
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
01350
01351
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
01382
01383
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
01437
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
01449
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
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
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
01594
01595
01596 methnum = ap_method_register(cmd->pool, method);
01597 }
01598
01599 limited |= (AP_METHOD_BIT << methnum);
01600 }
01601
01602
01603
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
01615
01616
01617
01618
01619
01620 #ifdef WIN32
01621 #define USE_ICASE REG_ICASE
01622 #else
01623 #define USE_ICASE 0
01624 #endif
01625
01626
01627
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