00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "apr.h"
00033 #include "apr_strings.h"
00034 #include "apr_portable.h"
00035 #include "apr_file_io.h"
00036 #include "apr_fnmatch.h"
00037
00038 #define APR_WANT_STDIO
00039 #define APR_WANT_STRFUNC
00040 #include "apr_want.h"
00041
00042 #define CORE_PRIVATE
00043
00044 #include "ap_config.h"
00045 #include "httpd.h"
00046 #include "http_config.h"
00047 #include "http_protocol.h"
00048 #include "http_core.h"
00049 #include "http_log.h"
00050 #include "http_request.h"
00051 #include "http_main.h"
00052 #include "http_vhost.h"
00053 #include "util_cfgtree.h"
00054 #include "mpm.h"
00055
00056
00057 AP_DECLARE_DATA const char *ap_server_argv0 = NULL;
00058
00059 AP_DECLARE_DATA const char *ap_server_root = NULL;
00060
00061 AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config = NULL;
00062 AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config = NULL;
00063 AP_DECLARE_DATA apr_array_header_t *ap_server_config_defines = NULL;
00064
00065 AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL;
00066
00067 APR_HOOK_STRUCT(
00068 APR_HOOK_LINK(header_parser)
00069 APR_HOOK_LINK(pre_config)
00070 APR_HOOK_LINK(post_config)
00071 APR_HOOK_LINK(open_logs)
00072 APR_HOOK_LINK(child_init)
00073 APR_HOOK_LINK(handler)
00074 APR_HOOK_LINK(quick_handler)
00075 APR_HOOK_LINK(optional_fn_retrieve)
00076 )
00077
00078 AP_IMPLEMENT_HOOK_RUN_ALL(int, header_parser,
00079 (request_rec *r), (r), OK, DECLINED)
00080
00081 AP_IMPLEMENT_HOOK_RUN_ALL(int, pre_config,
00082 (apr_pool_t *pconf, apr_pool_t *plog,
00083 apr_pool_t *ptemp),
00084 (pconf, plog, ptemp), OK, DECLINED)
00085
00086 AP_IMPLEMENT_HOOK_RUN_ALL(int, post_config,
00087 (apr_pool_t *pconf, apr_pool_t *plog,
00088 apr_pool_t *ptemp, server_rec *s),
00089 (pconf, plog, ptemp, s), OK, DECLINED)
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 AP_IMPLEMENT_HOOK_RUN_ALL(int, open_logs,
00144 (apr_pool_t *pconf, apr_pool_t *plog,
00145 apr_pool_t *ptemp, server_rec *s),
00146 (pconf, plog, ptemp, s), OK, DECLINED)
00147
00148 AP_IMPLEMENT_HOOK_VOID(child_init,
00149 (apr_pool_t *pchild, server_rec *s),
00150 (pchild, s))
00151
00152 AP_IMPLEMENT_HOOK_RUN_FIRST(int, handler, (request_rec *r),
00153 (r), DECLINED)
00154
00155 AP_IMPLEMENT_HOOK_RUN_FIRST(int, quick_handler, (request_rec *r, int lookup),
00156 (r, lookup), DECLINED)
00157
00158 AP_IMPLEMENT_HOOK_VOID(optional_fn_retrieve, (void), ())
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static int total_modules = 0;
00170
00171
00172
00173
00174
00175 static int dynamic_modules = 0;
00176
00177 AP_DECLARE_DATA module *ap_top_module = NULL;
00178 AP_DECLARE_DATA module **ap_loaded_modules=NULL;
00179
00180 typedef int (*handler_func)(request_rec *);
00181 typedef void *(*dir_maker_func)(apr_pool_t *, char *);
00182 typedef void *(*merger_func)(apr_pool_t *, void *, void *);
00183
00184
00185 #ifndef AP_MAX_INCLUDE_DIR_DEPTH
00186 #define AP_MAX_INCLUDE_DIR_DEPTH (128)
00187 #endif
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 static ap_conf_vector_t *create_empty_config(apr_pool_t *p)
00201 {
00202 void *conf_vector = apr_pcalloc(p, sizeof(void *) *
00203 (total_modules + DYNAMIC_MODULE_LIMIT));
00204 return conf_vector;
00205 }
00206
00207 static ap_conf_vector_t *create_default_per_dir_config(apr_pool_t *p)
00208 {
00209 void **conf_vector = apr_pcalloc(p, sizeof(void *) *
00210 (total_modules + DYNAMIC_MODULE_LIMIT));
00211 module *modp;
00212
00213 for (modp = ap_top_module; modp; modp = modp->next) {
00214 dir_maker_func df = modp->create_dir_config;
00215
00216 if (df)
00217 conf_vector[modp->module_index] = (*df)(p, NULL);
00218 }
00219
00220 return (ap_conf_vector_t *)conf_vector;
00221 }
00222
00223 AP_CORE_DECLARE(ap_conf_vector_t *) ap_merge_per_dir_configs(apr_pool_t *p,
00224 ap_conf_vector_t *base,
00225 ap_conf_vector_t *new_conf)
00226 {
00227 void **conf_vector = apr_palloc(p, sizeof(void *) * total_modules);
00228 void **base_vector = (void **)base;
00229 void **new_vector = (void **)new_conf;
00230 module *modp;
00231
00232 for (modp = ap_top_module; modp; modp = modp->next) {
00233 int i = modp->module_index;
00234
00235 if (!new_vector[i]) {
00236 conf_vector[i] = base_vector[i];
00237 }
00238 else {
00239 merger_func df = modp->merge_dir_config;
00240 if (df && base_vector[i]) {
00241 conf_vector[i] = (*df)(p, base_vector[i], new_vector[i]);
00242 }
00243 else
00244 conf_vector[i] = new_vector[i];
00245 }
00246 }
00247
00248 return (ap_conf_vector_t *)conf_vector;
00249 }
00250
00251 static ap_conf_vector_t *create_server_config(apr_pool_t *p, server_rec *s)
00252 {
00253 void **conf_vector = apr_pcalloc(p, sizeof(void *) *
00254 (total_modules + DYNAMIC_MODULE_LIMIT));
00255 module *modp;
00256
00257 for (modp = ap_top_module; modp; modp = modp->next) {
00258 if (modp->create_server_config)
00259 conf_vector[modp->module_index] = (*modp->create_server_config)(p, s);
00260 }
00261
00262 return (ap_conf_vector_t *)conf_vector;
00263 }
00264
00265 static void merge_server_configs(apr_pool_t *p, ap_conf_vector_t *base,
00266 ap_conf_vector_t *virt)
00267 {
00268
00269
00270
00271
00272 void **base_vector = (void **)base;
00273 void **virt_vector = (void **)virt;
00274 module *modp;
00275
00276 for (modp = ap_top_module; modp; modp = modp->next) {
00277 merger_func df = modp->merge_server_config;
00278 int i = modp->module_index;
00279
00280 if (!virt_vector[i])
00281 virt_vector[i] = base_vector[i];
00282 else if (df)
00283 virt_vector[i] = (*df)(p, base_vector[i], virt_vector[i]);
00284 }
00285 }
00286
00287 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_request_config(apr_pool_t *p)
00288 {
00289 return create_empty_config(p);
00290 }
00291
00292 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_conn_config(apr_pool_t *p)
00293 {
00294 return create_empty_config(p);
00295 }
00296
00297 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_per_dir_config(apr_pool_t *p)
00298 {
00299 return create_empty_config(p);
00300 }
00301
00302 static int ap_invoke_filter_init(ap_filter_t *filters)
00303 {
00304 while (filters) {
00305 if (filters->frec->filter_init_func) {
00306 int result = filters->frec->filter_init_func(filters);
00307 if (result != OK) {
00308 return result;
00309 }
00310 }
00311 filters = filters->next;
00312 }
00313 return OK;
00314 }
00315
00316 AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
00317 {
00318 const char *handler;
00319 const char *p;
00320 int result;
00321 const char *old_handler = r->handler;
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 ap_run_insert_filter(r);
00332
00333
00334
00335
00336
00337 result = ap_invoke_filter_init(r->input_filters);
00338 if (result != OK) {
00339 return result;
00340 }
00341 result = ap_invoke_filter_init(r->output_filters);
00342 if (result != OK) {
00343 return result;
00344 }
00345
00346 if (!r->handler) {
00347 handler = r->content_type ? r->content_type : ap_default_type(r);
00348 if ((p=ap_strchr_c(handler, ';')) != NULL) {
00349 char *new_handler = (char *)apr_pmemdup(r->pool, handler,
00350 p - handler + 1);
00351 char *p2 = new_handler + (p - handler);
00352 handler = new_handler;
00353
00354
00355 while (p2 > handler && p2[-1] == ' ')
00356 --p2;
00357
00358 *p2='\0';
00359 }
00360
00361 r->handler = handler;
00362 }
00363
00364 result = ap_run_handler(r);
00365
00366 r->handler = old_handler;
00367
00368 if (result == DECLINED && r->handler && r->filename) {
00369 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
00370 "handler \"%s\" not found for: %s", r->handler, r->filename);
00371 }
00372
00373 return result == DECLINED ? HTTP_INTERNAL_SERVER_ERROR : result;
00374 }
00375
00376 AP_DECLARE(int) ap_method_is_limited(cmd_parms *cmd, const char *method)
00377 {
00378 int methnum;
00379
00380 methnum = ap_method_number_of(method);
00381
00382
00383
00384
00385
00386 if (methnum != M_INVALID) {
00387 return (cmd->limited & (AP_METHOD_BIT << methnum)) ? 1 : 0;
00388 }
00389
00390 return 0;
00391 }
00392
00393 AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
00394 {
00395 if (m->register_hooks) {
00396 if (getenv("SHOW_HOOKS")) {
00397 printf("Registering hooks for %s\n", m->name);
00398 apr_hook_debug_enabled = 1;
00399 }
00400
00401 apr_hook_debug_current = m->name;
00402 m->register_hooks(p);
00403 }
00404 }
00405
00406
00407
00408 AP_DECLARE(void) ap_add_module(module *m, apr_pool_t *p)
00409 {
00410
00411
00412
00413
00414
00415 if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
00416 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
00417 "%s: module \"%s\" is not compatible with this "
00418 "version of Apache (found %d, need %d).",
00419 ap_server_argv0, m->name, m->version,
00420 MODULE_MAGIC_NUMBER_MAJOR);
00421 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
00422 "Please contact the vendor for the correct version.");
00423 exit(1);
00424 }
00425
00426 if (m->next == NULL) {
00427 m->next = ap_top_module;
00428 ap_top_module = m;
00429 }
00430
00431 if (m->module_index == -1) {
00432 m->module_index = total_modules++;
00433 dynamic_modules++;
00434
00435 if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
00436 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
00437 "%s: module \"%s\" could not be loaded, because"
00438 " the dynamic", ap_server_argv0, m->name);
00439 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
00440 "module limit was reached. Please increase "
00441 "DYNAMIC_MODULE_LIMIT and recompile.");
00442 exit(1);
00443 }
00444 }
00445
00446
00447
00448
00449
00450
00451 if (ap_strrchr_c(m->name, '/'))
00452 m->name = 1 + ap_strrchr_c(m->name, '/');
00453
00454 if (ap_strrchr_c(m->name, '\\'))
00455 m->name = 1 + ap_strrchr_c(m->name, '\\');
00456
00457 #ifdef _OSD_POSIX
00458
00459
00460
00461
00462
00463 if (m->name[strlen(m->name)-1] == ')') {
00464 char *tmp = strdup(m->name);
00465 tmp[strlen(tmp)-1] = '\0';
00466 m->name = tmp;
00467 }
00468 #endif
00469
00470
00471
00472
00473 ap_register_hooks(m, p);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 AP_DECLARE(void) ap_remove_module(module *m)
00485 {
00486 module *modp;
00487
00488 modp = ap_top_module;
00489 if (modp == m) {
00490
00491 ap_top_module = modp->next;
00492 m->next = NULL;
00493 }
00494 else {
00495
00496
00497
00498
00499 while (modp && modp->next != m) {
00500 modp = modp->next;
00501 }
00502
00503 if (!modp) {
00504
00505 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
00506 "Cannot remove module %s: not found in module list",
00507 m->name);
00508 return;
00509 }
00510
00511
00512 modp->next = modp->next->next;
00513 }
00514
00515 m->module_index = -1;
00516
00517 dynamic_modules--;
00518 total_modules--;
00519 }
00520
00521 AP_DECLARE(void) ap_add_loaded_module(module *mod, apr_pool_t *p)
00522 {
00523 module **m;
00524
00525
00526
00527
00528 ap_add_module(mod, p);
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 for (m = ap_loaded_modules; *m != NULL; m++)
00539 ;
00540 *m++ = mod;
00541 *m = NULL;
00542 }
00543
00544 AP_DECLARE(void) ap_remove_loaded_module(module *mod)
00545 {
00546 module **m;
00547 module **m2;
00548 int done;
00549
00550
00551
00552
00553 ap_remove_module(mod);
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
00565 if (*m2 == mod && done == 0)
00566 done = 1;
00567 else
00568 *m++ = *m2;
00569 }
00570
00571 *m = NULL;
00572 }
00573
00574 AP_DECLARE(void) ap_setup_prelinked_modules(process_rec *process)
00575 {
00576 module **m;
00577 module **m2;
00578
00579 apr_hook_global_pool=process->pconf;
00580
00581
00582
00583
00584 total_modules = 0;
00585 for (m = ap_preloaded_modules; *m != NULL; m++)
00586 (*m)->module_index = total_modules++;
00587
00588
00589
00590
00591 ap_loaded_modules = (module **)apr_palloc(process->pool,
00592 sizeof(module *) * (total_modules + DYNAMIC_MODULE_LIMIT + 1));
00593
00594 if (ap_loaded_modules == NULL) {
00595 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
00596 "Ouch! Out of memory in ap_setup_prelinked_modules()!");
00597 }
00598
00599 for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
00600 *m2++ = *m++;
00601
00602 *m2 = NULL;
00603
00604
00605
00606
00607 for (m = ap_prelinked_modules; *m != NULL; m++)
00608 ap_add_module(*m, process->pconf);
00609
00610 apr_hook_sort_all();
00611 }
00612
00613 AP_DECLARE(const char *) ap_find_module_name(module *m)
00614 {
00615 return m->name;
00616 }
00617
00618 AP_DECLARE(module *) ap_find_linked_module(const char *name)
00619 {
00620 module *modp;
00621
00622 for (modp = ap_top_module; modp; modp = modp->next) {
00623 if (strcmp(modp->name, name) == 0)
00624 return modp;
00625 }
00626
00627 return NULL;
00628 }
00629
00630
00631 AP_DECLARE(int) ap_add_named_module(const char *name, apr_pool_t *p)
00632 {
00633 module *modp;
00634 int i = 0;
00635
00636 for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
00637 if (strcmp(modp->name, name) == 0) {
00638
00639 if (modp->next == NULL) {
00640 ap_add_module(modp, p);
00641 }
00642
00643 return 1;
00644 }
00645 }
00646
00647 return 0;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
00660 void *mconfig, const char *args)
00661 {
00662 char *w, *w2, *w3;
00663 const char *errmsg = NULL;
00664
00665 if ((parms->override & cmd->req_override) == 0)
00666 return apr_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
00667
00668 parms->info = cmd->cmd_data;
00669 parms->cmd = cmd;
00670
00671 switch (cmd->args_how) {
00672 case RAW_ARGS:
00673 #ifdef RESOLVE_ENV_PER_TOKEN
00674 args = ap_resolve_env(parms->pool,args);
00675 #endif
00676 return cmd->AP_RAW_ARGS(parms, mconfig, args);
00677
00678 case NO_ARGS:
00679 if (*args != 0)
00680 return apr_pstrcat(parms->pool, cmd->name, " takes no arguments",
00681 NULL);
00682
00683 return cmd->AP_NO_ARGS(parms, mconfig);
00684
00685 case TAKE1:
00686 w = ap_getword_conf(parms->pool, &args);
00687
00688 if (*w == '\0' || *args != 0)
00689 return apr_pstrcat(parms->pool, cmd->name, " takes one argument",
00690 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00691
00692 return cmd->AP_TAKE1(parms, mconfig, w);
00693
00694 case TAKE2:
00695 w = ap_getword_conf(parms->pool, &args);
00696 w2 = ap_getword_conf(parms->pool, &args);
00697
00698 if (*w == '\0' || *w2 == '\0' || *args != 0)
00699 return apr_pstrcat(parms->pool, cmd->name, " takes two arguments",
00700 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00701
00702 return cmd->AP_TAKE2(parms, mconfig, w, w2);
00703
00704 case TAKE12:
00705 w = ap_getword_conf(parms->pool, &args);
00706 w2 = ap_getword_conf(parms->pool, &args);
00707
00708 if (*w == '\0' || *args != 0)
00709 return apr_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
00710 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00711
00712 return cmd->AP_TAKE2(parms, mconfig, w, *w2 ? w2 : NULL);
00713
00714 case TAKE3:
00715 w = ap_getword_conf(parms->pool, &args);
00716 w2 = ap_getword_conf(parms->pool, &args);
00717 w3 = ap_getword_conf(parms->pool, &args);
00718
00719 if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
00720 return apr_pstrcat(parms->pool, cmd->name, " takes three arguments",
00721 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00722
00723 return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
00724
00725 case TAKE23:
00726 w = ap_getword_conf(parms->pool, &args);
00727 w2 = ap_getword_conf(parms->pool, &args);
00728 w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
00729
00730 if (*w == '\0' || *w2 == '\0' || *args != 0)
00731 return apr_pstrcat(parms->pool, cmd->name,
00732 " takes two or three arguments",
00733 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00734
00735 return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
00736
00737 case TAKE123:
00738 w = ap_getword_conf(parms->pool, &args);
00739 w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
00740 w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
00741
00742 if (*w == '\0' || *args != 0)
00743 return apr_pstrcat(parms->pool, cmd->name,
00744 " takes one, two or three arguments",
00745 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00746
00747 return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
00748
00749 case TAKE13:
00750 w = ap_getword_conf(parms->pool, &args);
00751 w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
00752 w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
00753
00754 if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
00755 return apr_pstrcat(parms->pool, cmd->name,
00756 " takes one or three arguments",
00757 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00758
00759 return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
00760
00761 case ITERATE:
00762 while (*(w = ap_getword_conf(parms->pool, &args)) != '\0') {
00763
00764 errmsg = cmd->AP_TAKE1(parms, mconfig, w);
00765
00766 if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
00767 return errmsg;
00768 }
00769
00770 return errmsg;
00771
00772 case ITERATE2:
00773 w = ap_getword_conf(parms->pool, &args);
00774
00775 if (*w == '\0' || *args == 0)
00776 return apr_pstrcat(parms->pool, cmd->name,
00777 " requires at least two arguments",
00778 cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
00779
00780 while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0') {
00781
00782 errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2);
00783
00784 if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
00785 return errmsg;
00786 }
00787
00788 return errmsg;
00789
00790 case FLAG:
00791 w = ap_getword_conf(parms->pool, &args);
00792
00793 if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
00794 return apr_pstrcat(parms->pool, cmd->name, " must be On or Off",
00795 NULL);
00796
00797 return cmd->AP_FLAG(parms, mconfig, strcasecmp(w, "off") != 0);
00798
00799 default:
00800 return apr_pstrcat(parms->pool, cmd->name,
00801 " is improperly configured internally (server bug)",
00802 NULL);
00803 }
00804 }
00805
00806 AP_CORE_DECLARE(const command_rec *) ap_find_command(const char *name,
00807 const command_rec *cmds)
00808 {
00809 while (cmds->name) {
00810 if (!strcasecmp(name, cmds->name))
00811 return cmds;
00812
00813 ++cmds;
00814 }
00815
00816 return NULL;
00817 }
00818
00819 AP_CORE_DECLARE(const command_rec *) ap_find_command_in_modules(
00820 const char *cmd_name, module **mod)
00821 {
00822 const command_rec *cmdp;
00823 module *modp;
00824
00825 for (modp = *mod; modp; modp = modp->next) {
00826 if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
00827 *mod = modp;
00828 return cmdp;
00829 }
00830 }
00831
00832 return NULL;
00833 }
00834
00835 AP_CORE_DECLARE(void *) ap_set_config_vectors(server_rec *server,
00836 ap_conf_vector_t *section_vector,
00837 const char *section,
00838 module *mod, apr_pool_t *pconf)
00839 {
00840 void *section_config = ap_get_module_config(section_vector, mod);
00841 void *server_config = ap_get_module_config(server->module_config, mod);
00842
00843 if (!section_config && mod->create_dir_config) {
00844
00845 section_config = (*mod->create_dir_config)(pconf, (char *)section);
00846 ap_set_module_config(section_vector, mod, section_config);
00847 }
00848
00849 if (!server_config && mod->create_server_config) {
00850 server_config = (*mod->create_server_config)(pconf, server);
00851 ap_set_module_config(server->module_config, mod, server_config);
00852 }
00853
00854 return section_config;
00855 }
00856
00857 static const char *execute_now(char *cmd_line, const char *args,
00858 cmd_parms *parms,
00859 apr_pool_t *p, apr_pool_t *ptemp,
00860 ap_directive_t **sub_tree,
00861 ap_directive_t *parent);
00862
00863 static const char *ap_build_config_sub(apr_pool_t *p, apr_pool_t *temp_pool,
00864 const char *l, cmd_parms *parms,
00865 ap_directive_t **current,
00866 ap_directive_t **curr_parent,
00867 ap_directive_t **conftree)
00868 {
00869 const char *retval = NULL;
00870 const char *args;
00871 char *cmd_name;
00872 ap_directive_t *newdir;
00873 module *mod = ap_top_module;
00874 const command_rec *cmd;
00875
00876 if (*l == '#' || *l == '\0')
00877 return NULL;
00878
00879 #if RESOLVE_ENV_PER_TOKEN
00880 args = l;
00881 #else
00882 args = ap_resolve_env(temp_pool, l);
00883 #endif
00884
00885 cmd_name = ap_getword_conf(p, &args);
00886 if (*cmd_name == '\0') {
00887
00888
00889
00890 return NULL;
00891 }
00892
00893 if (cmd_name[1] != '/') {
00894 char *lastc = cmd_name + strlen(cmd_name) - 1;
00895 if (*lastc == '>') {
00896 *lastc = '\0' ;
00897 }
00898 if (cmd_name[0] == '<' && *args == '\0') {
00899 args = ">";
00900 }
00901 }
00902
00903 newdir = apr_pcalloc(p, sizeof(ap_directive_t));
00904 newdir->filename = parms->config_file->name;
00905 newdir->line_num = parms->config_file->line_number;
00906 newdir->directive = cmd_name;
00907 newdir->args = apr_pstrdup(p, args);
00908
00909 if ((cmd = ap_find_command_in_modules(cmd_name, &mod)) != NULL) {
00910 if (cmd->req_override & EXEC_ON_READ) {
00911 ap_directive_t *sub_tree = NULL;
00912
00913 parms->err_directive = newdir;
00914 retval = execute_now(cmd_name, args, parms, p, temp_pool,
00915 &sub_tree, *curr_parent);
00916 if (*current) {
00917 (*current)->next = sub_tree;
00918 }
00919 else {
00920 *current = sub_tree;
00921 if (*curr_parent) {
00922 (*curr_parent)->first_child = (*current);
00923 }
00924 if (*current) {
00925 (*current)->parent = (*curr_parent);
00926 }
00927 }
00928 if (*current) {
00929 if (!*conftree) {
00930
00931
00932
00933 *conftree = *current;
00934 }
00935 while ((*current)->next != NULL) {
00936 (*current) = (*current)->next;
00937 (*current)->parent = (*curr_parent);
00938 }
00939 }
00940 return retval;
00941 }
00942 }
00943
00944 if (cmd_name[0] == '<') {
00945 if (cmd_name[1] != '/') {
00946 (*current) = ap_add_node(curr_parent, *current, newdir, 1);
00947 }
00948 else if (*curr_parent == NULL) {
00949 parms->err_directive = newdir;
00950 return apr_pstrcat(p, cmd_name,
00951 " without matching <", cmd_name + 2,
00952 " section", NULL);
00953 }
00954 else {
00955 char *bracket = cmd_name + strlen(cmd_name) - 1;
00956
00957 if (*bracket != '>') {
00958 parms->err_directive = newdir;
00959 return apr_pstrcat(p, cmd_name,
00960 "> directive missing closing '>'", NULL);
00961 }
00962
00963 *bracket = '\0';
00964
00965 if (strcasecmp(cmd_name + 2,
00966 (*curr_parent)->directive + 1) != 0) {
00967 parms->err_directive = newdir;
00968 return apr_pstrcat(p, "Expected </",
00969 (*curr_parent)->directive + 1, "> but saw ",
00970 cmd_name, ">", NULL);
00971 }
00972
00973 *bracket = '>';
00974
00975
00976 *current = *curr_parent;
00977 *curr_parent = (*current)->parent;
00978 }
00979 }
00980 else {
00981 *current = ap_add_node(curr_parent, *current, newdir, 0);
00982 }
00983
00984 return retval;
00985 }
00986
00987 AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
00988 apr_pool_t *temp_pool,
00989 cmd_parms *parms,
00990 ap_directive_t **current,
00991 ap_directive_t **curr_parent,
00992 char *orig_directive)
00993 {
00994 char *l;
00995 char *bracket;
00996 const char *retval;
00997 ap_directive_t *sub_tree = NULL;
00998
00999
01000
01001
01002
01003 l = apr_palloc(temp_pool, MAX_STRING_LEN);
01004
01005 bracket = apr_pstrcat(p, orig_directive + 1, ">", NULL);
01006 while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
01007 if (!memcmp(l, "</", 2)
01008 && (strcasecmp(l + 2, bracket) == 0)
01009 && (*curr_parent == NULL)) {
01010 break;
01011 }
01012 retval = ap_build_config_sub(p, temp_pool, l, parms, current,
01013 curr_parent, &sub_tree);
01014 if (retval != NULL)
01015 return retval;
01016
01017 if (sub_tree == NULL && curr_parent != NULL) {
01018 sub_tree = *curr_parent;
01019 }
01020
01021 if (sub_tree == NULL && current != NULL) {
01022 sub_tree = *current;
01023 }
01024 }
01025
01026 *current = sub_tree;
01027 return NULL;
01028 }
01029
01030 static const char *ap_walk_config_sub(const ap_directive_t *current,
01031 cmd_parms *parms,
01032 ap_conf_vector_t *section_vector)
01033 {
01034 module *mod = ap_top_module;
01035
01036 while (1) {
01037 const command_rec *cmd;
01038
01039 if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
01040 parms->err_directive = current;
01041 return apr_pstrcat(parms->pool, "Invalid command '",
01042 current->directive,
01043 "', perhaps mis-spelled or defined by a module "
01044 "not included in the server configuration",
01045 NULL);
01046 }
01047 else {
01048 void *dir_config = ap_set_config_vectors(parms->server,
01049 section_vector,
01050 parms->path,
01051 mod,
01052 parms->pool);
01053 const char *retval;
01054
01055
01056 if (cmd->req_override & EXEC_ON_READ) {
01057 return NULL;
01058 }
01059
01060 retval = invoke_cmd(cmd, parms, dir_config, current->args);
01061 if (retval == NULL) {
01062 return NULL;
01063 }
01064
01065 if (strcmp(retval, DECLINE_CMD) != 0) {
01066
01067
01068
01069
01070
01071 if (!parms->err_directive) {
01072 parms->err_directive = current;
01073 }
01074
01075 return retval;
01076 }
01077
01078 mod = mod->next;
01079 }
01080 }
01081
01082 }
01083
01084 AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current,
01085 cmd_parms *parms,
01086 ap_conf_vector_t *section_vector)
01087 {
01088 ap_conf_vector_t *oldconfig = parms->context;
01089
01090 parms->context = section_vector;
01091
01092
01093 for (; current != NULL; current = current->next) {
01094 const char *errmsg;
01095
01096 parms->directive = current;
01097
01098
01099 errmsg = ap_walk_config_sub(current, parms, section_vector);
01100 if (errmsg != NULL) {
01101
01102 parms->context = oldconfig;
01103 return errmsg;
01104 }
01105 }
01106
01107 parms->context = oldconfig;
01108 return NULL;
01109 }
01110
01111 AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
01112 apr_pool_t *p, apr_pool_t *temp_pool,
01113 ap_directive_t **conftree)
01114 {
01115 ap_directive_t *current = *conftree;
01116 ap_directive_t *curr_parent = NULL;
01117 char *l = apr_palloc (temp_pool, MAX_STRING_LEN);
01118 const char *errmsg;
01119
01120 if (current != NULL) {
01121 while (current->next) {
01122 current = current->next;
01123 }
01124 }
01125
01126 while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
01127 errmsg = ap_build_config_sub(p, temp_pool, l, parms,
01128 ¤t, &curr_parent, conftree);
01129 if (errmsg != NULL)
01130 return errmsg;
01131
01132 if (*conftree == NULL && curr_parent != NULL) {
01133 *conftree = curr_parent;
01134 }
01135
01136 if (*conftree == NULL && current != NULL) {
01137 *conftree = current;
01138 }
01139 }
01140
01141 if (curr_parent != NULL) {
01142 errmsg = "";
01143
01144 while (curr_parent != NULL) {
01145 errmsg = apr_psprintf(p, "%s%s%s:%u: %s> was not closed.",
01146 errmsg,
01147 *errmsg == '\0' ? "" : APR_EOL_STR,
01148 curr_parent->filename,
01149 curr_parent->line_num,
01150 curr_parent->directive);
01151
01152 parms->err_directive = curr_parent;
01153 curr_parent = curr_parent->parent;
01154 }
01155
01156 return errmsg;
01157 }
01158
01159 return NULL;
01160 }
01161
01162
01163
01164
01165
01166 AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
01167 void *struct_ptr,
01168 const char *arg)
01169 {
01170 int offset = (int)(long)cmd->info;
01171
01172 *(const char **)((char *)struct_ptr + offset) = arg;
01173
01174 return NULL;
01175 }
01176
01177 AP_DECLARE_NONSTD(const char *) ap_set_int_slot(cmd_parms *cmd,
01178 void *struct_ptr,
01179 const char *arg)
01180 {
01181 char *endptr;
01182 char *error_str = NULL;
01183 int offset = (int)(long)cmd->info;
01184
01185 *(int *)((char*)struct_ptr + offset) = strtol(arg, &endptr, 10);
01186
01187 if ((*arg == '\0') || (*endptr != '\0')) {
01188 error_str = apr_psprintf(cmd->pool,
01189 "Invalid value for directive %s, expected integer",
01190 cmd->directive->directive);
01191 }
01192
01193 return error_str;
01194 }
01195
01196 AP_DECLARE_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
01197 void *struct_ptr,
01198 const char *arg_)
01199 {
01200 char *arg = apr_pstrdup(cmd->pool,arg_);
01201 int offset = (int)(long)cmd->info;
01202
01203 ap_str_tolower(arg);
01204 *(char **)((char *)struct_ptr + offset) = arg;
01205
01206 return NULL;
01207 }
01208
01209 AP_DECLARE_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
01210 void *struct_ptr_v, int arg)
01211 {
01212 int offset = (int)(long)cmd->info;
01213 char *struct_ptr = (char *)struct_ptr_v;
01214
01215 *(int *)(struct_ptr + offset) = arg ? 1 : 0;
01216
01217 return NULL;
01218 }
01219
01220 AP_DECLARE_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, void *struct_ptr,
01221 const char *arg)
01222 {
01223
01224
01225
01226
01227 const char *path;
01228 int offset = (int)(long)cmd->info;
01229
01230 path = ap_server_root_relative(cmd->pool, arg);
01231
01232 if (!path) {
01233 return apr_pstrcat(cmd->pool, "Invalid file path ",
01234 arg, NULL);
01235 }
01236
01237 *(const char **) ((char*)struct_ptr + offset) = path;
01238
01239 return NULL;
01240 }
01241
01242 AP_DECLARE_NONSTD(const char *) ap_set_deprecated(cmd_parms *cmd,
01243 void *struct_ptr,
01244 const char *arg)
01245 {
01246 return cmd->cmd->errmsg;
01247 }
01248
01249
01250
01251
01252
01253
01254 static cmd_parms default_parms =
01255 {NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
01256
01257 AP_DECLARE(char *) ap_server_root_relative(apr_pool_t *p, const char *file)
01258 {
01259 char *newpath = NULL;
01260 apr_status_t rv;
01261 rv = apr_filepath_merge(&newpath, ap_server_root, file,
01262 APR_FILEPATH_TRUENAME, p);
01263 if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv)
01264 || APR_STATUS_IS_ENOENT(rv)
01265 || APR_STATUS_IS_ENOTDIR(rv))) {
01266 return newpath;
01267 }
01268 else {
01269 return NULL;
01270 }
01271 }
01272
01273 AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
01274 {
01275 char l[MAX_STRING_LEN];
01276 const char *args;
01277 char *cmd_name;
01278
01279 while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
01280 #if RESOLVE_ENV_PER_TOKEN
01281 args = l;
01282 #else
01283 args = ap_resolve_env(cmd->temp_pool, l);
01284 #endif
01285
01286 cmd_name = ap_getword_conf(cmd->pool, &args);
01287 if (cmd_name[0] == '<') {
01288 if (cmd_name[1] == '/') {
01289 cmd_name[strlen(cmd_name) - 1] = '\0';
01290
01291 if (strcasecmp(cmd_name + 2, directive + 1) != 0) {
01292 return apr_pstrcat(cmd->pool, "Expected </",
01293 directive + 1, "> but saw ",
01294 cmd_name, ">", NULL);
01295 }
01296
01297 return NULL;
01298 }
01299 else {
01300 const char *msg;
01301
01302 if (*args == '\0' && cmd_name[strlen(cmd_name) - 1] == '>') {
01303 cmd_name[strlen(cmd_name) - 1] = '\0';
01304 }
01305
01306 if ((msg = ap_soak_end_container(cmd, cmd_name)) != NULL) {
01307 return msg;
01308 }
01309 }
01310 }
01311 }
01312
01313 return apr_pstrcat(cmd->pool, "Expected </",
01314 directive + 1, "> before end of configuration",
01315 NULL);
01316 }
01317
01318 static const char *execute_now(char *cmd_line, const char *args,
01319 cmd_parms *parms,
01320 apr_pool_t *p, apr_pool_t *ptemp,
01321 ap_directive_t **sub_tree,
01322 ap_directive_t *parent)
01323 {
01324 module *mod = ap_top_module;
01325 const command_rec *cmd;
01326
01327 if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
01328 return apr_pstrcat(parms->pool, "Invalid command '",
01329 cmd_line,
01330 "', perhaps mis-spelled or defined by a module "
01331 "not included in the server configuration",
01332 NULL);
01333 }
01334 else {
01335 return invoke_cmd(cmd, parms, sub_tree, args);
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 typedef struct {
01350 apr_array_header_t *array;
01351 int curr_idx;
01352 } arr_elts_param_t;
01353
01354
01355
01356 static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
01357 {
01358 arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
01359
01360
01361 if (++arr_param->curr_idx > arr_param->array->nelts)
01362 return NULL;
01363
01364
01365 apr_cpystrn(buf,
01366 ((char **)arr_param->array->elts)[arr_param->curr_idx - 1],
01367 bufsiz);
01368
01369 return buf;
01370 }
01371
01372
01373
01374 static int arr_elts_close(void *param)
01375 {
01376 arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
01377
01378 arr_param->curr_idx = arr_param->array->nelts;
01379
01380 return 0;
01381 }
01382
01383 static void process_command_config(server_rec *s, apr_array_header_t *arr,
01384 ap_directive_t **conftree, apr_pool_t *p,
01385 apr_pool_t *ptemp)
01386 {
01387 const char *errmsg;
01388 cmd_parms parms;
01389 arr_elts_param_t arr_parms;
01390
01391 arr_parms.curr_idx = 0;
01392 arr_parms.array = arr;
01393
01394 parms = default_parms;
01395 parms.pool = p;
01396 parms.temp_pool = ptemp;
01397 parms.server = s;
01398 parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
01399
01400 parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
01401 &arr_parms, NULL,
01402 arr_elts_getstr, arr_elts_close);
01403
01404 errmsg = ap_build_config(&parms, p, ptemp, conftree);
01405 if (errmsg) {
01406 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
01407 "Syntax error in -C/-c directive:");
01408 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
01409 "%s", errmsg);
01410 exit(1);
01411 }
01412
01413 ap_cfg_closefile(parms.config_file);
01414 }
01415
01416 typedef struct {
01417 char *fname;
01418 } fnames;
01419
01420 static int fname_alphasort(const void *fn1, const void *fn2)
01421 {
01422 const fnames *f1 = fn1;
01423 const fnames *f2 = fn2;
01424
01425 return strcmp(f1->fname,f2->fname);
01426 }
01427
01428 static void process_resource_config_nofnmatch(server_rec *s, const char *fname,
01429 ap_directive_t **conftree,
01430 apr_pool_t *p,
01431 apr_pool_t *ptemp,
01432 unsigned depth)
01433 {
01434 cmd_parms parms;
01435 ap_configfile_t *cfp;
01436 const char *errmsg;
01437
01438 if (ap_is_directory(p, fname)) {
01439 apr_dir_t *dirp;
01440 apr_finfo_t dirent;
01441 i