~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to server/core.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "apr.h"
 
18
#include "apr_strings.h"
 
19
#include "apr_lib.h"
 
20
#include "apr_fnmatch.h"
 
21
#include "apr_hash.h"
 
22
#include "apr_thread_proc.h"    /* for RLIMIT stuff */
 
23
#include "apr_hooks.h"
 
24
 
 
25
#define APR_WANT_IOVEC
 
26
#define APR_WANT_STRFUNC
 
27
#define APR_WANT_MEMFUNC
 
28
#include "apr_want.h"
 
29
 
 
30
#define CORE_PRIVATE
 
31
#include "ap_config.h"
 
32
#include "httpd.h"
 
33
#include "http_config.h"
 
34
#include "http_core.h"
 
35
#include "http_protocol.h" /* For index_of_response().  Grump. */
 
36
#include "http_request.h"
 
37
#include "http_vhost.h"
 
38
#include "http_main.h"     /* For the default_handler below... */
 
39
#include "http_log.h"
 
40
#include "util_md5.h"
 
41
#include "http_connection.h"
 
42
#include "apr_buckets.h"
 
43
#include "util_filter.h"
 
44
#include "util_ebcdic.h"
 
45
#include "mpm.h"
 
46
#include "mpm_common.h"
 
47
#include "scoreboard.h"
 
48
#include "mod_core.h"
 
49
#include "mod_proxy.h"
 
50
#include "ap_listen.h"
 
51
 
 
52
#include "mod_so.h" /* for ap_find_loaded_module_symbol */
 
53
 
 
54
/* LimitRequestBody handling */
 
55
#define AP_LIMIT_REQ_BODY_UNSET         ((apr_off_t) -1)
 
56
#define AP_DEFAULT_LIMIT_REQ_BODY       ((apr_off_t) 0)
 
57
 
 
58
/* LimitXMLRequestBody handling */
 
59
#define AP_LIMIT_UNSET                  ((long) -1)
 
60
#define AP_DEFAULT_LIMIT_XML_BODY       ((size_t)1000000)
 
61
 
 
62
#define AP_MIN_SENDFILE_BYTES           (256)
 
63
 
 
64
/* maximum include nesting level */
 
65
#ifndef AP_MAX_INCLUDE_DEPTH
 
66
#define AP_MAX_INCLUDE_DEPTH            (128)
 
67
#endif
 
68
 
 
69
APR_HOOK_STRUCT(
 
70
    APR_HOOK_LINK(get_mgmt_items)
 
71
)
 
72
 
 
73
AP_IMPLEMENT_HOOK_RUN_ALL(int, get_mgmt_items,
 
74
                          (apr_pool_t *p, const char *val, apr_hash_t *ht),
 
75
                          (p, val, ht), OK, DECLINED)
 
76
 
 
77
/* Server core module... This module provides support for really basic
 
78
 * server operations, including options and commands which control the
 
79
 * operation of other modules.  Consider this the bureaucracy module.
 
80
 *
 
81
 * The core module also defines handlers, etc., do handle just enough
 
82
 * to allow a server with the core module ONLY to actually serve documents
 
83
 * (though it slaps DefaultType on all of 'em); this was useful in testing,
 
84
 * but may not be worth preserving.
 
85
 *
 
86
 * This file could almost be mod_core.c, except for the stuff which affects
 
87
 * the http_conf_globals.
 
88
 */
 
89
 
 
90
/* Handles for core filters */
 
91
AP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle;
 
92
AP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle;
 
93
AP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle;
 
94
AP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle;
 
95
 
 
96
/* magic pointer for ErrorDocument xxx "default" */
 
97
static char errordocument_default;
 
98
 
 
99
static void *create_core_dir_config(apr_pool_t *a, char *dir)
 
100
{
 
101
    core_dir_config *conf;
 
102
    int i;
 
103
 
 
104
    conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
 
105
 
 
106
    /* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
 
107
 
 
108
    conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
 
109
    conf->opts_add = conf->opts_remove = OPT_NONE;
 
110
    conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
 
111
    conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER
 
112
                          | OPT_MULTI;
 
113
 
 
114
    conf->content_md5 = 2;
 
115
    conf->accept_path_info = 3;
 
116
 
 
117
    conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
 
118
    conf->use_canonical_phys_port = USE_CANONICAL_PHYS_PORT_UNSET;
 
119
 
 
120
    conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
 
121
    conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
 
122
    for (i = 0; i < METHODS; ++i) {
 
123
        conf->satisfy[i] = SATISFY_NOSPEC;
 
124
    }
 
125
 
 
126
#ifdef RLIMIT_CPU
 
127
    conf->limit_cpu = NULL;
 
128
#endif
 
129
#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
 
130
    conf->limit_mem = NULL;
 
131
#endif
 
132
#ifdef RLIMIT_NPROC
 
133
    conf->limit_nproc = NULL;
 
134
#endif
 
135
 
 
136
    conf->limit_req_body = AP_LIMIT_REQ_BODY_UNSET;
 
137
    conf->limit_xml_body = AP_LIMIT_UNSET;
 
138
    conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
 
139
 
 
140
    conf->server_signature = srv_sig_unset;
 
141
 
 
142
    conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
 
143
    conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
 
144
 
 
145
    /* Overriding all negotiation
 
146
     */
 
147
    conf->mime_type = NULL;
 
148
    conf->handler = NULL;
 
149
    conf->output_filters = NULL;
 
150
    conf->input_filters = NULL;
 
151
 
 
152
    /*
 
153
     * Flag for use of inodes in ETags.
 
154
     */
 
155
    conf->etag_bits = ETAG_UNSET;
 
156
    conf->etag_add = ETAG_UNSET;
 
157
    conf->etag_remove = ETAG_UNSET;
 
158
 
 
159
    conf->enable_mmap = ENABLE_MMAP_UNSET;
 
160
    conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
 
161
    conf->allow_encoded_slashes = 0;
 
162
 
 
163
    return (void *)conf;
 
164
}
 
165
 
 
166
/*
 
167
 * Overlay one hash table of ct_output_filters onto another
 
168
 */
 
169
static void *merge_ct_filters(apr_pool_t *p,
 
170
                              const void *key,
 
171
                              apr_ssize_t klen,
 
172
                              const void *overlay_val,
 
173
                              const void *base_val,
 
174
                              const void *data)
 
175
{
 
176
    ap_filter_rec_t *cur;
 
177
    const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
 
178
    const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
 
179
 
 
180
    cur = NULL;
 
181
 
 
182
    while (overlay_info) {
 
183
        ap_filter_rec_t *new;
 
184
 
 
185
        new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
 
186
        new->name = apr_pstrdup(p, overlay_info->name);
 
187
        new->next = cur;
 
188
        cur = new;
 
189
        overlay_info = overlay_info->next;
 
190
    }
 
191
 
 
192
    while (base_info) {
 
193
        ap_filter_rec_t *f;
 
194
        int found = 0;
 
195
 
 
196
        /* We can't have dups. */
 
197
        f = cur;
 
198
        while (f) {
 
199
            if (!strcasecmp(base_info->name, f->name)) {
 
200
                found = 1;
 
201
                break;
 
202
            }
 
203
 
 
204
            f = f->next;
 
205
        }
 
206
 
 
207
        if (!found) {
 
208
            f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
 
209
            f->name = apr_pstrdup(p, base_info->name);
 
210
            f->next = cur;
 
211
            cur = f;
 
212
        }
 
213
 
 
214
        base_info = base_info->next;
 
215
    }
 
216
 
 
217
    return cur;
 
218
}
 
219
 
 
220
static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
 
221
{
 
222
    core_dir_config *base = (core_dir_config *)basev;
 
223
    core_dir_config *new = (core_dir_config *)newv;
 
224
    core_dir_config *conf;
 
225
    int i;
 
226
 
 
227
    /* Create this conf by duplicating the base, replacing elements
 
228
     * (or creating copies for merging) where new-> values exist.
 
229
     */
 
230
    conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
 
231
    memcpy(conf, base, sizeof(core_dir_config));
 
232
 
 
233
    conf->d = new->d;
 
234
    conf->d_is_fnmatch = new->d_is_fnmatch;
 
235
    conf->d_components = new->d_components;
 
236
    conf->r = new->r;
 
237
 
 
238
    if (new->opts & OPT_UNSET) {
 
239
        /* there was no explicit setting of new->opts, so we merge
 
240
         * preserve the invariant (opts_add & opts_remove) == 0
 
241
         */
 
242
        conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
 
243
        conf->opts_remove = (conf->opts_remove & ~new->opts_add)
 
244
                            | new->opts_remove;
 
245
        conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
 
246
        if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
 
247
            conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
 
248
        }
 
249
    }
 
250
    else {
 
251
        /* otherwise we just copy, because an explicit opts setting
 
252
         * overrides all earlier +/- modifiers
 
253
         */
 
254
        conf->opts = new->opts;
 
255
        conf->opts_add = new->opts_add;
 
256
        conf->opts_remove = new->opts_remove;
 
257
    }
 
258
 
 
259
    if (!(new->override & OR_UNSET)) {
 
260
        conf->override = new->override;
 
261
    }
 
262
 
 
263
    if (!(new->override_opts & OPT_UNSET)) {
 
264
        conf->override_opts = new->override_opts;
 
265
    }
 
266
 
 
267
    if (new->ap_default_type) {
 
268
        conf->ap_default_type = new->ap_default_type;
 
269
    }
 
270
 
 
271
    if (new->ap_auth_type) {
 
272
        conf->ap_auth_type = new->ap_auth_type;
 
273
    }
 
274
 
 
275
    if (new->ap_auth_name) {
 
276
        conf->ap_auth_name = new->ap_auth_name;
 
277
    }
 
278
 
 
279
    if (new->ap_requires) {
 
280
        conf->ap_requires = new->ap_requires;
 
281
    }
 
282
 
 
283
    if (conf->response_code_strings == NULL) {
 
284
        conf->response_code_strings = new->response_code_strings;
 
285
    }
 
286
    else if (new->response_code_strings != NULL) {
 
287
        /* If we merge, the merge-result must have it's own array
 
288
         */
 
289
        conf->response_code_strings = apr_palloc(a,
 
290
            sizeof(*conf->response_code_strings) * RESPONSE_CODES);
 
291
        memcpy(conf->response_code_strings, base->response_code_strings,
 
292
               sizeof(*conf->response_code_strings) * RESPONSE_CODES);
 
293
 
 
294
        for (i = 0; i < RESPONSE_CODES; ++i) {
 
295
            if (new->response_code_strings[i] != NULL) {
 
296
                conf->response_code_strings[i] = new->response_code_strings[i];
 
297
            }
 
298
        }
 
299
    }
 
300
    /* Otherwise we simply use the base->response_code_strings array
 
301
     */
 
302
 
 
303
    if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
 
304
        conf->hostname_lookups = new->hostname_lookups;
 
305
    }
 
306
 
 
307
    if ((new->content_md5 & 2) == 0) {
 
308
        conf->content_md5 = new->content_md5;
 
309
    }
 
310
 
 
311
    if (new->accept_path_info != 3) {
 
312
        conf->accept_path_info = new->accept_path_info;
 
313
    }
 
314
 
 
315
    if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
 
316
        conf->use_canonical_name = new->use_canonical_name;
 
317
    }
 
318
 
 
319
    if (new->use_canonical_phys_port != USE_CANONICAL_PHYS_PORT_UNSET) {
 
320
        conf->use_canonical_phys_port = new->use_canonical_phys_port;
 
321
    }
 
322
 
 
323
#ifdef RLIMIT_CPU
 
324
    if (new->limit_cpu) {
 
325
        conf->limit_cpu = new->limit_cpu;
 
326
    }
 
327
#endif
 
328
 
 
329
#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
 
330
    if (new->limit_mem) {
 
331
        conf->limit_mem = new->limit_mem;
 
332
    }
 
333
#endif
 
334
 
 
335
#ifdef RLIMIT_NPROC
 
336
    if (new->limit_nproc) {
 
337
        conf->limit_nproc = new->limit_nproc;
 
338
    }
 
339
#endif
 
340
 
 
341
    if (new->limit_req_body != AP_LIMIT_REQ_BODY_UNSET) {
 
342
        conf->limit_req_body = new->limit_req_body;
 
343
    }
 
344
 
 
345
    if (new->limit_xml_body != AP_LIMIT_UNSET)
 
346
        conf->limit_xml_body = new->limit_xml_body;
 
347
    else
 
348
        conf->limit_xml_body = base->limit_xml_body;
 
349
 
 
350
    if (!conf->sec_file) {
 
351
        conf->sec_file = new->sec_file;
 
352
    }
 
353
    else if (new->sec_file) {
 
354
        /* If we merge, the merge-result must have it's own array
 
355
         */
 
356
        conf->sec_file = apr_array_append(a, base->sec_file, new->sec_file);
 
357
    }
 
358
    /* Otherwise we simply use the base->sec_file array
 
359
     */
 
360
 
 
361
    /* use a separate ->satisfy[] array either way */
 
362
    conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
 
363
    for (i = 0; i < METHODS; ++i) {
 
364
        if (new->satisfy[i] != SATISFY_NOSPEC) {
 
365
            conf->satisfy[i] = new->satisfy[i];
 
366
        } else {
 
367
            conf->satisfy[i] = base->satisfy[i];
 
368
        }
 
369
    }
 
370
 
 
371
    if (new->server_signature != srv_sig_unset) {
 
372
        conf->server_signature = new->server_signature;
 
373
    }
 
374
 
 
375
    if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
 
376
        conf->add_default_charset = new->add_default_charset;
 
377
        conf->add_default_charset_name = new->add_default_charset_name;
 
378
    }
 
379
 
 
380
    /* Overriding all negotiation
 
381
     */
 
382
    if (new->mime_type) {
 
383
        conf->mime_type = new->mime_type;
 
384
    }
 
385
 
 
386
    if (new->handler) {
 
387
        conf->handler = new->handler;
 
388
    }
 
389
 
 
390
    if (new->output_filters) {
 
391
        conf->output_filters = new->output_filters;
 
392
    }
 
393
 
 
394
    if (new->input_filters) {
 
395
        conf->input_filters = new->input_filters;
 
396
    }
 
397
 
 
398
    if (conf->ct_output_filters && new->ct_output_filters) {
 
399
        conf->ct_output_filters = apr_hash_merge(a,
 
400
                                                 new->ct_output_filters,
 
401
                                                 conf->ct_output_filters,
 
402
                                                 merge_ct_filters,
 
403
                                                 NULL);
 
404
    }
 
405
    else if (new->ct_output_filters) {
 
406
        conf->ct_output_filters = apr_hash_copy(a, new->ct_output_filters);
 
407
    }
 
408
    else if (conf->ct_output_filters) {
 
409
        /* That memcpy above isn't enough. */
 
410
        conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
 
411
    }
 
412
 
 
413
    /*
 
414
     * Now merge the setting of the FileETag directive.
 
415
     */
 
416
    if (new->etag_bits == ETAG_UNSET) {
 
417
        conf->etag_add =
 
418
            (conf->etag_add & (~ new->etag_remove)) | new->etag_add;
 
419
        conf->etag_remove =
 
420
            (conf->opts_remove & (~ new->etag_add)) | new->etag_remove;
 
421
        conf->etag_bits =
 
422
            (conf->etag_bits & (~ conf->etag_remove)) | conf->etag_add;
 
423
    }
 
424
    else {
 
425
        conf->etag_bits = new->etag_bits;
 
426
        conf->etag_add = new->etag_add;
 
427
        conf->etag_remove = new->etag_remove;
 
428
    }
 
429
 
 
430
    if (conf->etag_bits != ETAG_NONE) {
 
431
        conf->etag_bits &= (~ ETAG_NONE);
 
432
    }
 
433
 
 
434
    if (new->enable_mmap != ENABLE_MMAP_UNSET) {
 
435
        conf->enable_mmap = new->enable_mmap;
 
436
    }
 
437
 
 
438
    if (new->enable_sendfile != ENABLE_SENDFILE_UNSET) {
 
439
        conf->enable_sendfile = new->enable_sendfile;
 
440
    }
 
441
 
 
442
    conf->allow_encoded_slashes = new->allow_encoded_slashes;
 
443
 
 
444
    return (void*)conf;
 
445
}
 
446
 
 
447
static void *create_core_server_config(apr_pool_t *a, server_rec *s)
 
448
{
 
449
    core_server_config *conf;
 
450
    int is_virtual = s->is_virtual;
 
451
 
 
452
    conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
 
453
 
 
454
#ifdef GPROF
 
455
    conf->gprof_dir = NULL;
 
456
#endif
 
457
 
 
458
    conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
 
459
    conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
 
460
    conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
 
461
    conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
 
462
 
 
463
    /* recursion stopper */
 
464
    conf->redirect_limit = 0; /* 0 == unset */
 
465
    conf->subreq_limit = 0;
 
466
 
 
467
    conf->protocol = NULL;
 
468
    conf->accf_map = apr_table_make(a, 5);
 
469
 
 
470
#ifdef APR_TCP_DEFER_ACCEPT
 
471
    apr_table_set(conf->accf_map, "http", "data");
 
472
    apr_table_set(conf->accf_map, "https", "data");
 
473
#endif
 
474
 
 
475
#if APR_HAS_SO_ACCEPTFILTER
 
476
#ifndef ACCEPT_FILTER_NAME
 
477
#define ACCEPT_FILTER_NAME "httpready"
 
478
#ifdef __FreeBSD_version
 
479
#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */
 
480
#undef ACCEPT_FILTER_NAME
 
481
#define ACCEPT_FILTER_NAME "dataready"
 
482
#endif
 
483
#endif
 
484
#endif
 
485
    apr_table_set(conf->accf_map, "http", ACCEPT_FILTER_NAME);
 
486
    apr_table_set(conf->accf_map, "https", "dataready");
 
487
#endif
 
488
 
 
489
    conf->trace_enable = AP_TRACE_UNSET;
 
490
 
 
491
    return (void *)conf;
 
492
}
 
493
 
 
494
static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
 
495
{
 
496
    core_server_config *base = (core_server_config *)basev;
 
497
    core_server_config *virt = (core_server_config *)virtv;
 
498
    core_server_config *conf;
 
499
 
 
500
    conf = (core_server_config *)apr_palloc(p, sizeof(core_server_config));
 
501
    memcpy(conf, virt, sizeof(core_server_config));
 
502
 
 
503
    if (!conf->access_name) {
 
504
        conf->access_name = base->access_name;
 
505
    }
 
506
 
 
507
    if (!conf->ap_document_root) {
 
508
        conf->ap_document_root = base->ap_document_root;
 
509
    }
 
510
 
 
511
    if (!conf->protocol) {
 
512
        conf->protocol = base->protocol;
 
513
    }
 
514
 
 
515
    conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
 
516
    conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
 
517
 
 
518
    conf->redirect_limit = virt->redirect_limit
 
519
                           ? virt->redirect_limit
 
520
                           : base->redirect_limit;
 
521
 
 
522
    conf->subreq_limit = virt->subreq_limit
 
523
                         ? virt->subreq_limit
 
524
                         : base->subreq_limit;
 
525
 
 
526
    conf->trace_enable = (virt->trace_enable != AP_TRACE_UNSET)
 
527
                         ? virt->trace_enable
 
528
                         : base->trace_enable;
 
529
 
 
530
    return conf;
 
531
}
 
532
 
 
533
/* Add per-directory configuration entry (for <directory> section);
 
534
 * these are part of the core server config.
 
535
 */
 
536
 
 
537
AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
 
538
{
 
539
    core_server_config *sconf = ap_get_module_config(s->module_config,
 
540
                                                     &core_module);
 
541
    void **new_space = (void **)apr_array_push(sconf->sec_dir);
 
542
 
 
543
    *new_space = dir_config;
 
544
}
 
545
 
 
546
AP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config)
 
547
{
 
548
    core_server_config *sconf = ap_get_module_config(s->module_config,
 
549
                                                     &core_module);
 
550
    void **new_space = (void **)apr_array_push(sconf->sec_url);
 
551
 
 
552
    *new_space = url_config;
 
553
}
 
554
 
 
555
AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
 
556
{
 
557
    void **new_space = (void **)apr_array_push(conf->sec_file);
 
558
 
 
559
    *new_space = url_config;
 
560
}
 
561
 
 
562
/* We need to do a stable sort, qsort isn't stable.  So to make it stable
 
563
 * we'll be maintaining the original index into the list, and using it
 
564
 * as the minor key during sorting.  The major key is the number of
 
565
 * components (where the root component is zero).
 
566
 */
 
567
struct reorder_sort_rec {
 
568
    ap_conf_vector_t *elt;
 
569
    int orig_index;
 
570
};
 
571
 
 
572
static int reorder_sorter(const void *va, const void *vb)
 
573
{
 
574
    const struct reorder_sort_rec *a = va;
 
575
    const struct reorder_sort_rec *b = vb;
 
576
    core_dir_config *core_a;
 
577
    core_dir_config *core_b;
 
578
 
 
579
    core_a = ap_get_module_config(a->elt, &core_module);
 
580
    core_b = ap_get_module_config(b->elt, &core_module);
 
581
 
 
582
    /* a regex always sorts after a non-regex
 
583
     */
 
584
    if (!core_a->r && core_b->r) {
 
585
        return -1;
 
586
    }
 
587
    else if (core_a->r && !core_b->r) {
 
588
        return 1;
 
589
    }
 
590
 
 
591
    /* we always sort next by the number of components
 
592
     */
 
593
    if (core_a->d_components < core_b->d_components) {
 
594
        return -1;
 
595
    }
 
596
    else if (core_a->d_components > core_b->d_components) {
 
597
        return 1;
 
598
    }
 
599
 
 
600
    /* They have the same number of components, we now have to compare
 
601
     * the minor key to maintain the original order (from the config.)
 
602
     */
 
603
    return a->orig_index - b->orig_index;
 
604
}
 
605
 
 
606
void ap_core_reorder_directories(apr_pool_t *p, server_rec *s)
 
607
{
 
608
    core_server_config *sconf;
 
609
    apr_array_header_t *sec_dir;
 
610
    struct reorder_sort_rec *sortbin;
 
611
    int nelts;
 
612
    ap_conf_vector_t **elts;
 
613
    int i;
 
614
    apr_pool_t *tmp;
 
615
 
 
616
    sconf = ap_get_module_config(s->module_config, &core_module);
 
617
    sec_dir = sconf->sec_dir;
 
618
    nelts = sec_dir->nelts;
 
619
    elts = (ap_conf_vector_t **)sec_dir->elts;
 
620
 
 
621
    if (!nelts) {
 
622
        /* simple case of already being sorted... */
 
623
        /* We're not checking this condition to be fast... we're checking
 
624
         * it to avoid trying to palloc zero bytes, which can trigger some
 
625
         * memory debuggers to barf
 
626
         */
 
627
        return;
 
628
    }
 
629
 
 
630
    /* we have to allocate tmp space to do a stable sort */
 
631
    apr_pool_create(&tmp, p);
 
632
    sortbin = apr_palloc(tmp, sec_dir->nelts * sizeof(*sortbin));
 
633
    for (i = 0; i < nelts; ++i) {
 
634
        sortbin[i].orig_index = i;
 
635
        sortbin[i].elt = elts[i];
 
636
    }
 
637
 
 
638
    qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
 
639
 
 
640
    /* and now copy back to the original array */
 
641
    for (i = 0; i < nelts; ++i) {
 
642
        elts[i] = sortbin[i].elt;
 
643
    }
 
644
 
 
645
    apr_pool_destroy(tmp);
 
646
}
 
647
 
 
648
/*****************************************************************
 
649
 *
 
650
 * There are some elements of the core config structures in which
 
651
 * other modules have a legitimate interest (this is ugly, but necessary
 
652
 * to preserve NCSA back-compatibility).  So, we have a bunch of accessors
 
653
 * here...
 
654
 */
 
655
 
 
656
AP_DECLARE(int) ap_allow_options(request_rec *r)
 
657
{
 
658
    core_dir_config *conf =
 
659
      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
 
660
 
 
661
    return conf->opts;
 
662
}
 
663
 
 
664
AP_DECLARE(int) ap_allow_overrides(request_rec *r)
 
665
{
 
666
    core_dir_config *conf;
 
667
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
668
                                                   &core_module);
 
669
 
 
670
    return conf->override;
 
671
}
 
672
 
 
673
AP_DECLARE(const char *) ap_auth_type(request_rec *r)
 
674
{
 
675
    core_dir_config *conf;
 
676
 
 
677
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
678
                                                   &core_module);
 
679
 
 
680
    return conf->ap_auth_type;
 
681
}
 
682
 
 
683
AP_DECLARE(const char *) ap_auth_name(request_rec *r)
 
684
{
 
685
    core_dir_config *conf;
 
686
 
 
687
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
688
                                                   &core_module);
 
689
 
 
690
    return conf->ap_auth_name;
 
691
}
 
692
 
 
693
AP_DECLARE(const char *) ap_default_type(request_rec *r)
 
694
{
 
695
    core_dir_config *conf;
 
696
 
 
697
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
698
                                                   &core_module);
 
699
 
 
700
    return conf->ap_default_type
 
701
               ? conf->ap_default_type
 
702
               : DEFAULT_CONTENT_TYPE;
 
703
}
 
704
 
 
705
AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
 
706
{
 
707
    core_server_config *conf;
 
708
 
 
709
    conf = (core_server_config *)ap_get_module_config(r->server->module_config,
 
710
                                                      &core_module);
 
711
 
 
712
    return conf->ap_document_root;
 
713
}
 
714
 
 
715
AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r)
 
716
{
 
717
    core_dir_config *conf;
 
718
 
 
719
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
720
                                                   &core_module);
 
721
 
 
722
    return conf->ap_requires;
 
723
}
 
724
 
 
725
AP_DECLARE(int) ap_satisfies(request_rec *r)
 
726
{
 
727
    core_dir_config *conf;
 
728
 
 
729
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
730
                                                   &core_module);
 
731
 
 
732
    return conf->satisfy[r->method_number];
 
733
}
 
734
 
 
735
/* Should probably just get rid of this... the only code that cares is
 
736
 * part of the core anyway (and in fact, it isn't publicised to other
 
737
 * modules).
 
738
 */
 
739
 
 
740
char *ap_response_code_string(request_rec *r, int error_index)
 
741
{
 
742
    core_dir_config *dirconf;
 
743
    core_request_config *reqconf;
 
744
 
 
745
    /* check for string registered via ap_custom_response() first */
 
746
    reqconf = (core_request_config *)ap_get_module_config(r->request_config,
 
747
                                                          &core_module);
 
748
    if (reqconf->response_code_strings != NULL &&
 
749
        reqconf->response_code_strings[error_index] != NULL) {
 
750
        return reqconf->response_code_strings[error_index];
 
751
    }
 
752
 
 
753
    /* check for string specified via ErrorDocument */
 
754
    dirconf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
755
                                                      &core_module);
 
756
 
 
757
    if (dirconf->response_code_strings == NULL) {
 
758
        return NULL;
 
759
    }
 
760
 
 
761
    if (dirconf->response_code_strings[error_index] == &errordocument_default) {
 
762
        return NULL;
 
763
    }
 
764
 
 
765
    return dirconf->response_code_strings[error_index];
 
766
}
 
767
 
 
768
 
 
769
/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
 
770
static APR_INLINE void do_double_reverse (conn_rec *conn)
 
771
{
 
772
    apr_sockaddr_t *sa;
 
773
    apr_status_t rv;
 
774
 
 
775
    if (conn->double_reverse) {
 
776
        /* already done */
 
777
        return;
 
778
    }
 
779
 
 
780
    if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
 
781
        /* single reverse failed, so don't bother */
 
782
        conn->double_reverse = -1;
 
783
        return;
 
784
    }
 
785
 
 
786
    rv = apr_sockaddr_info_get(&sa, conn->remote_host, APR_UNSPEC, 0, 0, conn->pool);
 
787
    if (rv == APR_SUCCESS) {
 
788
        while (sa) {
 
789
            if (apr_sockaddr_equal(sa, conn->remote_addr)) {
 
790
                conn->double_reverse = 1;
 
791
                return;
 
792
            }
 
793
 
 
794
            sa = sa->next;
 
795
        }
 
796
    }
 
797
 
 
798
    conn->double_reverse = -1;
 
799
}
 
800
 
 
801
AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
 
802
                                            int type, int *str_is_ip)
 
803
{
 
804
    int hostname_lookups;
 
805
    int ignored_str_is_ip;
 
806
 
 
807
    if (!str_is_ip) { /* caller doesn't want to know */
 
808
        str_is_ip = &ignored_str_is_ip;
 
809
    }
 
810
    *str_is_ip = 0;
 
811
 
 
812
    /* If we haven't checked the host name, and we want to */
 
813
    if (dir_config) {
 
814
        hostname_lookups =
 
815
            ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
 
816
            ->hostname_lookups;
 
817
 
 
818
        if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
 
819
            hostname_lookups = HOSTNAME_LOOKUP_OFF;
 
820
        }
 
821
    }
 
822
    else {
 
823
        /* the default */
 
824
        hostname_lookups = HOSTNAME_LOOKUP_OFF;
 
825
    }
 
826
 
 
827
    if (type != REMOTE_NOLOOKUP
 
828
        && conn->remote_host == NULL
 
829
        && (type == REMOTE_DOUBLE_REV
 
830
        || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
 
831
 
 
832
        if (apr_getnameinfo(&conn->remote_host, conn->remote_addr, 0)
 
833
            == APR_SUCCESS) {
 
834
            ap_str_tolower(conn->remote_host);
 
835
 
 
836
            if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
 
837
                do_double_reverse(conn);
 
838
                if (conn->double_reverse != 1) {
 
839
                    conn->remote_host = NULL;
 
840
                }
 
841
            }
 
842
        }
 
843
 
 
844
        /* if failed, set it to the NULL string to indicate error */
 
845
        if (conn->remote_host == NULL) {
 
846
            conn->remote_host = "";
 
847
        }
 
848
    }
 
849
 
 
850
    if (type == REMOTE_DOUBLE_REV) {
 
851
        do_double_reverse(conn);
 
852
        if (conn->double_reverse == -1) {
 
853
            return NULL;
 
854
        }
 
855
    }
 
856
 
 
857
    /*
 
858
     * Return the desired information; either the remote DNS name, if found,
 
859
     * or either NULL (if the hostname was requested) or the IP address
 
860
     * (if any identifier was requested).
 
861
     */
 
862
    if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
 
863
        return conn->remote_host;
 
864
    }
 
865
    else {
 
866
        if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
 
867
            return NULL;
 
868
        }
 
869
        else {
 
870
            *str_is_ip = 1;
 
871
            return conn->remote_ip;
 
872
        }
 
873
    }
 
874
}
 
875
 
 
876
/*
 
877
 * Optional function coming from mod_ident, used for looking up ident user
 
878
 */
 
879
static APR_OPTIONAL_FN_TYPE(ap_ident_lookup) *ident_lookup;
 
880
 
 
881
AP_DECLARE(const char *) ap_get_remote_logname(request_rec *r)
 
882
{
 
883
    if (r->connection->remote_logname != NULL) {
 
884
        return r->connection->remote_logname;
 
885
    }
 
886
 
 
887
    if (ident_lookup) {
 
888
        return ident_lookup(r);
 
889
    }
 
890
 
 
891
    return NULL;
 
892
}
 
893
 
 
894
/* There are two options regarding what the "name" of a server is.  The
 
895
 * "canonical" name as defined by ServerName and Port, or the "client's
 
896
 * name" as supplied by a possible Host: header or full URI.
 
897
 *
 
898
 * The DNS option to UseCanonicalName causes this routine to do a
 
899
 * reverse lookup on the local IP address of the connection and use
 
900
 * that for the ServerName. This makes its value more reliable while
 
901
 * at the same time allowing Demon's magic virtual hosting to work.
 
902
 * The assumption is that DNS lookups are sufficiently quick...
 
903
 * -- fanf 1998-10-03
 
904
 */
 
905
AP_DECLARE(const char *) ap_get_server_name(request_rec *r)
 
906
{
 
907
    conn_rec *conn = r->connection;
 
908
    core_dir_config *d;
 
909
    const char *retval;
 
910
 
 
911
    d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
912
                                                &core_module);
 
913
 
 
914
    switch (d->use_canonical_name) {
 
915
        case USE_CANONICAL_NAME_ON:
 
916
            retval = r->server->server_hostname;
 
917
            break;
 
918
        case USE_CANONICAL_NAME_DNS:
 
919
            if (conn->local_host == NULL) {
 
920
                if (apr_getnameinfo(&conn->local_host,
 
921
                                conn->local_addr, 0) != APR_SUCCESS)
 
922
                    conn->local_host = apr_pstrdup(conn->pool,
 
923
                                               r->server->server_hostname);
 
924
                else {
 
925
                    ap_str_tolower(conn->local_host);
 
926
                }
 
927
            }
 
928
            retval = conn->local_host;
 
929
            break;
 
930
        case USE_CANONICAL_NAME_OFF:
 
931
        case USE_CANONICAL_NAME_UNSET:
 
932
            retval = r->hostname ? r->hostname : r->server->server_hostname;
 
933
            break;
 
934
        default:
 
935
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
936
                         "ap_get_server_name: Invalid UCN Option somehow");
 
937
            retval = "localhost";
 
938
            break;
 
939
    }
 
940
    return retval;
 
941
}
 
942
 
 
943
/*
 
944
 * Get the current server name from the request for the purposes
 
945
 * of using in a URL.  If the server name is an IPv6 literal
 
946
 * address, it will be returned in URL format (e.g., "[fe80::1]").
 
947
 */
 
948
static const char *get_server_name_for_url(request_rec *r)
 
949
{
 
950
    const char *plain_server_name = ap_get_server_name(r);
 
951
 
 
952
#if APR_HAVE_IPV6
 
953
    if (ap_strchr_c(plain_server_name, ':')) { /* IPv6 literal? */
 
954
        return apr_psprintf(r->pool, "[%s]", plain_server_name);
 
955
    }
 
956
#endif
 
957
    return plain_server_name;
 
958
}
 
959
 
 
960
AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)
 
961
{
 
962
    apr_port_t port;
 
963
    core_dir_config *d =
 
964
      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
 
965
 
 
966
    switch (d->use_canonical_name) {
 
967
        case USE_CANONICAL_NAME_OFF:
 
968
        case USE_CANONICAL_NAME_DNS:
 
969
        case USE_CANONICAL_NAME_UNSET:
 
970
            if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
 
971
                port = r->parsed_uri.port_str ? r->parsed_uri.port :
 
972
                       r->connection->local_addr->port ? r->connection->local_addr->port :
 
973
                       r->server->port ? r->server->port :
 
974
                       ap_default_port(r);
 
975
            else /* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
 
976
                port = r->parsed_uri.port_str ? r->parsed_uri.port :
 
977
                       r->server->port ? r->server->port :
 
978
                       ap_default_port(r);
 
979
            break;
 
980
        case USE_CANONICAL_NAME_ON:
 
981
            /* With UseCanonicalName on (and in all versions prior to 1.3)
 
982
             * Apache will use the hostname and port specified in the
 
983
             * ServerName directive to construct a canonical name for the
 
984
             * server. (If no port was specified in the ServerName
 
985
             * directive, Apache uses the port supplied by the client if
 
986
             * any is supplied, and finally the default port for the protocol
 
987
             * used.
 
988
             */
 
989
            if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
 
990
                port = r->server->port ? r->server->port :
 
991
                       r->connection->local_addr->port ? r->connection->local_addr->port :
 
992
                       ap_default_port(r);
 
993
            else /* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
 
994
                port = r->server->port ? r->server->port :
 
995
                       ap_default_port(r);
 
996
            break;
 
997
        default:
 
998
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
999
                         "ap_get_server_port: Invalid UCN Option somehow");
 
1000
            port = ap_default_port(r);
 
1001
            break;
 
1002
    }
 
1003
 
 
1004
    return port;
 
1005
}
 
1006
 
 
1007
AP_DECLARE(char *) ap_construct_url(apr_pool_t *p, const char *uri,
 
1008
                                    request_rec *r)
 
1009
{
 
1010
    unsigned port = ap_get_server_port(r);
 
1011
    const char *host = get_server_name_for_url(r);
 
1012
 
 
1013
    if (ap_is_default_port(port, r)) {
 
1014
        return apr_pstrcat(p, ap_http_scheme(r), "://", host, uri, NULL);
 
1015
    }
 
1016
 
 
1017
    return apr_psprintf(p, "%s://%s:%u%s", ap_http_scheme(r), host, port, uri);
 
1018
}
 
1019
 
 
1020
AP_DECLARE(apr_off_t) ap_get_limit_req_body(const request_rec *r)
 
1021
{
 
1022
    core_dir_config *d =
 
1023
      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
 
1024
 
 
1025
    if (d->limit_req_body == AP_LIMIT_REQ_BODY_UNSET) {
 
1026
        return AP_DEFAULT_LIMIT_REQ_BODY;
 
1027
    }
 
1028
 
 
1029
    return d->limit_req_body;
 
1030
}
 
1031
 
 
1032
 
 
1033
/*****************************************************************
 
1034
 *
 
1035
 * Commands... this module handles almost all of the NCSA httpd.conf
 
1036
 * commands, but most of the old srm.conf is in the the modules.
 
1037
 */
 
1038
 
 
1039
 
 
1040
/* returns a parent if it matches the given directive */
 
1041
static const ap_directive_t * find_parent(const ap_directive_t *dirp,
 
1042
                                          const char *what)
 
1043
{
 
1044
    while (dirp->parent != NULL) {
 
1045
        dirp = dirp->parent;
 
1046
 
 
1047
        /* ### it would be nice to have atom-ized directives */
 
1048
        if (strcasecmp(dirp->directive, what) == 0)
 
1049
            return dirp;
 
1050
    }
 
1051
 
 
1052
    return NULL;
 
1053
}
 
1054
 
 
1055
AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd,
 
1056
                                              unsigned forbidden)
 
1057
{
 
1058
    const char *gt = (cmd->cmd->name[0] == '<'
 
1059
                      && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
 
1060
                         ? ">" : "";
 
1061
    const ap_directive_t *found;
 
1062
 
 
1063
    if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
 
1064
        return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
 
1065
                           " cannot occur within <VirtualHost> section", NULL);
 
1066
    }
 
1067
 
 
1068
    if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
 
1069
        return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
 
1070
                           " cannot occur within <Limit> section", NULL);
 
1071
    }
 
1072
 
 
1073
    if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE) {
 
1074
        if (cmd->path != NULL) {
 
1075
            return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
 
1076
                            " cannot occur within <Directory/Location/Files> "
 
1077
                            "section", NULL);
 
1078
        }
 
1079
        if (cmd->cmd->req_override & EXEC_ON_READ) {
 
1080
            /* EXEC_ON_READ must be NOT_IN_DIR_LOC_FILE, if not, it will
 
1081
             * (deliberately) segfault below in the individual tests...
 
1082
             */
 
1083
            return NULL;
 
1084
        }
 
1085
    }
 
1086
 
 
1087
    if (((forbidden & NOT_IN_DIRECTORY)
 
1088
         && ((found = find_parent(cmd->directive, "<Directory"))
 
1089
             || (found = find_parent(cmd->directive, "<DirectoryMatch"))))
 
1090
        || ((forbidden & NOT_IN_LOCATION)
 
1091
            && ((found = find_parent(cmd->directive, "<Location"))
 
1092
                || (found = find_parent(cmd->directive, "<LocationMatch"))))
 
1093
        || ((forbidden & NOT_IN_FILES)
 
1094
            && ((found = find_parent(cmd->directive, "<Files"))
 
1095
                || (found = find_parent(cmd->directive, "<FilesMatch"))))) {
 
1096
        return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
 
1097
                           " cannot occur within ", found->directive,
 
1098
                           "> section", NULL);
 
1099
    }
 
1100
 
 
1101
    return NULL;
 
1102
}
 
1103
 
 
1104
static const char *set_access_name(cmd_parms *cmd, void *dummy,
 
1105
                                   const char *arg)
 
1106
{
 
1107
    void *sconf = cmd->server->module_config;
 
1108
    core_server_config *conf = ap_get_module_config(sconf, &core_module);
 
1109
 
 
1110
    const char *err = ap_check_cmd_context(cmd,
 
1111
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
1112
    if (err != NULL) {
 
1113
        return err;
 
1114
    }
 
1115
 
 
1116
    conf->access_name = apr_pstrdup(cmd->pool, arg);
 
1117
    return NULL;
 
1118
}
 
1119
 
 
1120
#ifdef GPROF
 
1121
static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, const char *arg)
 
1122
{
 
1123
    void *sconf = cmd->server->module_config;
 
1124
    core_server_config *conf = ap_get_module_config(sconf, &core_module);
 
1125
 
 
1126
    const char *err = ap_check_cmd_context(cmd,
 
1127
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
1128
    if (err != NULL) {
 
1129
        return err;
 
1130
    }
 
1131
 
 
1132
    conf->gprof_dir = apr_pstrdup(cmd->pool, arg);
 
1133
    return NULL;
 
1134
}
 
1135
#endif /*GPROF*/
 
1136
 
 
1137
static const char *set_add_default_charset(cmd_parms *cmd,
 
1138
                                           void *d_, const char *arg)
 
1139
{
 
1140
    core_dir_config *d = d_;
 
1141
 
 
1142
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1143
    if (err != NULL) {
 
1144
        return err;
 
1145
    }
 
1146
 
 
1147
    if (!strcasecmp(arg, "Off")) {
 
1148
       d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
 
1149
    }
 
1150
    else if (!strcasecmp(arg, "On")) {
 
1151
       d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
 
1152
       d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
 
1153
    }
 
1154
    else {
 
1155
       d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
 
1156
       d->add_default_charset_name = arg;
 
1157
    }
 
1158
 
 
1159
    return NULL;
 
1160
}
 
1161
 
 
1162
static const char *set_document_root(cmd_parms *cmd, void *dummy,
 
1163
                                     const char *arg)
 
1164
{
 
1165
    void *sconf = cmd->server->module_config;
 
1166
    core_server_config *conf = ap_get_module_config(sconf, &core_module);
 
1167
 
 
1168
    const char *err = ap_check_cmd_context(cmd,
 
1169
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
1170
    if (err != NULL) {
 
1171
        return err;
 
1172
    }
 
1173
 
 
1174
    /* Make it absolute, relative to ServerRoot */
 
1175
    arg = ap_server_root_relative(cmd->pool, arg);
 
1176
 
 
1177
    /* TODO: ap_configtestonly && ap_docrootcheck && */
 
1178
    if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
 
1179
                           APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS
 
1180
        || !ap_is_directory(cmd->pool, arg)) {
 
1181
        if (cmd->server->is_virtual) {
 
1182
            ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0,
 
1183
                          cmd->pool,
 
1184
                          "Warning: DocumentRoot [%s] does not exist",
 
1185
                          arg);
 
1186
            conf->ap_document_root = arg;
 
1187
        }
 
1188
        else {
 
1189
            return "DocumentRoot must be a directory";
 
1190
        }
 
1191
    }
 
1192
    return NULL;
 
1193
}
 
1194
 
 
1195
AP_DECLARE(void) ap_custom_response(request_rec *r, int status,
 
1196
                                    const char *string)
 
1197
{
 
1198
    core_request_config *conf =
 
1199
        ap_get_module_config(r->request_config, &core_module);
 
1200
    int idx;
 
1201
 
 
1202
    if (conf->response_code_strings == NULL) {
 
1203
        conf->response_code_strings =
 
1204
            apr_pcalloc(r->pool,
 
1205
                        sizeof(*conf->response_code_strings) * RESPONSE_CODES);
 
1206
    }
 
1207
 
 
1208
    idx = ap_index_of_response(status);
 
1209
 
 
1210
    conf->response_code_strings[idx] =
 
1211
       ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ?
 
1212
       apr_pstrdup(r->pool, string) : apr_pstrcat(r->pool, "\"", string, NULL);
 
1213
}
 
1214
 
 
1215
static const char *set_error_document(cmd_parms *cmd, void *conf_,
 
1216
                                      const char *errno_str, const char *msg)
 
1217
{
 
1218
    core_dir_config *conf = conf_;
 
1219
    int error_number, index_number, idx500;
 
1220
    enum { MSG, LOCAL_PATH, REMOTE_PATH } what = MSG;
 
1221
 
 
1222
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1223
    if (err != NULL) {
 
1224
        return err;
 
1225
    }
 
1226
 
 
1227
    /* 1st parameter should be a 3 digit number, which we recognize;
 
1228
     * convert it into an array index
 
1229
     */
 
1230
    error_number = atoi(errno_str);
 
1231
    idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
 
1232
 
 
1233
    if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
 
1234
        index_number = idx500;
 
1235
    }
 
1236
    else if ((index_number = ap_index_of_response(error_number)) == idx500) {
 
1237
        return apr_pstrcat(cmd->pool, "Unsupported HTTP response code ",
 
1238
                           errno_str, NULL);
 
1239
    }
 
1240
 
 
1241
    /* Heuristic to determine second argument. */
 
1242
    if (ap_strchr_c(msg,' '))
 
1243
        what = MSG;
 
1244
    else if (msg[0] == '/')
 
1245
        what = LOCAL_PATH;
 
1246
    else if (ap_is_url(msg))
 
1247
        what = REMOTE_PATH;
 
1248
    else
 
1249
        what = MSG;
 
1250
 
 
1251
    /* The entry should be ignored if it is a full URL for a 401 error */
 
1252
 
 
1253
    if (error_number == 401 && what == REMOTE_PATH) {
 
1254
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server,
 
1255
                     "cannot use a full URL in a 401 ErrorDocument "
 
1256
                     "directive --- ignoring!");
 
1257
    }
 
1258
    else { /* Store it... */
 
1259
        if (conf->response_code_strings == NULL) {
 
1260
            conf->response_code_strings =
 
1261
                apr_pcalloc(cmd->pool,
 
1262
                            sizeof(*conf->response_code_strings) *
 
1263
                            RESPONSE_CODES);
 
1264
        }
 
1265
 
 
1266
        if (strcmp(msg, "default") == 0) {
 
1267
            /* special case: ErrorDocument 404 default restores the
 
1268
             * canned server error response
 
1269
             */
 
1270
            conf->response_code_strings[index_number] = &errordocument_default;
 
1271
        }
 
1272
        else {
 
1273
            /* hack. Prefix a " if it is a msg; as that is what
 
1274
             * http_protocol.c relies on to distinguish between
 
1275
             * a msg and a (local) path.
 
1276
             */
 
1277
            conf->response_code_strings[index_number] = (what == MSG) ?
 
1278
                    apr_pstrcat(cmd->pool, "\"",msg,NULL) :
 
1279
                    apr_pstrdup(cmd->pool, msg);
 
1280
        }
 
1281
    }
 
1282
 
 
1283
    return NULL;
 
1284
}
 
1285
 
 
1286
static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts,
 
1287
                                  const char *l)
 
1288
{
 
1289
    allow_options_t opt;
 
1290
    int first = 1;
 
1291
 
 
1292
    char *w, *p = (char *) l;
 
1293
    char *tok_state;
 
1294
 
 
1295
    while ((w = apr_strtok(p, ",", &tok_state)) != NULL) {
 
1296
 
 
1297
        if (first) {
 
1298
            p = NULL;
 
1299
            *opts = OPT_NONE;
 
1300
            first = 0;
 
1301
        }
 
1302
 
 
1303
        if (!strcasecmp(w, "Indexes")) {
 
1304
            opt = OPT_INDEXES;
 
1305
        }
 
1306
        else if (!strcasecmp(w, "Includes")) {
 
1307
            opt = OPT_INCLUDES;
 
1308
        }
 
1309
        else if (!strcasecmp(w, "IncludesNOEXEC")) {
 
1310
            opt = (OPT_INCLUDES | OPT_INCNOEXEC);
 
1311
        }
 
1312
        else if (!strcasecmp(w, "FollowSymLinks")) {
 
1313
            opt = OPT_SYM_LINKS;
 
1314
        }
 
1315
        else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
 
1316
            opt = OPT_SYM_OWNER;
 
1317
        }
 
1318
        else if (!strcasecmp(w, "ExecCGI")) {
 
1319
            opt = OPT_EXECCGI;
 
1320
        }
 
1321
        else if (!strcasecmp(w, "MultiViews")) {
 
1322
            opt = OPT_MULTI;
 
1323
        }
 
1324
        else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
 
1325
            opt = OPT_MULTI|OPT_EXECCGI;
 
1326
        }
 
1327
        else if (!strcasecmp(w, "None")) {
 
1328
            opt = OPT_NONE;
 
1329
        }
 
1330
        else if (!strcasecmp(w, "All")) {
 
1331
            opt = OPT_ALL;
 
1332
        }
 
1333
        else {
 
1334
            return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
 
1335
        }
 
1336
 
 
1337
        *opts |= opt;
 
1338
    }
 
1339
 
 
1340
    (*opts) &= (~OPT_UNSET);
 
1341
 
 
1342
    return NULL;
 
1343
}
 
1344
 
 
1345
static const char *set_override(cmd_parms *cmd, void *d_, const char *l)
 
1346
{
 
1347
    core_dir_config *d = d_;
 
1348
    char *w;
 
1349
    char *k, *v;
 
1350
 
 
1351
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1352
    if (err != NULL) {
 
1353
        return err;
 
1354
    }
 
1355
 
 
1356
    /* Throw a warning if we're in <Location> or <Files> */
 
1357
    if (ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_FILES)) {
 
1358
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
 
1359
                     "Useless use of AllowOverride in line %d.",
 
1360
                     cmd->directive->line_num);
 
1361
    }
 
1362
 
 
1363
    d->override = OR_NONE;
 
1364
    while (l[0]) {
 
1365
        w = ap_getword_conf(cmd->pool, &l);
 
1366
 
 
1367
        k = w;
 
1368
        v = strchr(k, '=');
 
1369
        if (v) {
 
1370
                *v++ = '\0';
 
1371
        }
 
1372
 
 
1373
        if (!strcasecmp(w, "Limit")) {
 
1374
            d->override |= OR_LIMIT;
 
1375
        }
 
1376
        else if (!strcasecmp(k, "Options")) {
 
1377
            d->override |= OR_OPTIONS;
 
1378
            if (v)
 
1379
                set_allow_opts(cmd, &(d->override_opts), v);
 
1380
            else
 
1381
                d->override_opts = OPT_ALL;
 
1382
        }
 
1383
        else if (!strcasecmp(w, "FileInfo")) {
 
1384
            d->override |= OR_FILEINFO;
 
1385
        }
 
1386
        else if (!strcasecmp(w, "AuthConfig")) {
 
1387
            d->override |= OR_AUTHCFG;
 
1388
        }
 
1389
        else if (!strcasecmp(w, "Indexes")) {
 
1390
            d->override |= OR_INDEXES;
 
1391
        }
 
1392
        else if (!strcasecmp(w, "None")) {
 
1393
            d->override = OR_NONE;
 
1394
        }
 
1395
        else if (!strcasecmp(w, "All")) {
 
1396
            d->override = OR_ALL;
 
1397
        }
 
1398
        else {
 
1399
            return apr_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
 
1400
        }
 
1401
 
 
1402
        d->override &= ~OR_UNSET;
 
1403
    }
 
1404
 
 
1405
    return NULL;
 
1406
}
 
1407
 
 
1408
static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
 
1409
{
 
1410
    core_dir_config *d = d_;
 
1411
    allow_options_t opt;
 
1412
    int first = 1;
 
1413
    char action;
 
1414
 
 
1415
    while (l[0]) {
 
1416
        char *w = ap_getword_conf(cmd->pool, &l);
 
1417
        action = '\0';
 
1418
 
 
1419
        if (*w == '+' || *w == '-') {
 
1420
            action = *(w++);
 
1421
        }
 
1422
        else if (first) {
 
1423
              d->opts = OPT_NONE;
 
1424
            first = 0;
 
1425
        }
 
1426
 
 
1427
        if (!strcasecmp(w, "Indexes")) {
 
1428
            opt = OPT_INDEXES;
 
1429
        }
 
1430
        else if (!strcasecmp(w, "Includes")) {
 
1431
            opt = OPT_INCLUDES;
 
1432
        }
 
1433
        else if (!strcasecmp(w, "IncludesNOEXEC")) {
 
1434
            opt = (OPT_INCLUDES | OPT_INCNOEXEC);
 
1435
        }
 
1436
        else if (!strcasecmp(w, "FollowSymLinks")) {
 
1437
            opt = OPT_SYM_LINKS;
 
1438
        }
 
1439
        else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
 
1440
            opt = OPT_SYM_OWNER;
 
1441
        }
 
1442
        else if (!strcasecmp(w, "ExecCGI")) {
 
1443
            opt = OPT_EXECCGI;
 
1444
        }
 
1445
        else if (!strcasecmp(w, "MultiViews")) {
 
1446
            opt = OPT_MULTI;
 
1447
        }
 
1448
        else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
 
1449
            opt = OPT_MULTI|OPT_EXECCGI;
 
1450
        }
 
1451
        else if (!strcasecmp(w, "None")) {
 
1452
            opt = OPT_NONE;
 
1453
        }
 
1454
        else if (!strcasecmp(w, "All")) {
 
1455
            opt = OPT_ALL;
 
1456
        }
 
1457
        else {
 
1458
            return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
 
1459
        }
 
1460
 
 
1461
        if (!(cmd->override_opts & opt) && opt != OPT_NONE) {
 
1462
            return apr_pstrcat(cmd->pool, "Option ", w, " not allowed here", NULL);
 
1463
        }
 
1464
        else if (action == '-') {
 
1465
            /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
 
1466
            d->opts_remove |= opt;
 
1467
            d->opts_add &= ~opt;
 
1468
            d->opts &= ~opt;
 
1469
        }
 
1470
        else if (action == '+') {
 
1471
            d->opts_add |= opt;
 
1472
            d->opts_remove &= ~opt;
 
1473
            d->opts |= opt;
 
1474
        }
 
1475
        else {
 
1476
            d->opts |= opt;
 
1477
        }
 
1478
    }
 
1479
 
 
1480
    return NULL;
 
1481
}
 
1482
 
 
1483
/*
 
1484
 * Note what data should be used when forming file ETag values.
 
1485
 * It would be nicer to do this as an ITERATE, but then we couldn't
 
1486
 * remember the +/- state properly.
 
1487
 */
 
1488
static const char *set_etag_bits(cmd_parms *cmd, void *mconfig,
 
1489
                                 const char *args_p)
 
1490
{
 
1491
    core_dir_config *cfg;
 
1492
    etag_components_t bit;
 
1493
    char action;
 
1494
    char *token;
 
1495
    const char *args;
 
1496
    int valid;
 
1497
    int first;
 
1498
    int explicit;
 
1499
 
 
1500
    cfg = (core_dir_config *)mconfig;
 
1501
 
 
1502
    args = args_p;
 
1503
    first = 1;
 
1504
    explicit = 0;
 
1505
    while (args[0] != '\0') {
 
1506
        action = '*';
 
1507
        bit = ETAG_UNSET;
 
1508
        valid = 1;
 
1509
        token = ap_getword_conf(cmd->pool, &args);
 
1510
        if ((*token == '+') || (*token == '-')) {
 
1511
            action = *token;
 
1512
            token++;
 
1513
        }
 
1514
        else {
 
1515
            /*
 
1516
             * The occurrence of an absolute setting wipes
 
1517
             * out any previous relative ones.  The first such
 
1518
             * occurrence forgets any inherited ones, too.
 
1519
             */
 
1520
            if (first) {
 
1521
                cfg->etag_bits = ETAG_UNSET;
 
1522
                cfg->etag_add = ETAG_UNSET;
 
1523
                cfg->etag_remove = ETAG_UNSET;
 
1524
                first = 0;
 
1525
            }
 
1526
        }
 
1527
 
 
1528
        if (strcasecmp(token, "None") == 0) {
 
1529
            if (action != '*') {
 
1530
                valid = 0;
 
1531
            }
 
1532
            else {
 
1533
                cfg->etag_bits = bit = ETAG_NONE;
 
1534
                explicit = 1;
 
1535
            }
 
1536
        }
 
1537
        else if (strcasecmp(token, "All") == 0) {
 
1538
            if (action != '*') {
 
1539
                valid = 0;
 
1540
            }
 
1541
            else {
 
1542
                explicit = 1;
 
1543
                cfg->etag_bits = bit = ETAG_ALL;
 
1544
            }
 
1545
        }
 
1546
        else if (strcasecmp(token, "Size") == 0) {
 
1547
            bit = ETAG_SIZE;
 
1548
        }
 
1549
        else if ((strcasecmp(token, "LMTime") == 0)
 
1550
                 || (strcasecmp(token, "MTime") == 0)
 
1551
                 || (strcasecmp(token, "LastModified") == 0)) {
 
1552
            bit = ETAG_MTIME;
 
1553
        }
 
1554
        else if (strcasecmp(token, "INode") == 0) {
 
1555
            bit = ETAG_INODE;
 
1556
        }
 
1557
        else {
 
1558
            return apr_pstrcat(cmd->pool, "Unknown keyword '",
 
1559
                               token, "' for ", cmd->cmd->name,
 
1560
                               " directive", NULL);
 
1561
        }
 
1562
 
 
1563
        if (! valid) {
 
1564
            return apr_pstrcat(cmd->pool, cmd->cmd->name, " keyword '",
 
1565
                               token, "' cannot be used with '+' or '-'",
 
1566
                               NULL);
 
1567
        }
 
1568
 
 
1569
        if (action == '+') {
 
1570
            /*
 
1571
             * Make sure it's in the 'add' list and absent from the
 
1572
             * 'subtract' list.
 
1573
             */
 
1574
            cfg->etag_add |= bit;
 
1575
            cfg->etag_remove &= (~ bit);
 
1576
        }
 
1577
        else if (action == '-') {
 
1578
            cfg->etag_remove |= bit;
 
1579
            cfg->etag_add &= (~ bit);
 
1580
        }
 
1581
        else {
 
1582
            /*
 
1583
             * Non-relative values wipe out any + or - values
 
1584
             * accumulated so far.
 
1585
             */
 
1586
            cfg->etag_bits |= bit;
 
1587
            cfg->etag_add = ETAG_UNSET;
 
1588
            cfg->etag_remove = ETAG_UNSET;
 
1589
            explicit = 1;
 
1590
        }
 
1591
    }
 
1592
 
 
1593
    /*
 
1594
     * Any setting at all will clear the 'None' and 'Unset' bits.
 
1595
     */
 
1596
 
 
1597
    if (cfg->etag_add != ETAG_UNSET) {
 
1598
        cfg->etag_add &= (~ ETAG_UNSET);
 
1599
    }
 
1600
 
 
1601
    if (cfg->etag_remove != ETAG_UNSET) {
 
1602
        cfg->etag_remove &= (~ ETAG_UNSET);
 
1603
    }
 
1604
 
 
1605
    if (explicit) {
 
1606
        cfg->etag_bits &= (~ ETAG_UNSET);
 
1607
 
 
1608
        if ((cfg->etag_bits & ETAG_NONE) != ETAG_NONE) {
 
1609
            cfg->etag_bits &= (~ ETAG_NONE);
 
1610
        }
 
1611
    }
 
1612
 
 
1613
    return NULL;
 
1614
}
 
1615
 
 
1616
static const char *set_enable_mmap(cmd_parms *cmd, void *d_,
 
1617
                                   const char *arg)
 
1618
{
 
1619
    core_dir_config *d = d_;
 
1620
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1621
 
 
1622
    if (err != NULL) {
 
1623
        return err;
 
1624
    }
 
1625
 
 
1626
    if (strcasecmp(arg, "on") == 0) {
 
1627
        d->enable_mmap = ENABLE_MMAP_ON;
 
1628
    }
 
1629
    else if (strcasecmp(arg, "off") == 0) {
 
1630
        d->enable_mmap = ENABLE_MMAP_OFF;
 
1631
    }
 
1632
    else {
 
1633
        return "parameter must be 'on' or 'off'";
 
1634
    }
 
1635
 
 
1636
    return NULL;
 
1637
}
 
1638
 
 
1639
static const char *set_enable_sendfile(cmd_parms *cmd, void *d_,
 
1640
                                   const char *arg)
 
1641
{
 
1642
    core_dir_config *d = d_;
 
1643
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1644
 
 
1645
    if (err != NULL) {
 
1646
        return err;
 
1647
    }
 
1648
 
 
1649
    if (strcasecmp(arg, "on") == 0) {
 
1650
        d->enable_sendfile = ENABLE_SENDFILE_ON;
 
1651
    }
 
1652
    else if (strcasecmp(arg, "off") == 0) {
 
1653
        d->enable_sendfile = ENABLE_SENDFILE_OFF;
 
1654
    }
 
1655
    else {
 
1656
        return "parameter must be 'on' or 'off'";
 
1657
    }
 
1658
 
 
1659
    return NULL;
 
1660
}
 
1661
 
 
1662
static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
 
1663
{
 
1664
    core_dir_config *c = c_;
 
1665
    int satisfy = SATISFY_NOSPEC;
 
1666
    int i;
 
1667
 
 
1668
    if (!strcasecmp(arg, "all")) {
 
1669
        satisfy = SATISFY_ALL;
 
1670
    }
 
1671
    else if (!strcasecmp(arg, "any")) {
 
1672
        satisfy = SATISFY_ANY;
 
1673
    }
 
1674
    else {
 
1675
        return "Satisfy either 'any' or 'all'.";
 
1676
    }
 
1677
 
 
1678
    for (i = 0; i < METHODS; ++i) {
 
1679
        if (cmd->limited & (AP_METHOD_BIT << i)) {
 
1680
            c->satisfy[i] = satisfy;
 
1681
        }
 
1682
    }
 
1683
 
 
1684
    return NULL;
 
1685
}
 
1686
 
 
1687
static const char *require(cmd_parms *cmd, void *c_, const char *arg)
 
1688
{
 
1689
    require_line *r;
 
1690
    core_dir_config *c = c_;
 
1691
 
 
1692
    if (!c->ap_requires) {
 
1693
        c->ap_requires = apr_array_make(cmd->pool, 2, sizeof(require_line));
 
1694
    }
 
1695
 
 
1696
    r = (require_line *)apr_array_push(c->ap_requires);
 
1697
    r->requirement = apr_pstrdup(cmd->pool, arg);
 
1698
    r->method_mask = cmd->limited;
 
1699
 
 
1700
    return NULL;
 
1701
}
 
1702
 
 
1703
/*
 
1704
 * Report a missing-'>' syntax error.
 
1705
 */
 
1706
static char *unclosed_directive(cmd_parms *cmd)
 
1707
{
 
1708
    return apr_pstrcat(cmd->pool, cmd->cmd->name,
 
1709
                       "> directive missing closing '>'", NULL);
 
1710
}
 
1711
 
 
1712
/*
 
1713
 * Report a missing args in '<Foo >' syntax error.
 
1714
 */
 
1715
static char *missing_container_arg(cmd_parms *cmd)
 
1716
{
 
1717
    return apr_pstrcat(cmd->pool, cmd->cmd->name,
 
1718
                       "> directive requires additional arguments", NULL);
 
1719
}
 
1720
 
 
1721
AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd,
 
1722
                                                      void *dummy,
 
1723
                                                      const char *arg)
 
1724
{
 
1725
    const char *endp = ap_strrchr_c(arg, '>');
 
1726
    const char *limited_methods;
 
1727
    void *tog = cmd->cmd->cmd_data;
 
1728
    apr_int64_t limited = 0;
 
1729
    const char *errmsg;
 
1730
 
 
1731
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
1732
    if (err != NULL) {
 
1733
        return err;
 
1734
    }
 
1735
 
 
1736
    if (endp == NULL) {
 
1737
        return unclosed_directive(cmd);
 
1738
    }
 
1739
 
 
1740
    limited_methods = apr_pstrndup(cmd->pool, arg, endp - arg);
 
1741
 
 
1742
    if (!limited_methods[0]) {
 
1743
        return missing_container_arg(cmd);
 
1744
    }
 
1745
 
 
1746
    while (limited_methods[0]) {
 
1747
        char *method = ap_getword_conf(cmd->pool, &limited_methods);
 
1748
        int methnum;
 
1749
 
 
1750
        /* check for builtin or module registered method number */
 
1751
        methnum = ap_method_number_of(method);
 
1752
 
 
1753
        if (methnum == M_TRACE && !tog) {
 
1754
            return "TRACE cannot be controlled by <Limit>, see TraceEnable";
 
1755
        }
 
1756
        else if (methnum == M_INVALID) {
 
1757
            /* method has not been registered yet, but resorce restriction
 
1758
             * is always checked before method handling, so register it.
 
1759
             */
 
1760
            methnum = ap_method_register(cmd->pool, method);
 
1761
        }
 
1762
 
 
1763
        limited |= (AP_METHOD_BIT << methnum);
 
1764
    }
 
1765
 
 
1766
    /* Killing two features with one function,
 
1767
     * if (tog == NULL) <Limit>, else <LimitExcept>
 
1768
     */
 
1769
    cmd->limited = tog ? ~limited : limited;
 
1770
 
 
1771
    errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
 
1772
 
 
1773
    cmd->limited = -1;
 
1774
 
 
1775
    return errmsg;
 
1776
}
 
1777
 
 
1778
/* XXX: Bogus - need to do this differently (at least OS2/Netware suffer
 
1779
 * the same problem!!!
 
1780
 * We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
 
1781
 * people don't get bitten by wrong-cased regex matches
 
1782
 */
 
1783
 
 
1784
#ifdef WIN32
 
1785
#define USE_ICASE AP_REG_ICASE
 
1786
#else
 
1787
#define USE_ICASE 0
 
1788
#endif
 
1789
 
 
1790
static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
 
1791
{
 
1792
    const char *errmsg;
 
1793
    const char *endp = ap_strrchr_c(arg, '>');
 
1794
    int old_overrides = cmd->override;
 
1795
    char *old_path = cmd->path;
 
1796
    core_dir_config *conf;
 
1797
    ap_conf_vector_t *new_dir_conf = ap_create_per_dir_config(cmd->pool);
 
1798
    ap_regex_t *r = NULL;
 
1799
    const command_rec *thiscmd = cmd->cmd;
 
1800
 
 
1801
    const char *err = ap_check_cmd_context(cmd,
 
1802
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
1803
    if (err != NULL) {
 
1804
        return err;
 
1805
    }
 
1806
 
 
1807
    if (endp == NULL) {
 
1808
        return unclosed_directive(cmd);
 
1809
    }
 
1810
 
 
1811
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
1812
 
 
1813
    if (!arg[0]) {
 
1814
        return missing_container_arg(cmd);
 
1815
    }
 
1816
 
 
1817
    if (!arg) {
 
1818
        if (thiscmd->cmd_data)
 
1819
            return "<DirectoryMatch > block must specify a path";
 
1820
        else
 
1821
            return "<Directory > block must specify a path";
 
1822
    }
 
1823
 
 
1824
    cmd->path = ap_getword_conf(cmd->pool, &arg);
 
1825
    cmd->override = OR_ALL|ACCESS_CONF;
 
1826
 
 
1827
    if (!strcmp(cmd->path, "~")) {
 
1828
        cmd->path = ap_getword_conf(cmd->pool, &arg);
 
1829
        if (!cmd->path)
 
1830
            return "<Directory ~ > block must specify a path";
 
1831
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
 
1832
        if (!r) {
 
1833
            return "Regex could not be compiled";
 
1834
        }
 
1835
    }
 
1836
    else if (thiscmd->cmd_data) { /* <DirectoryMatch> */
 
1837
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
 
1838
        if (!r) {
 
1839
            return "Regex could not be compiled";
 
1840
        }
 
1841
    }
 
1842
    else if (!strcmp(cmd->path, "/") == 0)
 
1843
    {
 
1844
        char *newpath;
 
1845
 
 
1846
        /*
 
1847
         * Ensure that the pathname is canonical, and append the trailing /
 
1848
         */
 
1849
        apr_status_t rv = apr_filepath_merge(&newpath, NULL, cmd->path,
 
1850
                                             APR_FILEPATH_TRUENAME, cmd->pool);
 
1851
        if (rv != APR_SUCCESS && rv != APR_EPATHWILD) {
 
1852
            return apr_pstrcat(cmd->pool, "<Directory \"", cmd->path,
 
1853
                               "\"> path is invalid.", NULL);
 
1854
        }
 
1855
 
 
1856
        cmd->path = newpath;
 
1857
        if (cmd->path[strlen(cmd->path) - 1] != '/')
 
1858
            cmd->path = apr_pstrcat(cmd->pool, cmd->path, "/", NULL);
 
1859
    }
 
1860
 
 
1861
    /* initialize our config and fetch it */
 
1862
    conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,
 
1863
                                 &core_module, cmd->pool);
 
1864
 
 
1865
    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);
 
1866
    if (errmsg != NULL)
 
1867
        return errmsg;
 
1868
 
 
1869
    conf->r = r;
 
1870
    conf->d = cmd->path;
 
1871
    conf->d_is_fnmatch = (apr_fnmatch_test(conf->d) != 0);
 
1872
 
 
1873
    /* Make this explicit - the "/" root has 0 elements, that is, we
 
1874
     * will always merge it, and it will always sort and merge first.
 
1875
     * All others are sorted and tested by the number of slashes.
 
1876
     */
 
1877
    if (strcmp(conf->d, "/") == 0)
 
1878
        conf->d_components = 0;
 
1879
    else
 
1880
        conf->d_components = ap_count_dirs(conf->d);
 
1881
 
 
1882
    ap_add_per_dir_conf(cmd->server, new_dir_conf);
 
1883
 
 
1884
    if (*arg != '\0') {
 
1885
        return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
 
1886
                           "> arguments not (yet) supported.", NULL);
 
1887
    }
 
1888
 
 
1889
    cmd->path = old_path;
 
1890
    cmd->override = old_overrides;
 
1891
 
 
1892
    return NULL;
 
1893
}
 
1894
 
 
1895
static const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg)
 
1896
{
 
1897
    const char *errmsg;
 
1898
    const char *endp = ap_strrchr_c(arg, '>');
 
1899
    int old_overrides = cmd->override;
 
1900
    char *old_path = cmd->path;
 
1901
    core_dir_config *conf;
 
1902
    ap_regex_t *r = NULL;
 
1903
    const command_rec *thiscmd = cmd->cmd;
 
1904
    ap_conf_vector_t *new_url_conf = ap_create_per_dir_config(cmd->pool);
 
1905
    const char *err = ap_check_cmd_context(cmd,
 
1906
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
1907
    if (err != NULL) {
 
1908
        return err;
 
1909
    }
 
1910
 
 
1911
    if (endp == NULL) {
 
1912
        return unclosed_directive(cmd);
 
1913
    }
 
1914
 
 
1915
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
1916
 
 
1917
    if (!arg[0]) {
 
1918
        return missing_container_arg(cmd);
 
1919
    }
 
1920
 
 
1921
    cmd->path = ap_getword_conf(cmd->pool, &arg);
 
1922
    cmd->override = OR_ALL|ACCESS_CONF;
 
1923
 
 
1924
    if (thiscmd->cmd_data) { /* <LocationMatch> */
 
1925
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);
 
1926
        if (!r) {
 
1927
            return "Regex could not be compiled";
 
1928
        }
 
1929
    }
 
1930
    else if (!strcmp(cmd->path, "~")) {
 
1931
        cmd->path = ap_getword_conf(cmd->pool, &arg);
 
1932
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);
 
1933
        if (!r) {
 
1934
            return "Regex could not be compiled";
 
1935
        }
 
1936
    }
 
1937
 
 
1938
    /* initialize our config and fetch it */
 
1939
    conf = ap_set_config_vectors(cmd->server, new_url_conf, cmd->path,
 
1940
                                 &core_module, cmd->pool);
 
1941
 
 
1942
    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_url_conf);
 
1943
    if (errmsg != NULL)
 
1944
        return errmsg;
 
1945
 
 
1946
    conf->d = apr_pstrdup(cmd->pool, cmd->path);     /* No mangling, please */
 
1947
    conf->d_is_fnmatch = apr_fnmatch_test(conf->d) != 0;
 
1948
    conf->r = r;
 
1949
 
 
1950
    ap_add_per_url_conf(cmd->server, new_url_conf);
 
1951
 
 
1952
    if (*arg != '\0') {
 
1953
        return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
 
1954
                           "> arguments not (yet) supported.", NULL);
 
1955
    }
 
1956
 
 
1957
    cmd->path = old_path;
 
1958
    cmd->override = old_overrides;
 
1959
 
 
1960
    return NULL;
 
1961
}
 
1962
 
 
1963
static const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
 
1964
{
 
1965
    const char *errmsg;
 
1966
    const char *endp = ap_strrchr_c(arg, '>');
 
1967
    int old_overrides = cmd->override;
 
1968
    char *old_path = cmd->path;
 
1969
    core_dir_config *conf;
 
1970
    ap_regex_t *r = NULL;
 
1971
    const command_rec *thiscmd = cmd->cmd;
 
1972
    core_dir_config *c = mconfig;
 
1973
    ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
 
1974
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_LOCATION);
 
1975
 
 
1976
    if (err != NULL) {
 
1977
        return err;
 
1978
    }
 
1979
 
 
1980
    if (endp == NULL) {
 
1981
        return unclosed_directive(cmd);
 
1982
    }
 
1983
 
 
1984
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
1985
 
 
1986
    if (!arg[0]) {
 
1987
        return missing_container_arg(cmd);
 
1988
    }
 
1989
 
 
1990
    cmd->path = ap_getword_conf(cmd->pool, &arg);
 
1991
    /* Only if not an .htaccess file */
 
1992
    if (!old_path) {
 
1993
        cmd->override = OR_ALL|ACCESS_CONF;
 
1994
    }
 
1995
 
 
1996
    if (thiscmd->cmd_data) { /* <FilesMatch> */
 
1997
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
 
1998
        if (!r) {
 
1999
            return "Regex could not be compiled";
 
2000
        }
 
2001
    }
 
2002
    else if (!strcmp(cmd->path, "~")) {
 
2003
        cmd->path = ap_getword_conf(cmd->pool, &arg);
 
2004
        r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED|USE_ICASE);
 
2005
        if (!r) {
 
2006
            return "Regex could not be compiled";
 
2007
        }
 
2008
    }
 
2009
    else {
 
2010
        char *newpath;
 
2011
        /* Ensure that the pathname is canonical, but we
 
2012
         * can't test the case/aliases without a fixed path */
 
2013
        if (apr_filepath_merge(&newpath, "", cmd->path,
 
2014
                               0, cmd->pool) != APR_SUCCESS)
 
2015
                return apr_pstrcat(cmd->pool, "<Files \"", cmd->path,
 
2016
                               "\"> is invalid.", NULL);
 
2017
        cmd->path = newpath;
 
2018
    }
 
2019
 
 
2020
    /* initialize our config and fetch it */
 
2021
    conf = ap_set_config_vectors(cmd->server, new_file_conf, cmd->path,
 
2022
                                 &core_module, cmd->pool);
 
2023
 
 
2024
    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_file_conf);
 
2025
    if (errmsg != NULL)
 
2026
        return errmsg;
 
2027
 
 
2028
    conf->d = cmd->path;
 
2029
    conf->d_is_fnmatch = apr_fnmatch_test(conf->d) != 0;
 
2030
    conf->r = r;
 
2031
 
 
2032
    ap_add_file_conf(c, new_file_conf);
 
2033
 
 
2034
    if (*arg != '\0') {
 
2035
        return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
 
2036
                           "> arguments not (yet) supported.", NULL);
 
2037
    }
 
2038
 
 
2039
    cmd->path = old_path;
 
2040
    cmd->override = old_overrides;
 
2041
 
 
2042
    return NULL;
 
2043
}
 
2044
 
 
2045
static const char *start_ifmod(cmd_parms *cmd, void *mconfig, const char *arg)
 
2046
{
 
2047
    const char *endp = ap_strrchr_c(arg, '>');
 
2048
    int not = (arg[0] == '!');
 
2049
    module *found;
 
2050
 
 
2051
    if (endp == NULL) {
 
2052
        return unclosed_directive(cmd);
 
2053
    }
 
2054
 
 
2055
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
2056
 
 
2057
    if (not) {
 
2058
        arg++;
 
2059
    }
 
2060
 
 
2061
    if (!arg[0]) {
 
2062
        return missing_container_arg(cmd);
 
2063
    }
 
2064
 
 
2065
    found = ap_find_linked_module(arg);
 
2066
 
 
2067
    /* search prelinked stuff */
 
2068
    if (!found) {
 
2069
        ap_module_symbol_t *current = ap_prelinked_module_symbols;
 
2070
 
 
2071
        for (; current->name; ++current) {
 
2072
            if (!strcmp(current->name, arg)) {
 
2073
                found = current->modp;
 
2074
                break;
 
2075
            }
 
2076
        }
 
2077
    }
 
2078
 
 
2079
    /* search dynamic stuff */
 
2080
    if (!found) {
 
2081
        APR_OPTIONAL_FN_TYPE(ap_find_loaded_module_symbol) *check_symbol =
 
2082
            APR_RETRIEVE_OPTIONAL_FN(ap_find_loaded_module_symbol);
 
2083
 
 
2084
        if (check_symbol) {
 
2085
            found = check_symbol(cmd->server, arg);
 
2086
        }
 
2087
    }
 
2088
 
 
2089
    if ((!not && found) || (not && !found)) {
 
2090
        ap_directive_t *parent = NULL;
 
2091
        ap_directive_t *current = NULL;
 
2092
        const char *retval;
 
2093
 
 
2094
        retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
 
2095
                                      &current, &parent, "<IfModule");
 
2096
        *(ap_directive_t **)mconfig = current;
 
2097
        return retval;
 
2098
    }
 
2099
    else {
 
2100
        *(ap_directive_t **)mconfig = NULL;
 
2101
        return ap_soak_end_container(cmd, "<IfModule");
 
2102
    }
 
2103
}
 
2104
 
 
2105
AP_DECLARE(int) ap_exists_config_define(const char *name)
 
2106
{
 
2107
    char **defines;
 
2108
    int i;
 
2109
 
 
2110
    defines = (char **)ap_server_config_defines->elts;
 
2111
    for (i = 0; i < ap_server_config_defines->nelts; i++) {
 
2112
        if (strcmp(defines[i], name) == 0) {
 
2113
            return 1;
 
2114
        }
 
2115
    }
 
2116
 
 
2117
    return 0;
 
2118
}
 
2119
 
 
2120
static const char *start_ifdefine(cmd_parms *cmd, void *dummy, const char *arg)
 
2121
{
 
2122
    const char *endp;
 
2123
    int defined;
 
2124
    int not = 0;
 
2125
 
 
2126
    endp = ap_strrchr_c(arg, '>');
 
2127
    if (endp == NULL) {
 
2128
        return unclosed_directive(cmd);
 
2129
    }
 
2130
 
 
2131
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
2132
 
 
2133
    if (arg[0] == '!') {
 
2134
        not = 1;
 
2135
        arg++;
 
2136
    }
 
2137
 
 
2138
    if (!arg[0]) {
 
2139
        return missing_container_arg(cmd);
 
2140
    }
 
2141
 
 
2142
    defined = ap_exists_config_define(arg);
 
2143
    if ((!not && defined) || (not && !defined)) {
 
2144
        ap_directive_t *parent = NULL;
 
2145
        ap_directive_t *current = NULL;
 
2146
        const char *retval;
 
2147
 
 
2148
        retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
 
2149
                                      &current, &parent, "<IfDefine");
 
2150
        *(ap_directive_t **)dummy = current;
 
2151
        return retval;
 
2152
    }
 
2153
    else {
 
2154
        *(ap_directive_t **)dummy = NULL;
 
2155
        return ap_soak_end_container(cmd, "<IfDefine");
 
2156
    }
 
2157
}
 
2158
 
 
2159
/* httpd.conf commands... beginning with the <VirtualHost> business */
 
2160
 
 
2161
static const char *virtualhost_section(cmd_parms *cmd, void *dummy,
 
2162
                                       const char *arg)
 
2163
{
 
2164
    server_rec *main_server = cmd->server, *s;
 
2165
    const char *errmsg;
 
2166
    const char *endp = ap_strrchr_c(arg, '>');
 
2167
    apr_pool_t *p = cmd->pool;
 
2168
 
 
2169
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2170
    if (err != NULL) {
 
2171
        return err;
 
2172
    }
 
2173
 
 
2174
    if (endp == NULL) {
 
2175
        return unclosed_directive(cmd);
 
2176
    }
 
2177
 
 
2178
    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
 
2179
 
 
2180
    if (!arg[0]) {
 
2181
        return missing_container_arg(cmd);
 
2182
    }
 
2183
 
 
2184
    /* FIXME: There's another feature waiting to happen here -- since you
 
2185
        can now put multiple addresses/names on a single <VirtualHost>
 
2186
        you might want to use it to group common definitions and then
 
2187
        define other "subhosts" with their individual differences.  But
 
2188
        personally I'd rather just do it with a macro preprocessor. -djg */
 
2189
    if (main_server->is_virtual) {
 
2190
        return "<VirtualHost> doesn't nest!";
 
2191
    }
 
2192
 
 
2193
    errmsg = ap_init_virtual_host(p, arg, main_server, &s);
 
2194
    if (errmsg) {
 
2195
        return errmsg;
 
2196
    }
 
2197
 
 
2198
    s->next = main_server->next;
 
2199
    main_server->next = s;
 
2200
 
 
2201
    s->defn_name = cmd->directive->filename;
 
2202
    s->defn_line_number = cmd->directive->line_num;
 
2203
 
 
2204
    cmd->server = s;
 
2205
 
 
2206
    errmsg = ap_walk_config(cmd->directive->first_child, cmd,
 
2207
                            s->lookup_defaults);
 
2208
 
 
2209
    cmd->server = main_server;
 
2210
 
 
2211
    return errmsg;
 
2212
}
 
2213
 
 
2214
static const char *set_server_alias(cmd_parms *cmd, void *dummy,
 
2215
                                    const char *arg)
 
2216
{
 
2217
    if (!cmd->server->names) {
 
2218
        return "ServerAlias only used in <VirtualHost>";
 
2219
    }
 
2220
 
 
2221
    while (*arg) {
 
2222
        char **item, *name = ap_getword_conf(cmd->pool, &arg);
 
2223
 
 
2224
        if (ap_is_matchexp(name)) {
 
2225
            item = (char **)apr_array_push(cmd->server->wild_names);
 
2226
        }
 
2227
        else {
 
2228
            item = (char **)apr_array_push(cmd->server->names);
 
2229
        }
 
2230
 
 
2231
        *item = name;
 
2232
    }
 
2233
 
 
2234
    return NULL;
 
2235
}
 
2236
 
 
2237
static const char *set_accf_map(cmd_parms *cmd, void *dummy,
 
2238
                                const char *iproto, const char* iaccf)
 
2239
{
 
2240
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2241
    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
 
2242
                                                    &core_module);
 
2243
    char* proto;
 
2244
    char* accf;
 
2245
    if (err != NULL) {
 
2246
        return err;
 
2247
    }
 
2248
 
 
2249
    proto = apr_pstrdup(cmd->pool, iproto);
 
2250
    ap_str_tolower(proto);
 
2251
    accf = apr_pstrdup(cmd->pool, iaccf);
 
2252
    ap_str_tolower(accf);
 
2253
    apr_table_set(conf->accf_map, proto, accf);
 
2254
 
 
2255
    return NULL;
 
2256
}
 
2257
 
 
2258
AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s)
 
2259
{
 
2260
    core_server_config *conf = ap_get_module_config(s->module_config,
 
2261
                                                    &core_module);
 
2262
    return conf->protocol;
 
2263
}
 
2264
 
 
2265
AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto)
 
2266
{
 
2267
    core_server_config *conf = ap_get_module_config(s->module_config,
 
2268
                                                    &core_module);
 
2269
    conf->protocol = proto;
 
2270
}
 
2271
 
 
2272
static const char *set_protocol(cmd_parms *cmd, void *dummy,
 
2273
                                const char *arg)
 
2274
{
 
2275
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2276
    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
 
2277
                                                    &core_module);
 
2278
    char* proto;
 
2279
 
 
2280
    if (err != NULL) {
 
2281
        return err;
 
2282
    }
 
2283
 
 
2284
    proto = apr_pstrdup(cmd->pool, arg);
 
2285
    ap_str_tolower(proto);
 
2286
    conf->protocol = proto;
 
2287
 
 
2288
    return NULL;
 
2289
}
 
2290
 
 
2291
static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
 
2292
                                          const char *arg)
 
2293
{
 
2294
    /* This one's pretty generic... */
 
2295
 
 
2296
    int offset = (int)(long)cmd->info;
 
2297
    char *struct_ptr = (char *)cmd->server;
 
2298
 
 
2299
    const char *err = ap_check_cmd_context(cmd,
 
2300
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2301
    if (err != NULL) {
 
2302
        return err;
 
2303
    }
 
2304
 
 
2305
    *(const char **)(struct_ptr + offset) = arg;
 
2306
    return NULL;
 
2307
}
 
2308
 
 
2309
/*
 
2310
 * The ServerName directive takes one argument with format
 
2311
 * [scheme://]fully-qualified-domain-name[:port], for instance
 
2312
 * ServerName www.example.com
 
2313
 * ServerName www.example.com:80
 
2314
 * ServerName https://www.example.com:443
 
2315
 */
 
2316
 
 
2317
static const char *server_hostname_port(cmd_parms *cmd, void *dummy, const char *arg)
 
2318
{
 
2319
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2320
    const char *portstr, *part;
 
2321
    char *scheme;
 
2322
    int port;
 
2323
 
 
2324
    if (err != NULL) {
 
2325
        return err;
 
2326
    }
 
2327
 
 
2328
    part = ap_strstr_c(arg, "://");
 
2329
 
 
2330
    if (part) {
 
2331
      scheme = apr_pstrmemdup(cmd->pool, arg, part - arg);
 
2332
      ap_str_tolower(scheme);
 
2333
      cmd->server->server_scheme = scheme;
 
2334
      part += 3;
 
2335
    } else {
 
2336
      part = arg;
 
2337
    }
 
2338
 
 
2339
    portstr = ap_strchr_c(part, ':');
 
2340
    if (portstr) {
 
2341
        cmd->server->server_hostname = apr_pstrmemdup(cmd->pool, part,
 
2342
                                                      portstr - part);
 
2343
        portstr++;
 
2344
        port = atoi(portstr);
 
2345
        if (port <= 0 || port >= 65536) { /* 65536 == 1<<16 */
 
2346
            return apr_pstrcat(cmd->temp_pool, "The port number \"", arg,
 
2347
                          "\" is outside the appropriate range "
 
2348
                          "(i.e., 1..65535).", NULL);
 
2349
        }
 
2350
    }
 
2351
    else {
 
2352
        cmd->server->server_hostname = apr_pstrdup(cmd->pool, part);
 
2353
        port = 0;
 
2354
    }
 
2355
 
 
2356
    cmd->server->port = port;
 
2357
    return NULL;
 
2358
}
 
2359
 
 
2360
static const char *set_signature_flag(cmd_parms *cmd, void *d_,
 
2361
                                      const char *arg)
 
2362
{
 
2363
    core_dir_config *d = d_;
 
2364
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2365
 
 
2366
    if (err != NULL) {
 
2367
        return err;
 
2368
    }
 
2369
 
 
2370
    if (strcasecmp(arg, "On") == 0) {
 
2371
        d->server_signature = srv_sig_on;
 
2372
    }
 
2373
    else if (strcasecmp(arg, "Off") == 0) {
 
2374
        d->server_signature = srv_sig_off;
 
2375
    }
 
2376
    else if (strcasecmp(arg, "EMail") == 0) {
 
2377
        d->server_signature = srv_sig_withmail;
 
2378
    }
 
2379
    else {
 
2380
        return "ServerSignature: use one of: off | on | email";
 
2381
    }
 
2382
 
 
2383
    return NULL;
 
2384
}
 
2385
 
 
2386
static const char *set_server_root(cmd_parms *cmd, void *dummy,
 
2387
                                   const char *arg)
 
2388
{
 
2389
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2390
 
 
2391
    if (err != NULL) {
 
2392
        return err;
 
2393
    }
 
2394
 
 
2395
    if ((apr_filepath_merge((char**)&ap_server_root, NULL, arg,
 
2396
                            APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS)
 
2397
        || !ap_is_directory(cmd->pool, ap_server_root)) {
 
2398
        return "ServerRoot must be a valid directory";
 
2399
    }
 
2400
 
 
2401
    return NULL;
 
2402
}
 
2403
 
 
2404
static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg)
 
2405
{
 
2406
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2407
 
 
2408
    if (err != NULL) {
 
2409
        return err;
 
2410
    }
 
2411
 
 
2412
    cmd->server->timeout = apr_time_from_sec(atoi(arg));
 
2413
    return NULL;
 
2414
}
 
2415
 
 
2416
static const char *set_allow2f(cmd_parms *cmd, void *d_, int arg)
 
2417
{
 
2418
    core_dir_config *d = d_;
 
2419
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2420
 
 
2421
    if (err != NULL) {
 
2422
        return err;
 
2423
    }
 
2424
 
 
2425
    d->allow_encoded_slashes = arg != 0;
 
2426
    return NULL;
 
2427
}
 
2428
 
 
2429
static const char *set_hostname_lookups(cmd_parms *cmd, void *d_,
 
2430
                                        const char *arg)
 
2431
{
 
2432
    core_dir_config *d = d_;
 
2433
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2434
 
 
2435
    if (err != NULL) {
 
2436
        return err;
 
2437
    }
 
2438
 
 
2439
    if (!strcasecmp(arg, "on")) {
 
2440
        d->hostname_lookups = HOSTNAME_LOOKUP_ON;
 
2441
    }
 
2442
    else if (!strcasecmp(arg, "off")) {
 
2443
        d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
 
2444
    }
 
2445
    else if (!strcasecmp(arg, "double")) {
 
2446
        d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
 
2447
    }
 
2448
    else {
 
2449
        return "parameter must be 'on', 'off', or 'double'";
 
2450
    }
 
2451
 
 
2452
    return NULL;
 
2453
}
 
2454
 
 
2455
static const char *set_serverpath(cmd_parms *cmd, void *dummy,
 
2456
                                  const char *arg)
 
2457
{
 
2458
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2459
 
 
2460
    if (err != NULL) {
 
2461
        return err;
 
2462
    }
 
2463
 
 
2464
    cmd->server->path = arg;
 
2465
    cmd->server->pathlen = (int)strlen(arg);
 
2466
    return NULL;
 
2467
}
 
2468
 
 
2469
static const char *set_content_md5(cmd_parms *cmd, void *d_, int arg)
 
2470
{
 
2471
    core_dir_config *d = d_;
 
2472
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2473
 
 
2474
    if (err != NULL) {
 
2475
        return err;
 
2476
    }
 
2477
 
 
2478
    d->content_md5 = arg != 0;
 
2479
    return NULL;
 
2480
}
 
2481
 
 
2482
static const char *set_accept_path_info(cmd_parms *cmd, void *d_, const char *arg)
 
2483
{
 
2484
    core_dir_config *d = d_;
 
2485
 
 
2486
    if (strcasecmp(arg, "on") == 0) {
 
2487
        d->accept_path_info = AP_REQ_ACCEPT_PATH_INFO;
 
2488
    }
 
2489
    else if (strcasecmp(arg, "off") == 0) {
 
2490
        d->accept_path_info = AP_REQ_REJECT_PATH_INFO;
 
2491
    }
 
2492
    else if (strcasecmp(arg, "default") == 0) {
 
2493
        d->accept_path_info = AP_REQ_DEFAULT_PATH_INFO;
 
2494
    }
 
2495
    else {
 
2496
        return "AcceptPathInfo must be set to on, off or default";
 
2497
    }
 
2498
 
 
2499
    return NULL;
 
2500
}
 
2501
 
 
2502
static const char *set_use_canonical_name(cmd_parms *cmd, void *d_,
 
2503
                                          const char *arg)
 
2504
{
 
2505
    core_dir_config *d = d_;
 
2506
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2507
 
 
2508
    if (err != NULL) {
 
2509
        return err;
 
2510
    }
 
2511
 
 
2512
    if (strcasecmp(arg, "on") == 0) {
 
2513
        d->use_canonical_name = USE_CANONICAL_NAME_ON;
 
2514
    }
 
2515
    else if (strcasecmp(arg, "off") == 0) {
 
2516
        d->use_canonical_name = USE_CANONICAL_NAME_OFF;
 
2517
    }
 
2518
    else if (strcasecmp(arg, "dns") == 0) {
 
2519
        d->use_canonical_name = USE_CANONICAL_NAME_DNS;
 
2520
    }
 
2521
    else {
 
2522
        return "parameter must be 'on', 'off', or 'dns'";
 
2523
    }
 
2524
 
 
2525
    return NULL;
 
2526
}
 
2527
 
 
2528
static const char *set_use_canonical_phys_port(cmd_parms *cmd, void *d_,
 
2529
                                          const char *arg)
 
2530
{
 
2531
    core_dir_config *d = d_;
 
2532
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2533
 
 
2534
    if (err != NULL) {
 
2535
        return err;
 
2536
    }
 
2537
 
 
2538
    if (strcasecmp(arg, "on") == 0) {
 
2539
        d->use_canonical_phys_port = USE_CANONICAL_PHYS_PORT_ON;
 
2540
    }
 
2541
    else if (strcasecmp(arg, "off") == 0) {
 
2542
        d->use_canonical_phys_port = USE_CANONICAL_PHYS_PORT_OFF;
 
2543
    }
 
2544
    else {
 
2545
        return "parameter must be 'on' or 'off'";
 
2546
    }
 
2547
 
 
2548
    return NULL;
 
2549
}
 
2550
 
 
2551
 
 
2552
static const char *include_config (cmd_parms *cmd, void *dummy,
 
2553
                                   const char *name)
 
2554
{
 
2555
    ap_directive_t *conftree = NULL;
 
2556
    const char* conffile, *error;
 
2557
    unsigned *recursion;
 
2558
    void *data;
 
2559
 
 
2560
    apr_pool_userdata_get(&data, "ap_include_sentinel", cmd->pool);
 
2561
    if (data) {
 
2562
        recursion = data;
 
2563
    }
 
2564
    else {
 
2565
        data = recursion = apr_palloc(cmd->pool, sizeof(*recursion));
 
2566
        *recursion = 0;
 
2567
        apr_pool_userdata_setn(data, "ap_include_sentinel", NULL, cmd->pool);
 
2568
    }
 
2569
 
 
2570
    if (++*recursion > AP_MAX_INCLUDE_DEPTH) {
 
2571
        *recursion = 0;
 
2572
        return apr_psprintf(cmd->pool, "Exceeded maximum include depth of %u. "
 
2573
                            "You have probably a recursion somewhere.",
 
2574
                            AP_MAX_INCLUDE_DEPTH);
 
2575
    }
 
2576
 
 
2577
    conffile = ap_server_root_relative(cmd->pool, name);
 
2578
    if (!conffile) {
 
2579
        *recursion = 0;
 
2580
        return apr_pstrcat(cmd->pool, "Invalid Include path ",
 
2581
                           name, NULL);
 
2582
    }
 
2583
 
 
2584
    error = ap_process_resource_config(cmd->server, conffile,
 
2585
                                       &conftree, cmd->pool, cmd->temp_pool);
 
2586
    if (error) {
 
2587
        *recursion = 0;
 
2588
        return error;
 
2589
    }
 
2590
 
 
2591
    *(ap_directive_t **)dummy = conftree;
 
2592
 
 
2593
    /* recursion level done */
 
2594
    if (*recursion) {
 
2595
        --*recursion;
 
2596
    }
 
2597
 
 
2598
    return NULL;
 
2599
}
 
2600
 
 
2601
static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg)
 
2602
{
 
2603
    char *str;
 
2604
 
 
2605
    const char *err = ap_check_cmd_context(cmd,
 
2606
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2607
    if (err != NULL) {
 
2608
        return err;
 
2609
    }
 
2610
 
 
2611
    if ((str = ap_getword_conf(cmd->pool, &arg))) {
 
2612
        if (!strcasecmp(str, "emerg")) {
 
2613
            cmd->server->loglevel = APLOG_EMERG;
 
2614
        }
 
2615
        else if (!strcasecmp(str, "alert")) {
 
2616
            cmd->server->loglevel = APLOG_ALERT;
 
2617
        }
 
2618
        else if (!strcasecmp(str, "crit")) {
 
2619
            cmd->server->loglevel = APLOG_CRIT;
 
2620
        }
 
2621
        else if (!strcasecmp(str, "error")) {
 
2622
            cmd->server->loglevel = APLOG_ERR;
 
2623
        }
 
2624
        else if (!strcasecmp(str, "warn")) {
 
2625
            cmd->server->loglevel = APLOG_WARNING;
 
2626
        }
 
2627
        else if (!strcasecmp(str, "notice")) {
 
2628
            cmd->server->loglevel = APLOG_NOTICE;
 
2629
        }
 
2630
        else if (!strcasecmp(str, "info")) {
 
2631
            cmd->server->loglevel = APLOG_INFO;
 
2632
        }
 
2633
        else if (!strcasecmp(str, "debug")) {
 
2634
            cmd->server->loglevel = APLOG_DEBUG;
 
2635
        }
 
2636
        else {
 
2637
            return "LogLevel requires level keyword: one of "
 
2638
                   "emerg/alert/crit/error/warn/notice/info/debug";
 
2639
        }
 
2640
    }
 
2641
    else {
 
2642
        return "LogLevel requires level keyword";
 
2643
    }
 
2644
 
 
2645
    return NULL;
 
2646
}
 
2647
 
 
2648
AP_DECLARE(const char *) ap_psignature(const char *prefix, request_rec *r)
 
2649
{
 
2650
    char sport[20];
 
2651
    core_dir_config *conf;
 
2652
 
 
2653
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
2654
                                                   &core_module);
 
2655
    if ((conf->server_signature == srv_sig_off)
 
2656
            || (conf->server_signature == srv_sig_unset)) {
 
2657
        return "";
 
2658
    }
 
2659
 
 
2660
    apr_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
 
2661
 
 
2662
    if (conf->server_signature == srv_sig_withmail) {
 
2663
        return apr_pstrcat(r->pool, prefix, "<address>",
 
2664
                           ap_get_server_version(),
 
2665
                           " Server at <a href=\"",
 
2666
                           ap_is_url(r->server->server_admin) ? "" : "mailto:",
 
2667
                           ap_escape_html(r->pool, r->server->server_admin),
 
2668
                           "\">",
 
2669
                           ap_escape_html(r->pool, ap_get_server_name(r)),
 
2670
                           "</a> Port ", sport,
 
2671
                           "</address>\n", NULL);
 
2672
    }
 
2673
 
 
2674
    return apr_pstrcat(r->pool, prefix, "<address>", ap_get_server_version(),
 
2675
                       " Server at ",
 
2676
                       ap_escape_html(r->pool, ap_get_server_name(r)),
 
2677
                       " Port ", sport,
 
2678
                       "</address>\n", NULL);
 
2679
}
 
2680
 
 
2681
/*
 
2682
 * Load an authorisation realm into our location configuration, applying the
 
2683
 * usual rules that apply to realms.
 
2684
 */
 
2685
static const char *set_authname(cmd_parms *cmd, void *mconfig,
 
2686
                                const char *word1)
 
2687
{
 
2688
    core_dir_config *aconfig = (core_dir_config *)mconfig;
 
2689
 
 
2690
    aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
 
2691
    return NULL;
 
2692
}
 
2693
 
 
2694
/*
 
2695
 * Handle a request to include the server's OS platform in the Server
 
2696
 * response header field (the ServerTokens directive).  Unfortunately
 
2697
 * this requires a new global in order to communicate the setting back to
 
2698
 * http_main so it can insert the information in the right place in the
 
2699
 * string.
 
2700
 */
 
2701
 
 
2702
static char *server_version = NULL;
 
2703
static int version_locked = 0;
 
2704
 
 
2705
enum server_token_type {
 
2706
    SrvTk_MAJOR,        /* eg: Apache/2 */
 
2707
    SrvTk_MINOR,        /* eg. Apache/2.0 */
 
2708
    SrvTk_MINIMAL,      /* eg: Apache/2.0.41 */
 
2709
    SrvTk_OS,           /* eg: Apache/2.0.41 (UNIX) */
 
2710
    SrvTk_FULL,         /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
 
2711
    SrvTk_PRODUCT_ONLY  /* eg: Apache */
 
2712
};
 
2713
static enum server_token_type ap_server_tokens = SrvTk_FULL;
 
2714
 
 
2715
static apr_status_t reset_version(void *dummy)
 
2716
{
 
2717
    version_locked = 0;
 
2718
    ap_server_tokens = SrvTk_FULL;
 
2719
    server_version = NULL;
 
2720
    return APR_SUCCESS;
 
2721
}
 
2722
 
 
2723
AP_DECLARE(void) ap_get_server_revision(ap_version_t *version)
 
2724
{
 
2725
    version->major = AP_SERVER_MAJORVERSION_NUMBER;
 
2726
    version->minor = AP_SERVER_MINORVERSION_NUMBER;
 
2727
    version->patch = AP_SERVER_PATCHLEVEL_NUMBER;
 
2728
    version->add_string = AP_SERVER_ADD_STRING;
 
2729
}
 
2730
 
 
2731
AP_DECLARE(const char *) ap_get_server_version(void)
 
2732
{
 
2733
    return (server_version ? server_version : AP_SERVER_BASEVERSION);
 
2734
}
 
2735
 
 
2736
AP_DECLARE(void) ap_add_version_component(apr_pool_t *pconf, const char *component)
 
2737
{
 
2738
    if (! version_locked) {
 
2739
        /*
 
2740
         * If the version string is null, register our cleanup to reset the
 
2741
         * pointer on pool destruction. We also know that, if NULL,
 
2742
         * we are adding the original SERVER_BASEVERSION string.
 
2743
         */
 
2744
        if (server_version == NULL) {
 
2745
            apr_pool_cleanup_register(pconf, NULL, reset_version,
 
2746
                                      apr_pool_cleanup_null);
 
2747
            server_version = apr_pstrdup(pconf, component);
 
2748
        }
 
2749
        else {
 
2750
            /*
 
2751
             * Tack the given component identifier to the end of
 
2752
             * the existing string.
 
2753
             */
 
2754
            server_version = apr_pstrcat(pconf, server_version, " ",
 
2755
                                         component, NULL);
 
2756
        }
 
2757
    }
 
2758
}
 
2759
 
 
2760
/*
 
2761
 * This routine adds the real server base identity to the version string,
 
2762
 * and then locks out changes until the next reconfig.
 
2763
 */
 
2764
static void ap_set_version(apr_pool_t *pconf)
 
2765
{
 
2766
    if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
 
2767
        ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
 
2768
    }
 
2769
    else if (ap_server_tokens == SrvTk_MINIMAL) {
 
2770
        ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
 
2771
    }
 
2772
    else if (ap_server_tokens == SrvTk_MINOR) {
 
2773
        ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
 
2774
    }
 
2775
    else if (ap_server_tokens == SrvTk_MAJOR) {
 
2776
        ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
 
2777
    }
 
2778
    else {
 
2779
        ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
 
2780
    }
 
2781
 
 
2782
    /*
 
2783
     * Lock the server_version string if we're not displaying
 
2784
     * the full set of tokens
 
2785
     */
 
2786
    if (ap_server_tokens != SrvTk_FULL) {
 
2787
        version_locked++;
 
2788
    }
 
2789
}
 
2790
 
 
2791
static const char *set_serv_tokens(cmd_parms *cmd, void *dummy,
 
2792
                                   const char *arg)
 
2793
{
 
2794
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2795
 
 
2796
    if (err != NULL) {
 
2797
        return err;
 
2798
    }
 
2799
 
 
2800
    if (!strcasecmp(arg, "OS")) {
 
2801
        ap_server_tokens = SrvTk_OS;
 
2802
    }
 
2803
    else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
 
2804
        ap_server_tokens = SrvTk_MINIMAL;
 
2805
    }
 
2806
    else if (!strcasecmp(arg, "Major")) {
 
2807
        ap_server_tokens = SrvTk_MAJOR;
 
2808
    }
 
2809
    else if (!strcasecmp(arg, "Minor") ) {
 
2810
        ap_server_tokens = SrvTk_MINOR;
 
2811
    }
 
2812
    else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
 
2813
        ap_server_tokens = SrvTk_PRODUCT_ONLY;
 
2814
    }
 
2815
    else {
 
2816
        ap_server_tokens = SrvTk_FULL;
 
2817
    }
 
2818
 
 
2819
    return NULL;
 
2820
}
 
2821
 
 
2822
static const char *set_limit_req_line(cmd_parms *cmd, void *dummy,
 
2823
                                      const char *arg)
 
2824
{
 
2825
    const char *err = ap_check_cmd_context(cmd,
 
2826
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2827
    int lim;
 
2828
 
 
2829
    if (err != NULL) {
 
2830
        return err;
 
2831
    }
 
2832
 
 
2833
    lim = atoi(arg);
 
2834
    if (lim < 0) {
 
2835
        return apr_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg,
 
2836
                           "\" must be a non-negative integer", NULL);
 
2837
    }
 
2838
 
 
2839
    cmd->server->limit_req_line = lim;
 
2840
    return NULL;
 
2841
}
 
2842
 
 
2843
static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
 
2844
                                           const char *arg)
 
2845
{
 
2846
    const char *err = ap_check_cmd_context(cmd,
 
2847
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2848
    int lim;
 
2849
 
 
2850
    if (err != NULL) {
 
2851
        return err;
 
2852
    }
 
2853
 
 
2854
    lim = atoi(arg);
 
2855
    if (lim < 0) {
 
2856
        return apr_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg,
 
2857
                          "\" must be a non-negative integer",
 
2858
                          NULL);
 
2859
    }
 
2860
 
 
2861
    cmd->server->limit_req_fieldsize = lim;
 
2862
    return NULL;
 
2863
}
 
2864
 
 
2865
static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy,
 
2866
                                        const char *arg)
 
2867
{
 
2868
    const char *err = ap_check_cmd_context(cmd,
 
2869
                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
 
2870
    int lim;
 
2871
 
 
2872
    if (err != NULL) {
 
2873
        return err;
 
2874
    }
 
2875
 
 
2876
    lim = atoi(arg);
 
2877
    if (lim < 0) {
 
2878
        return apr_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg,
 
2879
                           "\" must be a non-negative integer (0 = no limit)",
 
2880
                           NULL);
 
2881
    }
 
2882
 
 
2883
    cmd->server->limit_req_fields = lim;
 
2884
    return NULL;
 
2885
}
 
2886
 
 
2887
static const char *set_limit_req_body(cmd_parms *cmd, void *conf_,
 
2888
                                      const char *arg)
 
2889
{
 
2890
    core_dir_config *conf = conf_;
 
2891
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2892
    char *errp;
 
2893
 
 
2894
    if (err != NULL) {
 
2895
        return err;
 
2896
    }
 
2897
 
 
2898
    if (APR_SUCCESS != apr_strtoff(&conf->limit_req_body, arg, &errp, 10)) {
 
2899
        return "LimitRequestBody argument is not parsable.";
 
2900
    }
 
2901
    if (*errp || conf->limit_req_body < 0) {
 
2902
        return "LimitRequestBody requires a non-negative integer.";
 
2903
    }
 
2904
 
 
2905
    return NULL;
 
2906
}
 
2907
 
 
2908
static const char *set_limit_xml_req_body(cmd_parms *cmd, void *conf_,
 
2909
                                          const char *arg)
 
2910
{
 
2911
    core_dir_config *conf = conf_;
 
2912
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
2913
 
 
2914
    if (err != NULL) {
 
2915
        return err;
 
2916
    }
 
2917
 
 
2918
    conf->limit_xml_body = atol(arg);
 
2919
    if (conf->limit_xml_body < 0)
 
2920
        return "LimitXMLRequestBody requires a non-negative integer.";
 
2921
 
 
2922
    return NULL;
 
2923
}
 
2924
 
 
2925
AP_DECLARE(size_t) ap_get_limit_xml_body(const request_rec *r)
 
2926
{
 
2927
    core_dir_config *conf;
 
2928
 
 
2929
    conf = ap_get_module_config(r->per_dir_config, &core_module);
 
2930
    if (conf->limit_xml_body == AP_LIMIT_UNSET)
 
2931
        return AP_DEFAULT_LIMIT_XML_BODY;
 
2932
 
 
2933
    return (size_t)conf->limit_xml_body;
 
2934
}
 
2935
 
 
2936
#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
 
2937
static const char *no_set_limit(cmd_parms *cmd, void *conf_,
 
2938
                                const char *arg, const char *arg2)
 
2939
{
 
2940
    ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
 
2941
                "%s not supported on this platform", cmd->cmd->name);
 
2942
 
 
2943
    return NULL;
 
2944
}
 
2945
#endif
 
2946
 
 
2947
#ifdef RLIMIT_CPU
 
2948
static const char *set_limit_cpu(cmd_parms *cmd, void *conf_,
 
2949
                                 const char *arg, const char *arg2)
 
2950
{
 
2951
    core_dir_config *conf = conf_;
 
2952
 
 
2953
    unixd_set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
 
2954
    return NULL;
 
2955
}
 
2956
#endif
 
2957
 
 
2958
#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
 
2959
static const char *set_limit_mem(cmd_parms *cmd, void *conf_,
 
2960
                                 const char *arg, const char * arg2)
 
2961
{
 
2962
    core_dir_config *conf = conf_;
 
2963
 
 
2964
#if defined(RLIMIT_AS)
 
2965
    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
 
2966
#elif defined(RLIMIT_DATA)
 
2967
    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
 
2968
#elif defined(RLIMIT_VMEM)
 
2969
    unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
 
2970
#endif
 
2971
 
 
2972
    return NULL;
 
2973
}
 
2974
#endif
 
2975
 
 
2976
#ifdef RLIMIT_NPROC
 
2977
static const char *set_limit_nproc(cmd_parms *cmd, void *conf_,
 
2978
                                   const char *arg, const char * arg2)
 
2979
{
 
2980
    core_dir_config *conf = conf_;
 
2981
 
 
2982
    unixd_set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
 
2983
    return NULL;
 
2984
}
 
2985
#endif
 
2986
 
 
2987
static const char *set_recursion_limit(cmd_parms *cmd, void *dummy,
 
2988
                                       const char *arg1, const char *arg2)
 
2989
{
 
2990
    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
 
2991
                                                    &core_module);
 
2992
    int limit = atoi(arg1);
 
2993
 
 
2994
    if (limit <= 0) {
 
2995
        return "The recursion limit must be greater than zero.";
 
2996
    }
 
2997
    if (limit < 4) {
 
2998
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
 
2999
                     "Limiting internal redirects to very low numbers may "
 
3000
                     "cause normal requests to fail.");
 
3001
    }
 
3002
 
 
3003
    conf->redirect_limit = limit;
 
3004
 
 
3005
    if (arg2) {
 
3006
        limit = atoi(arg2);
 
3007
 
 
3008
        if (limit <= 0) {
 
3009
            return "The recursion limit must be greater than zero.";
 
3010
        }
 
3011
        if (limit < 4) {
 
3012
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
 
3013
                         "Limiting the subrequest depth to a very low level may"
 
3014
                         " cause normal requests to fail.");
 
3015
        }
 
3016
    }
 
3017
 
 
3018
    conf->subreq_limit = limit;
 
3019
 
 
3020
    return NULL;
 
3021
}
 
3022
 
 
3023
static void log_backtrace(const request_rec *r)
 
3024
{
 
3025
    const request_rec *top = r;
 
3026
 
 
3027
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
 
3028
                  "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)");
 
3029
 
 
3030
    while (top && (top->prev || top->main)) {
 
3031
        if (top->prev) {
 
3032
            top = top->prev;
 
3033
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
 
3034
                          "redirected from r->uri = %s",
 
3035
                          top->uri ? top->uri : "(unexpectedly NULL)");
 
3036
        }
 
3037
 
 
3038
        if (!top->prev && top->main) {
 
3039
            top = top->main;
 
3040
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
 
3041
                          "subrequested from r->uri = %s",
 
3042
                          top->uri ? top->uri : "(unexpectedly NULL)");
 
3043
        }
 
3044
    }
 
3045
}
 
3046
 
 
3047
/*
 
3048
 * check whether redirect limit is reached
 
3049
 */
 
3050
AP_DECLARE(int) ap_is_recursion_limit_exceeded(const request_rec *r)
 
3051
{
 
3052
    core_server_config *conf = ap_get_module_config(r->server->module_config,
 
3053
                                                    &core_module);
 
3054
    const request_rec *top = r;
 
3055
    int redirects = 0, subreqs = 0;
 
3056
    int rlimit = conf->redirect_limit
 
3057
                 ? conf->redirect_limit
 
3058
                 : AP_DEFAULT_MAX_INTERNAL_REDIRECTS;
 
3059
    int slimit = conf->subreq_limit
 
3060
                 ? conf->subreq_limit
 
3061
                 : AP_DEFAULT_MAX_SUBREQ_DEPTH;
 
3062
 
 
3063
 
 
3064
    while (top->prev || top->main) {
 
3065
        if (top->prev) {
 
3066
            if (++redirects >= rlimit) {
 
3067
                /* uuh, too much. */
 
3068
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3069
                              "Request exceeded the limit of %d internal "
 
3070
                              "redirects due to probable configuration error. "
 
3071
                              "Use 'LimitInternalRecursion' to increase the "
 
3072
                              "limit if necessary. Use 'LogLevel debug' to get "
 
3073
                              "a backtrace.", rlimit);
 
3074
 
 
3075
                /* post backtrace */
 
3076
                log_backtrace(r);
 
3077
 
 
3078
                /* return failure */
 
3079
                return 1;
 
3080
            }
 
3081
 
 
3082
            top = top->prev;
 
3083
        }
 
3084
 
 
3085
        if (!top->prev && top->main) {
 
3086
            if (++subreqs >= slimit) {
 
3087
                /* uuh, too much. */
 
3088
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3089
                              "Request exceeded the limit of %d subrequest "
 
3090
                              "nesting levels due to probable confguration "
 
3091
                              "error. Use 'LimitInternalRecursion' to increase "
 
3092
                              "the limit if necessary. Use 'LogLevel debug' to "
 
3093
                              "get a backtrace.", slimit);
 
3094
 
 
3095
                /* post backtrace */
 
3096
                log_backtrace(r);
 
3097
 
 
3098
                /* return failure */
 
3099
                return 1;
 
3100
            }
 
3101
 
 
3102
            top = top->main;
 
3103
        }
 
3104
    }
 
3105
 
 
3106
    /* recursion state: ok */
 
3107
    return 0;
 
3108
}
 
3109
 
 
3110
static const char *add_ct_output_filters(cmd_parms *cmd, void *conf_,
 
3111
                                         const char *arg, const char *arg2)
 
3112
{
 
3113
    core_dir_config *conf = conf_;
 
3114
    ap_filter_rec_t *old, *new = NULL;
 
3115
    const char *filter_name;
 
3116
 
 
3117
    if (!conf->ct_output_filters) {
 
3118
        conf->ct_output_filters = apr_hash_make(cmd->pool);
 
3119
        old = NULL;
 
3120
    }
 
3121
    else {
 
3122
        old = (ap_filter_rec_t*) apr_hash_get(conf->ct_output_filters, arg2,
 
3123
                                              APR_HASH_KEY_STRING);
 
3124
        /* find last entry */
 
3125
        if (old) {
 
3126
            while (old->next) {
 
3127
                old = old->next;
 
3128
            }
 
3129
        }
 
3130
    }
 
3131
 
 
3132
    while (*arg &&
 
3133
           (filter_name = ap_getword(cmd->pool, &arg, ';')) &&
 
3134
           strcmp(filter_name, "")) {
 
3135
        new = apr_pcalloc(cmd->pool, sizeof(ap_filter_rec_t));
 
3136
        new->name = filter_name;
 
3137
 
 
3138
        /* We found something, so let's append it.  */
 
3139
        if (old) {
 
3140
            old->next = new;
 
3141
        }
 
3142
        else {
 
3143
            apr_hash_set(conf->ct_output_filters, arg2,
 
3144
                         APR_HASH_KEY_STRING, new);
 
3145
        }
 
3146
        old = new;
 
3147
    }
 
3148
 
 
3149
    if (!new) {
 
3150
        return "invalid filter name";
 
3151
    }
 
3152
 
 
3153
    return NULL;
 
3154
}
 
3155
/*
 
3156
 * Insert filters requested by the AddOutputFilterByType
 
3157
 * configuration directive. We cannot add filters based
 
3158
 * on content-type until after the handler has started
 
3159
 * to run. Only then do we reliably know the content-type.
 
3160
 */
 
3161
void ap_add_output_filters_by_type(request_rec *r)
 
3162
{
 
3163
    core_dir_config *conf;
 
3164
    const char *ctype;
 
3165
 
 
3166
    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
3167
                                                   &core_module);
 
3168
 
 
3169
    /* We can't do anything with no content-type or if we don't have a
 
3170
     * filter configured.
 
3171
     */
 
3172
    if (!r->content_type || !conf->ct_output_filters) {
 
3173
        return;
 
3174
    }
 
3175
 
 
3176
    /* remove c-t decoration */
 
3177
    ctype = ap_field_noparam(r->pool, r->content_type);
 
3178
    if (ctype) {
 
3179
        ap_filter_rec_t *ct_filter;
 
3180
        ct_filter = apr_hash_get(conf->ct_output_filters, ctype,
 
3181
                                 APR_HASH_KEY_STRING);
 
3182
        while (ct_filter) {
 
3183
            ap_add_output_filter(ct_filter->name, NULL, r, r->connection);
 
3184
            ct_filter = ct_filter->next;
 
3185
        }
 
3186
    }
 
3187
 
 
3188
    return;
 
3189
}
 
3190
 
 
3191
static const char *set_trace_enable(cmd_parms *cmd, void *dummy,
 
3192
                                    const char *arg1)
 
3193
{
 
3194
    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
 
3195
                                                    &core_module);
 
3196
 
 
3197
    if (strcasecmp(arg1, "on") == 0) {
 
3198
        conf->trace_enable = AP_TRACE_ENABLE;
 
3199
    }
 
3200
    else if (strcasecmp(arg1, "off") == 0) {
 
3201
        conf->trace_enable = AP_TRACE_DISABLE;
 
3202
    }
 
3203
    else if (strcasecmp(arg1, "extended") == 0) {
 
3204
        conf->trace_enable = AP_TRACE_EXTENDED;
 
3205
    }
 
3206
    else {
 
3207
        return "TraceEnable must be one of 'on', 'off', or 'extended'";
 
3208
    }
 
3209
 
 
3210
    return NULL;
 
3211
}
 
3212
 
 
3213
/* Note --- ErrorDocument will now work from .htaccess files.
 
3214
 * The AllowOverride of Fileinfo allows webmasters to turn it off
 
3215
 */
 
3216
 
 
3217
static const command_rec core_cmds[] = {
 
3218
 
 
3219
/* Old access config file commands */
 
3220
 
 
3221
AP_INIT_RAW_ARGS("<Directory", dirsection, NULL, RSRC_CONF,
 
3222
  "Container for directives affecting resources located in the specified "
 
3223
  "directories"),
 
3224
AP_INIT_RAW_ARGS("<Location", urlsection, NULL, RSRC_CONF,
 
3225
  "Container for directives affecting resources accessed through the "
 
3226
  "specified URL paths"),
 
3227
AP_INIT_RAW_ARGS("<VirtualHost", virtualhost_section, NULL, RSRC_CONF,
 
3228
  "Container to map directives to a particular virtual host, takes one or "
 
3229
  "more host addresses"),
 
3230
AP_INIT_RAW_ARGS("<Files", filesection, NULL, OR_ALL,
 
3231
  "Container for directives affecting files matching specified patterns"),
 
3232
AP_INIT_RAW_ARGS("<Limit", ap_limit_section, NULL, OR_ALL,
 
3233
  "Container for authentication directives when accessed using specified HTTP "
 
3234
  "methods"),
 
3235
AP_INIT_RAW_ARGS("<LimitExcept", ap_limit_section, (void*)1, OR_ALL,
 
3236
  "Container for authentication directives to be applied when any HTTP "
 
3237
  "method other than those specified is used to access the resource"),
 
3238
AP_INIT_TAKE1("<IfModule", start_ifmod, NULL, EXEC_ON_READ | OR_ALL,
 
3239
  "Container for directives based on existance of specified modules"),
 
3240
AP_INIT_TAKE1("<IfDefine", start_ifdefine, NULL, EXEC_ON_READ | OR_ALL,
 
3241
  "Container for directives based on existance of command line defines"),
 
3242
AP_INIT_RAW_ARGS("<DirectoryMatch", dirsection, (void*)1, RSRC_CONF,
 
3243
  "Container for directives affecting resources located in the "
 
3244
  "specified directories"),
 
3245
AP_INIT_RAW_ARGS("<LocationMatch", urlsection, (void*)1, RSRC_CONF,
 
3246
  "Container for directives affecting resources accessed through the "
 
3247
  "specified URL paths"),
 
3248
AP_INIT_RAW_ARGS("<FilesMatch", filesection, (void*)1, OR_ALL,
 
3249
  "Container for directives affecting files matching specified patterns"),
 
3250
AP_INIT_TAKE1("AuthType", ap_set_string_slot,
 
3251
  (void*)APR_OFFSETOF(core_dir_config, ap_auth_type), OR_AUTHCFG,
 
3252
  "An HTTP authorization type (e.g., \"Basic\")"),
 
3253
AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG,
 
3254
  "The authentication realm (e.g. \"Members Only\")"),
 
3255
AP_INIT_RAW_ARGS("Require", require, NULL, OR_AUTHCFG,
 
3256
  "Selects which authenticated users or groups may access a protected space"),
 
3257
AP_INIT_TAKE1("Satisfy", satisfy, NULL, OR_AUTHCFG,
 
3258
  "access policy if both allow and require used ('all' or 'any')"),
 
3259
#ifdef GPROF
 
3260
AP_INIT_TAKE1("GprofDir", set_gprof_dir, NULL, RSRC_CONF,
 
3261
  "Directory to plop gmon.out files"),
 
3262
#endif
 
3263
AP_INIT_TAKE1("AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO,
 
3264
  "The name of the default charset to add to any Content-Type without one or 'Off' to disable"),
 
3265
AP_INIT_TAKE1("AcceptPathInfo", set_accept_path_info, NULL, OR_FILEINFO,
 
3266
  "Set to on or off for PATH_INFO to be accepted by handlers, or default for the per-handler preference"),
 
3267
 
 
3268
/* Old resource config file commands */
 
3269
 
 
3270
AP_INIT_RAW_ARGS("AccessFileName", set_access_name, NULL, RSRC_CONF,
 
3271
  "Name(s) of per-directory config files (default: .htaccess)"),
 
3272
AP_INIT_TAKE1("DocumentRoot", set_document_root, NULL, RSRC_CONF,
 
3273
  "Root directory of the document tree"),
 
3274
AP_INIT_TAKE2("ErrorDocument", set_error_document, NULL, OR_FILEINFO,
 
3275
  "Change responses for HTTP errors"),
 
3276
AP_INIT_RAW_ARGS("AllowOverride", set_override, NULL, ACCESS_CONF,
 
3277
  "Controls what groups of directives can be configured by per-directory "
 
3278
  "config files"),
 
3279
AP_INIT_RAW_ARGS("Options", set_options, NULL, OR_OPTIONS,
 
3280
  "Set a number of attributes for a given directory"),
 
3281
AP_INIT_TAKE1("DefaultType", ap_set_string_slot,
 
3282
  (void*)APR_OFFSETOF(core_dir_config, ap_default_type),
 
3283
  OR_FILEINFO, "the default MIME type for untypable files"),
 
3284
AP_INIT_RAW_ARGS("FileETag", set_etag_bits, NULL, OR_FILEINFO,
 
3285
  "Specify components used to construct a file's ETag"),
 
3286
AP_INIT_TAKE1("EnableMMAP", set_enable_mmap, NULL, OR_FILEINFO,
 
3287
  "Controls whether memory-mapping may be used to read files"),
 
3288
AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO,
 
3289
  "Controls whether sendfile may be used to transmit files"),
 
3290
 
 
3291
/* Old server config file commands */
 
3292
 
 
3293
AP_INIT_TAKE1("Protocol", set_protocol, NULL, RSRC_CONF,
 
3294
  "Set the Protocol for httpd to use."),
 
3295
AP_INIT_TAKE2("AcceptFilter", set_accf_map, NULL, RSRC_CONF,
 
3296
  "Set the Accept Filter to use for a protocol"),
 
3297
AP_INIT_TAKE1("Port", ap_set_deprecated, NULL, RSRC_CONF,
 
3298
  "Port was replaced with Listen in Apache 2.0"),
 
3299
AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL,
 
3300
  ACCESS_CONF|RSRC_CONF,
 
3301
  "\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
 
3302
  "enable double-reverse DNS lookups"),
 
3303
AP_INIT_TAKE1("ServerAdmin", set_server_string_slot,
 
3304
  (void *)APR_OFFSETOF(server_rec, server_admin), RSRC_CONF,
 
3305
  "The email address of the server administrator"),
 
3306
AP_INIT_TAKE1("ServerName", server_hostname_port, NULL, RSRC_CONF,
 
3307
  "The hostname and port of the server"),
 
3308
AP_INIT_TAKE1("ServerSignature", set_signature_flag, NULL, OR_ALL,
 
3309
  "En-/disable server signature (on|off|email)"),
 
3310
AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF | EXEC_ON_READ,
 
3311
  "Common directory of server-related files (logs, confs, etc.)"),
 
3312
AP_INIT_TAKE1("ErrorLog", set_server_string_slot,
 
3313
  (void *)APR_OFFSETOF(server_rec, error_fname), RSRC_CONF,
 
3314
  "The filename of the error log"),
 
3315
AP_INIT_RAW_ARGS("ServerAlias", set_server_alias, NULL, RSRC_CONF,
 
3316
  "A name or names alternately used to access the server"),
 
3317
AP_INIT_TAKE1("ServerPath", set_serverpath, NULL, RSRC_CONF,
 
3318
  "The pathname the server can be reached at"),
 
3319
AP_INIT_TAKE1("Timeout", set_timeout, NULL, RSRC_CONF,
 
3320
  "Timeout duration (sec)"),
 
3321
AP_INIT_FLAG("ContentDigest", set_content_md5, NULL, OR_OPTIONS,
 
3322
  "whether or not to send a Content-MD5 header with each request"),
 
3323
AP_INIT_TAKE1("UseCanonicalName", set_use_canonical_name, NULL,
 
3324
  RSRC_CONF|ACCESS_CONF,
 
3325
  "How to work out the ServerName : Port when constructing URLs"),
 
3326
AP_INIT_TAKE1("UseCanonicalPhysicalPort", set_use_canonical_phys_port, NULL,
 
3327
  RSRC_CONF|ACCESS_CONF,
 
3328
  "Whether to use the physical Port when constructing URLs"),
 
3329
/* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
 
3330
/* TODO: ListenBacklog in MPM */
 
3331
AP_INIT_TAKE1("Include", include_config, NULL,
 
3332
  (RSRC_CONF | ACCESS_CONF | EXEC_ON_READ),
 
3333
  "Name of the config file to be included"),
 
3334
AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF,
 
3335
  "Level of verbosity in error logging"),
 
3336
AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF,
 
3337
  "A numeric IP address:port, or the name of a host"),
 
3338
AP_INIT_TAKE1("ServerTokens", set_serv_tokens, NULL, RSRC_CONF,
 
3339
  "Determine tokens displayed in the Server: header - Min(imal), OS or Full"),
 
3340
AP_INIT_TAKE1("LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF,
 
3341
  "Limit on maximum size of an HTTP request line"),
 
3342
AP_INIT_TAKE1("LimitRequestFieldsize", set_limit_req_fieldsize, NULL,
 
3343
  RSRC_CONF,
 
3344
  "Limit on maximum size of an HTTP request header field"),
 
3345
AP_INIT_TAKE1("LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF,
 
3346
  "Limit (0 = unlimited) on max number of header fields in a request message"),
 
3347
AP_INIT_TAKE1("LimitRequestBody", set_limit_req_body,
 
3348
  (void*)APR_OFFSETOF(core_dir_config, limit_req_body), OR_ALL,
 
3349
  "Limit (in bytes) on maximum size of request message body"),
 
3350
AP_INIT_TAKE1("LimitXMLRequestBody", set_limit_xml_req_body, NULL, OR_ALL,
 
3351
              "Limit (in bytes) on maximum size of an XML-based request "
 
3352
              "body"),
 
3353
 
 
3354
/* System Resource Controls */
 
3355
#ifdef RLIMIT_CPU
 
3356
AP_INIT_TAKE12("RLimitCPU", set_limit_cpu,
 
3357
  (void*)APR_OFFSETOF(core_dir_config, limit_cpu),
 
3358
  OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
 
3359
#else
 
3360
AP_INIT_TAKE12("RLimitCPU", no_set_limit, NULL,
 
3361
  OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
 
3362
#endif
 
3363
#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
 
3364
AP_INIT_TAKE12("RLimitMEM", set_limit_mem,
 
3365
  (void*)APR_OFFSETOF(core_dir_config, limit_mem),
 
3366
  OR_ALL, "Soft/hard limits for max memory usage per process"),
 
3367
#else
 
3368
AP_INIT_TAKE12("RLimitMEM", no_set_limit, NULL,
 
3369
  OR_ALL, "Soft/hard limits for max memory usage per process"),
 
3370
#endif
 
3371
#ifdef RLIMIT_NPROC
 
3372
AP_INIT_TAKE12("RLimitNPROC", set_limit_nproc,
 
3373
  (void*)APR_OFFSETOF(core_dir_config, limit_nproc),
 
3374
  OR_ALL, "soft/hard limits for max number of processes per uid"),
 
3375
#else
 
3376
AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL,
 
3377
   OR_ALL, "soft/hard limits for max number of processes per uid"),
 
3378
#endif
 
3379
 
 
3380
/* internal recursion stopper */
 
3381
AP_INIT_TAKE12("LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF,
 
3382
              "maximum recursion depth of internal redirects and subrequests"),
 
3383
 
 
3384
AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower,
 
3385
       (void *)APR_OFFSETOF(core_dir_config, mime_type), OR_FILEINFO,
 
3386
     "a mime type that overrides other configured type"),
 
3387
AP_INIT_TAKE1("SetHandler", ap_set_string_slot_lower,
 
3388
       (void *)APR_OFFSETOF(core_dir_config, handler), OR_FILEINFO,
 
3389
   "a handler name that overrides any other configured handler"),
 
3390
AP_INIT_TAKE1("SetOutputFilter", ap_set_string_slot,
 
3391
       (void *)APR_OFFSETOF(core_dir_config, output_filters), OR_FILEINFO,
 
3392
   "filter (or ; delimited list of filters) to be run on the request content"),
 
3393
AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot,
 
3394
       (void *)APR_OFFSETOF(core_dir_config, input_filters), OR_FILEINFO,
 
3395
   "filter (or ; delimited list of filters) to be run on the request body"),
 
3396
AP_INIT_ITERATE2("AddOutputFilterByType", add_ct_output_filters,
 
3397
       (void *)APR_OFFSETOF(core_dir_config, ct_output_filters), OR_FILEINFO,
 
3398
     "output filter name followed by one or more content-types"),
 
3399
AP_INIT_FLAG("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF,
 
3400
             "Allow URLs containing '/' encoded as '%2F'"),
 
3401
 
 
3402
/*
 
3403
 * These are default configuration directives that mpms can/should
 
3404
 * pay attention to. If an mpm wishes to use these, they should
 
3405
 * #defined them in mpm.h.
 
3406
 */
 
3407
#ifdef AP_MPM_WANT_SET_PIDFILE
 
3408
AP_INIT_TAKE1("PidFile",  ap_mpm_set_pidfile, NULL, RSRC_CONF,
 
3409
              "A file for logging the server process ID"),
 
3410
#endif
 
3411
#ifdef AP_MPM_WANT_SET_SCOREBOARD
 
3412
AP_INIT_TAKE1("ScoreBoardFile", ap_mpm_set_scoreboard, NULL, RSRC_CONF,
 
3413
              "A file for Apache to maintain runtime process management information"),
 
3414
#endif
 
3415
#ifdef AP_MPM_WANT_SET_LOCKFILE
 
3416
AP_INIT_TAKE1("LockFile",  ap_mpm_set_lockfile, NULL, RSRC_CONF,
 
3417
              "The lockfile used when Apache needs to lock the accept() call"),
 
3418
#endif
 
3419
#ifdef AP_MPM_WANT_SET_MAX_REQUESTS
 
3420
AP_INIT_TAKE1("MaxRequestsPerChild", ap_mpm_set_max_requests, NULL, RSRC_CONF,
 
3421
              "Maximum number of requests a particular child serves before dying."),
 
3422
#endif
 
3423
#ifdef AP_MPM_WANT_SET_COREDUMPDIR
 
3424
AP_INIT_TAKE1("CoreDumpDirectory", ap_mpm_set_coredumpdir, NULL, RSRC_CONF,
 
3425
              "The location of the directory Apache changes to before dumping core"),
 
3426
#endif
 
3427
#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
 
3428
AP_INIT_TAKE1("AcceptMutex", ap_mpm_set_accept_lock_mech, NULL, RSRC_CONF,
 
3429
              ap_valid_accept_mutex_string),
 
3430
#endif
 
3431
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
 
3432
AP_INIT_TAKE1("MaxMemFree", ap_mpm_set_max_mem_free, NULL, RSRC_CONF,
 
3433
              "Maximum number of 1k blocks a particular childs allocator may hold."),
 
3434
#endif
 
3435
#ifdef AP_MPM_WANT_SET_STACKSIZE
 
3436
AP_INIT_TAKE1("ThreadStackSize", ap_mpm_set_thread_stacksize, NULL, RSRC_CONF,
 
3437
              "Size in bytes of stack used by threads handling client connections"),
 
3438
#endif
 
3439
#if AP_ENABLE_EXCEPTION_HOOK
 
3440
AP_INIT_TAKE1("EnableExceptionHook", ap_mpm_set_exception_hook, NULL, RSRC_CONF,
 
3441
              "Controls whether exception hook may be called after a crash"),
 
3442
#endif
 
3443
AP_INIT_TAKE1("TraceEnable", set_trace_enable, NULL, RSRC_CONF,
 
3444
              "'on' (default), 'off' or 'extended' to trace request body content"),
 
3445
{ NULL }
 
3446
};
 
3447
 
 
3448
/*****************************************************************
 
3449
 *
 
3450
 * Core handlers for various phases of server operation...
 
3451
 */
 
3452
 
 
3453
AP_DECLARE_NONSTD(int) ap_core_translate(request_rec *r)
 
3454
{
 
3455
    void *sconf = r->server->module_config;
 
3456
    core_server_config *conf = ap_get_module_config(sconf, &core_module);
 
3457
    apr_status_t rv;
 
3458
 
 
3459
    /* XXX this seems too specific, this should probably become
 
3460
     * some general-case test
 
3461
     */
 
3462
    if (r->proxyreq) {
 
3463
        return HTTP_FORBIDDEN;
 
3464
    }
 
3465
    if (!r->uri || ((r->uri[0] != '/') && strcmp(r->uri, "*"))) {
 
3466
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3467
                     "Invalid URI in request %s", r->the_request);
 
3468
        return HTTP_BAD_REQUEST;
 
3469
    }
 
3470
 
 
3471
    if (r->server->path
 
3472
        && !strncmp(r->uri, r->server->path, r->server->pathlen)
 
3473
        && (r->server->path[r->server->pathlen - 1] == '/'
 
3474
            || r->uri[r->server->pathlen] == '/'
 
3475
            || r->uri[r->server->pathlen] == '\0'))
 
3476
    {
 
3477
        /* skip all leading /'s (e.g. http://localhost///foo)
 
3478
         * so we are looking at only the relative path.
 
3479
         */
 
3480
        char *path = r->uri + r->server->pathlen;
 
3481
        while (*path == '/') {
 
3482
            ++path;
 
3483
        }
 
3484
        if ((rv = apr_filepath_merge(&r->filename, conf->ap_document_root, path,
 
3485
                                     APR_FILEPATH_TRUENAME
 
3486
                                   | APR_FILEPATH_SECUREROOT, r->pool))
 
3487
                    != APR_SUCCESS) {
 
3488
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
 
3489
                         "Cannot map %s to file", r->the_request);
 
3490
            return HTTP_FORBIDDEN;
 
3491
        }
 
3492
        r->canonical_filename = r->filename;
 
3493
    }
 
3494
    else {
 
3495
        /*
 
3496
         * Make sure that we do not mess up the translation by adding two
 
3497
         * /'s in a row.  This happens under windows when the document
 
3498
         * root ends with a /
 
3499
         */
 
3500
        /* skip all leading /'s (e.g. http://localhost///foo)
 
3501
         * so we are looking at only the relative path.
 
3502
         */
 
3503
        char *path = r->uri;
 
3504
        while (*path == '/') {
 
3505
            ++path;
 
3506
        }
 
3507
        if ((rv = apr_filepath_merge(&r->filename, conf->ap_document_root, path,
 
3508
                                     APR_FILEPATH_TRUENAME
 
3509
                                   | APR_FILEPATH_SECUREROOT, r->pool))
 
3510
                    != APR_SUCCESS) {
 
3511
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
 
3512
                         "Cannot map %s to file", r->the_request);
 
3513
            return HTTP_FORBIDDEN;
 
3514
        }
 
3515
        r->canonical_filename = r->filename;
 
3516
    }
 
3517
 
 
3518
    return OK;
 
3519
}
 
3520
 
 
3521
/*****************************************************************
 
3522
 *
 
3523
 * Test the filesystem name through directory_walk and file_walk
 
3524
 */
 
3525
static int core_map_to_storage(request_rec *r)
 
3526
{
 
3527
    int access_status;
 
3528
 
 
3529
    if ((access_status = ap_directory_walk(r))) {
 
3530
        return access_status;
 
3531
    }
 
3532
 
 
3533
    if ((access_status = ap_file_walk(r))) {
 
3534
        return access_status;
 
3535
    }
 
3536
 
 
3537
    return OK;
 
3538
}
 
3539
 
 
3540
 
 
3541
static int do_nothing(request_rec *r) { return OK; }
 
3542
 
 
3543
 
 
3544
static int core_override_type(request_rec *r)
 
3545
{
 
3546
    core_dir_config *conf =
 
3547
        (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
3548
                                                &core_module);
 
3549
 
 
3550
    /* Check for overrides with ForceType / SetHandler
 
3551
     */
 
3552
    if (conf->mime_type && strcmp(conf->mime_type, "none"))
 
3553
        ap_set_content_type(r, (char*) conf->mime_type);
 
3554
 
 
3555
    if (conf->handler && strcmp(conf->handler, "none"))
 
3556
        r->handler = conf->handler;
 
3557
 
 
3558
    /* Deal with the poor soul who is trying to force path_info to be
 
3559
     * accepted within the core_handler, where they will let the subreq
 
3560
     * address its contents.  This is toggled by the user in the very
 
3561
     * beginning of the fixup phase, so modules should override the user's
 
3562
     * discretion in their own module fixup phase.  It is tristate, if
 
3563
     * the user doesn't specify, the result is 2 (which the module may
 
3564
     * interpret to its own customary behavior.)  It won't be touched
 
3565
     * if the value is no longer undefined (2), so any module changing
 
3566
     * the value prior to the fixup phase OVERRIDES the user's choice.
 
3567
     */
 
3568
    if ((r->used_path_info == AP_REQ_DEFAULT_PATH_INFO)
 
3569
        && (conf->accept_path_info != 3)) {
 
3570
        r->used_path_info = conf->accept_path_info;
 
3571
    }
 
3572
 
 
3573
    return OK;
 
3574
}
 
3575
 
 
3576
static int default_handler(request_rec *r)
 
3577
{
 
3578
    conn_rec *c = r->connection;
 
3579
    apr_bucket_brigade *bb;
 
3580
    apr_bucket *e;
 
3581
    core_dir_config *d;
 
3582
    int errstatus;
 
3583
    apr_file_t *fd = NULL;
 
3584
    apr_status_t status;
 
3585
    /* XXX if/when somebody writes a content-md5 filter we either need to
 
3586
     *     remove this support or coordinate when to use the filter vs.
 
3587
     *     when to use this code
 
3588
     *     The current choice of when to compute the md5 here matches the 1.3
 
3589
     *     support fairly closely (unlike 1.3, we don't handle computing md5
 
3590
     *     when the charset is translated).
 
3591
     */
 
3592
    int bld_content_md5;
 
3593
 
 
3594
    d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
 
3595
                                                &core_module);
 
3596
    bld_content_md5 = (d->content_md5 & 1)
 
3597
                      && r->output_filters->frec->ftype != AP_FTYPE_RESOURCE;
 
3598
 
 
3599
    ap_allow_standard_methods(r, MERGE_ALLOW, M_GET, M_OPTIONS, M_POST, -1);
 
3600
 
 
3601
    /* If filters intend to consume the request body, they must
 
3602
     * register an InputFilter to slurp the contents of the POST
 
3603
     * data from the POST input stream.  It no longer exists when
 
3604
     * the output filters are invoked by the default handler.
 
3605
     */
 
3606
    if ((errstatus = ap_discard_request_body(r)) != OK) {
 
3607
        return errstatus;
 
3608
    }
 
3609
 
 
3610
    if (r->method_number == M_GET || r->method_number == M_POST) {
 
3611
        if (r->finfo.filetype == 0) {
 
3612
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3613
                          "File does not exist: %s", r->filename);
 
3614
            return HTTP_NOT_FOUND;
 
3615
        }
 
3616
 
 
3617
        /* Don't try to serve a dir.  Some OSs do weird things with
 
3618
         * raw I/O on a dir.
 
3619
         */
 
3620
        if (r->finfo.filetype == APR_DIR) {
 
3621
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3622
                          "Attempt to serve directory: %s", r->filename);
 
3623
            return HTTP_NOT_FOUND;
 
3624
        }
 
3625
 
 
3626
        if ((r->used_path_info != AP_REQ_ACCEPT_PATH_INFO) &&
 
3627
            r->path_info && *r->path_info)
 
3628
        {
 
3629
            /* default to reject */
 
3630
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3631
                          "File does not exist: %s",
 
3632
                          apr_pstrcat(r->pool, r->filename, r->path_info, NULL));
 
3633
            return HTTP_NOT_FOUND;
 
3634
        }
 
3635
 
 
3636
        /* We understood the (non-GET) method, but it might not be legal for
 
3637
           this particular resource. Check to see if the 'deliver_script'
 
3638
           flag is set. If so, then we go ahead and deliver the file since
 
3639
           it isn't really content (only GET normally returns content).
 
3640
 
 
3641
           Note: based on logic further above, the only possible non-GET
 
3642
           method at this point is POST. In the future, we should enable
 
3643
           script delivery for all methods.  */
 
3644
        if (r->method_number != M_GET) {
 
3645
            core_request_config *req_cfg;
 
3646
 
 
3647
            req_cfg = ap_get_module_config(r->request_config, &core_module);
 
3648
            if (!req_cfg->deliver_script) {
 
3649
                /* The flag hasn't been set for this request. Punt. */
 
3650
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3651
                              "This resource does not accept the %s method.",
 
3652
                              r->method);
 
3653
                return HTTP_METHOD_NOT_ALLOWED;
 
3654
            }
 
3655
        }
 
3656
 
 
3657
 
 
3658
        if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY
 
3659
#if APR_HAS_SENDFILE
 
3660
                            | ((d->enable_sendfile == ENABLE_SENDFILE_OFF)
 
3661
                                                ? 0 : APR_SENDFILE_ENABLED)
 
3662
#endif
 
3663
                                    , 0, r->pool)) != APR_SUCCESS) {
 
3664
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
 
3665
                          "file permissions deny server access: %s", r->filename);
 
3666
            return HTTP_FORBIDDEN;
 
3667
        }
 
3668
 
 
3669
        ap_update_mtime(r, r->finfo.mtime);
 
3670
        ap_set_last_modified(r);
 
3671
        ap_set_etag(r);
 
3672
        apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
 
3673
        ap_set_content_length(r, r->finfo.size);
 
3674
 
 
3675
        bb = apr_brigade_create(r->pool, c->bucket_alloc);
 
3676
 
 
3677
        if ((errstatus = ap_meets_conditions(r)) != OK) {
 
3678
            apr_file_close(fd);
 
3679
            r->status = errstatus;
 
3680
        }
 
3681
        else {
 
3682
            if (bld_content_md5) {
 
3683
                apr_table_setn(r->headers_out, "Content-MD5",
 
3684
                               ap_md5digest(r->pool, fd));
 
3685
            }
 
3686
 
 
3687
            /* For platforms where the size of the file may be larger than
 
3688
             * that which can be stored in a single bucket (where the
 
3689
             * length field is an apr_size_t), split it into several
 
3690
             * buckets: */
 
3691
            if (sizeof(apr_off_t) > sizeof(apr_size_t)
 
3692
                && r->finfo.size > AP_MAX_SENDFILE) {
 
3693
                apr_off_t fsize = r->finfo.size;
 
3694
                e = apr_bucket_file_create(fd, 0, AP_MAX_SENDFILE, r->pool,
 
3695
                                           c->bucket_alloc);
 
3696
                while (fsize > AP_MAX_SENDFILE) {
 
3697
                    apr_bucket *ce;
 
3698
                    apr_bucket_copy(e, &ce);
 
3699
                    APR_BRIGADE_INSERT_TAIL(bb, ce);
 
3700
                    e->start += AP_MAX_SENDFILE;
 
3701
                    fsize -= AP_MAX_SENDFILE;
 
3702
                }
 
3703
                e->length = (apr_size_t)fsize; /* Resize just the last bucket */
 
3704
            }
 
3705
            else {
 
3706
                e = apr_bucket_file_create(fd, 0, (apr_size_t)r->finfo.size,
 
3707
                                           r->pool, c->bucket_alloc);
 
3708
            }
 
3709
 
 
3710
#if APR_HAS_MMAP
 
3711
            if (d->enable_mmap == ENABLE_MMAP_OFF) {
 
3712
                (void)apr_bucket_file_enable_mmap(e, 0);
 
3713
            }
 
3714
#endif
 
3715
            APR_BRIGADE_INSERT_TAIL(bb, e);
 
3716
        }
 
3717
 
 
3718
        e = apr_bucket_eos_create(c->bucket_alloc);
 
3719
        APR_BRIGADE_INSERT_TAIL(bb, e);
 
3720
 
 
3721
        status = ap_pass_brigade(r->output_filters, bb);
 
3722
        if (status == APR_SUCCESS
 
3723
            || r->status != HTTP_OK
 
3724
            || c->aborted) {
 
3725
            return OK;
 
3726
        }
 
3727
        else {
 
3728
            /* no way to know what type of error occurred */
 
3729
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
 
3730
                          "default_handler: ap_pass_brigade returned %i",
 
3731
                          status);
 
3732
            return HTTP_INTERNAL_SERVER_ERROR;
 
3733
        }
 
3734
    }
 
3735
    else {              /* unusual method (not GET or POST) */
 
3736
        if (r->method_number == M_INVALID) {
 
3737
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
3738
                          "Invalid method in request %s", r->the_request);
 
3739
            return HTTP_NOT_IMPLEMENTED;
 
3740
        }
 
3741
 
 
3742
        if (r->method_number == M_OPTIONS) {
 
3743
            return ap_send_http_options(r);
 
3744
        }
 
3745
        return HTTP_METHOD_NOT_ALLOWED;
 
3746
    }
 
3747
}
 
3748
 
 
3749
/* Optional function coming from mod_logio, used for logging of output
 
3750
 * traffic
 
3751
 */
 
3752
APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *logio_add_bytes_out;
 
3753
 
 
3754
static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 
3755
{
 
3756
    logio_add_bytes_out = APR_RETRIEVE_OPTIONAL_FN(ap_logio_add_bytes_out);
 
3757
    ident_lookup = APR_RETRIEVE_OPTIONAL_FN(ap_ident_lookup);
 
3758
 
 
3759
    ap_set_version(pconf);
 
3760
    ap_setup_make_content_type(pconf);
 
3761
    return OK;
 
3762
}
 
3763
 
 
3764
static void core_insert_filter(request_rec *r)
 
3765
{
 
3766
    core_dir_config *conf = (core_dir_config *)
 
3767
                            ap_get_module_config(r->per_dir_config,
 
3768
                                                 &core_module);
 
3769
    const char *filter, *filters = conf->output_filters;
 
3770
 
 
3771
    if (filters) {
 
3772
        while (*filters && (filter = ap_getword(r->pool, &filters, ';'))) {
 
3773
            ap_add_output_filter(filter, NULL, r, r->connection);
 
3774
        }
 
3775
    }
 
3776
 
 
3777
    filters = conf->input_filters;
 
3778
    if (filters) {
 
3779
        while (*filters && (filter = ap_getword(r->pool, &filters, ';'))) {
 
3780
            ap_add_input_filter(filter, NULL, r, r->connection);
 
3781
        }
 
3782
    }
 
3783
}
 
3784
 
 
3785
static apr_size_t num_request_notes = AP_NUM_STD_NOTES;
 
3786
 
 
3787
static apr_status_t reset_request_notes(void *dummy)
 
3788
{
 
3789
    num_request_notes = AP_NUM_STD_NOTES;
 
3790
    return APR_SUCCESS;
 
3791
}
 
3792
 
 
3793
AP_DECLARE(apr_size_t) ap_register_request_note(void)
 
3794
{
 
3795
    apr_pool_cleanup_register(apr_hook_global_pool, NULL, reset_request_notes,
 
3796
                              apr_pool_cleanup_null);
 
3797
    return num_request_notes++;
 
3798
}
 
3799
 
 
3800
AP_DECLARE(void **) ap_get_request_note(request_rec *r, apr_size_t note_num)
 
3801
{
 
3802
    core_request_config *req_cfg;
 
3803
 
 
3804
    if (note_num >= num_request_notes) {
 
3805
        return NULL;
 
3806
    }
 
3807
 
 
3808
    req_cfg = (core_request_config *)
 
3809
        ap_get_module_config(r->request_config, &core_module);
 
3810
 
 
3811
    if (!req_cfg) {
 
3812
        return NULL;
 
3813
    }
 
3814
 
 
3815
    return &(req_cfg->notes[note_num]);
 
3816
}
 
3817
 
 
3818
static int core_create_req(request_rec *r)
 
3819
{
 
3820
    /* Alloc the config struct and the array of request notes in
 
3821
     * a single block for efficiency
 
3822
     */
 
3823
    core_request_config *req_cfg;
 
3824
 
 
3825
    req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config) +
 
3826
                          sizeof(void *) * num_request_notes);
 
3827
    req_cfg->notes = (void **)((char *)req_cfg + sizeof(core_request_config));
 
3828
 
 
3829
    /* ### temporarily enable script delivery as the default */
 
3830
    req_cfg->deliver_script = 1;
 
3831
 
 
3832
    if (r->main) {
 
3833
        core_request_config *main_req_cfg = (core_request_config *)
 
3834
            ap_get_module_config(r->main->request_config, &core_module);
 
3835
        req_cfg->bb = main_req_cfg->bb;
 
3836
    }
 
3837
    else {
 
3838
        req_cfg->bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
 
3839
    }
 
3840
 
 
3841
    ap_set_module_config(r->request_config, &core_module, req_cfg);
 
3842
 
 
3843
    return OK;
 
3844
}
 
3845
 
 
3846
static int core_create_proxy_req(request_rec *r, request_rec *pr)
 
3847
{
 
3848
    return core_create_req(pr);
 
3849
}
 
3850
 
 
3851
static conn_rec *core_create_conn(apr_pool_t *ptrans, server_rec *server,
 
3852
                                  apr_socket_t *csd, long id, void *sbh,
 
3853
                                  apr_bucket_alloc_t *alloc)
 
3854
{
 
3855
    apr_status_t rv;
 
3856
    conn_rec *c = (conn_rec *) apr_pcalloc(ptrans, sizeof(conn_rec));
 
3857
 
 
3858
    c->sbh = sbh;
 
3859
    (void)ap_update_child_status(c->sbh, SERVER_BUSY_READ, (request_rec *)NULL);
 
3860
 
 
3861
    /* Got a connection structure, so initialize what fields we can
 
3862
     * (the rest are zeroed out by pcalloc).
 
3863
     */
 
3864
    c->conn_config = ap_create_conn_config(ptrans);
 
3865
    c->notes = apr_table_make(ptrans, 5);
 
3866
 
 
3867
    c->pool = ptrans;
 
3868
    if ((rv = apr_socket_addr_get(&c->local_addr, APR_LOCAL, csd))
 
3869
        != APR_SUCCESS) {
 
3870
        ap_log_error(APLOG_MARK, APLOG_INFO, rv, server,
 
3871
                     "apr_socket_addr_get(APR_LOCAL)");
 
3872
        apr_socket_close(csd);
 
3873
        return NULL;
 
3874
    }
 
3875
 
 
3876
    apr_sockaddr_ip_get(&c->local_ip, c->local_addr);
 
3877
    if ((rv = apr_socket_addr_get(&c->remote_addr, APR_REMOTE, csd))
 
3878
        != APR_SUCCESS) {
 
3879
        ap_log_error(APLOG_MARK, APLOG_INFO, rv, server,
 
3880
                     "apr_socket_addr_get(APR_REMOTE)");
 
3881
        apr_socket_close(csd);
 
3882
        return NULL;
 
3883
    }
 
3884
 
 
3885
    apr_sockaddr_ip_get(&c->remote_ip, c->remote_addr);
 
3886
    c->base_server = server;
 
3887
 
 
3888
    c->id = id;
 
3889
    c->bucket_alloc = alloc;
 
3890
 
 
3891
    return c;
 
3892
}
 
3893
 
 
3894
static int core_pre_connection(conn_rec *c, void *csd)
 
3895
{
 
3896
    core_net_rec *net = apr_palloc(c->pool, sizeof(*net));
 
3897
    apr_status_t rv;
 
3898
 
 
3899
#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
 
3900
    /* The Nagle algorithm says that we should delay sending partial
 
3901
     * packets in hopes of getting more data.  We don't want to do
 
3902
     * this; we are not telnet.  There are bad interactions between
 
3903
     * persistent connections and Nagle's algorithm that have very severe
 
3904
     * performance penalties.  (Failing to disable Nagle is not much of a
 
3905
     * problem with simple HTTP.)
 
3906
     */
 
3907
    rv = apr_socket_opt_set(csd, APR_TCP_NODELAY, 1);
 
3908
    if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
 
3909
        /* expected cause is that the client disconnected already,
 
3910
         * hence the debug level
 
3911
         */
 
3912
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c,
 
3913
                      "apr_socket_opt_set(APR_TCP_NODELAY)");
 
3914
    }
 
3915
#endif
 
3916
 
 
3917
    /* The core filter requires the timeout mode to be set, which
 
3918
     * incidentally sets the socket to be nonblocking.  If this
 
3919
     * is not initialized correctly, Linux - for example - will
 
3920
     * be initially blocking, while Solaris will be non blocking
 
3921
     * and any initial read will fail.
 
3922
     */
 
3923
    rv = apr_socket_timeout_set(csd, c->base_server->timeout);
 
3924
    if (rv != APR_SUCCESS) {
 
3925
        /* expected cause is that the client disconnected already */
 
3926
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c,
 
3927
                      "apr_socket_timeout_set");
 
3928
    }
 
3929
 
 
3930
    net->c = c;
 
3931
    net->in_ctx = NULL;
 
3932
    net->out_ctx = NULL;
 
3933
    net->client_socket = csd;
 
3934
 
 
3935
    ap_set_module_config(net->c->conn_config, &core_module, csd);
 
3936
    ap_add_input_filter_handle(ap_core_input_filter_handle, net, NULL, net->c);
 
3937
    ap_add_output_filter_handle(ap_core_output_filter_handle, net, NULL, net->c);
 
3938
    return DONE;
 
3939
}
 
3940
 
 
3941
static void register_hooks(apr_pool_t *p)
 
3942
{
 
3943
    /* create_connection and install_transport_filters are
 
3944
     * hooks that should always be APR_HOOK_REALLY_LAST to give other
 
3945
     * modules the opportunity to install alternate network transports
 
3946
     * and stop other functions from being run.
 
3947
     */
 
3948
    ap_hook_create_connection(core_create_conn, NULL, NULL,
 
3949
                              APR_HOOK_REALLY_LAST);
 
3950
    ap_hook_pre_connection(core_pre_connection, NULL, NULL,
 
3951
                           APR_HOOK_REALLY_LAST);
 
3952
 
 
3953
    ap_hook_post_config(core_post_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
 
3954
    ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
 
3955
    ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
 
3956
    ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST);
 
3957
    ap_hook_child_init(ap_logs_child_init,NULL,NULL,APR_HOOK_MIDDLE);
 
3958
    ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
 
3959
    /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
 
3960
    ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
 
3961
    ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST);
 
3962
    ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
 
3963
    ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
 
3964
    APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL,
 
3965
                      APR_HOOK_MIDDLE);
 
3966
    ap_hook_pre_mpm(ap_create_scoreboard, NULL, NULL, APR_HOOK_MIDDLE);
 
3967
 
 
3968
    /* register the core's insert_filter hook and register core-provided
 
3969
     * filters
 
3970
     */
 
3971
    ap_hook_insert_filter(core_insert_filter, NULL, NULL, APR_HOOK_MIDDLE);
 
3972
 
 
3973
    ap_core_input_filter_handle =
 
3974
        ap_register_input_filter("CORE_IN", ap_core_input_filter,
 
3975
                                 NULL, AP_FTYPE_NETWORK);
 
3976
    ap_content_length_filter_handle =
 
3977
        ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter,
 
3978
                                  NULL, AP_FTYPE_PROTOCOL);
 
3979
    ap_core_output_filter_handle =
 
3980
        ap_register_output_filter("CORE", ap_core_output_filter,
 
3981
                                  NULL, AP_FTYPE_NETWORK);
 
3982
    ap_subreq_core_filter_handle =
 
3983
        ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter,
 
3984
                                  NULL, AP_FTYPE_CONTENT_SET);
 
3985
    ap_old_write_func =
 
3986
        ap_register_output_filter("OLD_WRITE", ap_old_write_filter,
 
3987
                                  NULL, AP_FTYPE_RESOURCE - 10);
 
3988
}
 
3989
 
 
3990
AP_DECLARE_DATA module core_module = {
 
3991
    STANDARD20_MODULE_STUFF,
 
3992
    create_core_dir_config,       /* create per-directory config structure */
 
3993
    merge_core_dir_configs,       /* merge per-directory config structures */
 
3994
    create_core_server_config,    /* create per-server config structure */
 
3995
    merge_core_server_configs,    /* merge per-server config structures */
 
3996
    core_cmds,                    /* command apr_table_t */
 
3997
    register_hooks                /* register hooks */
 
3998
};
 
3999