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

« back to all changes in this revision

Viewing changes to modules/generators/mod_info.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
/*
 
18
 * Info Module.  Display configuration information for the server and
 
19
 * all included modules.
 
20
 *
 
21
 * <Location /server-info>
 
22
 * SetHandler server-info
 
23
 * </Location>
 
24
 *
 
25
 * GET /server-info - Returns full configuration page for server and all modules
 
26
 * GET /server-info?server - Returns server configuration only
 
27
 * GET /server-info?module_name - Returns configuration for a single module
 
28
 * GET /server-info?list - Returns quick list of included modules
 
29
 * GET /server-info?config - Returns full configuration
 
30
 * GET /server-info?hooks - Returns a listing of the modules active for each hook
 
31
 *
 
32
 * Original Author:
 
33
 *   Rasmus Lerdorf <rasmus vex.net>, May 1996
 
34
 *
 
35
 * Modified By:
 
36
 *   Lou Langholtz <ldl usi.utah.edu>, July 1997
 
37
 *
 
38
 * Apache 2.0 Port:
 
39
 *   Ryan Morgan <rmorgan covalent.net>, August 2000
 
40
 *
 
41
 */
 
42
 
 
43
 
 
44
#include "apr.h"
 
45
#include "apr_strings.h"
 
46
#include "apr_lib.h"
 
47
#define APR_WANT_STRFUNC
 
48
#include "apr_want.h"
 
49
 
 
50
#define CORE_PRIVATE
 
51
 
 
52
#include "httpd.h"
 
53
#include "http_config.h"
 
54
#include "http_core.h"
 
55
#include "http_log.h"
 
56
#include "http_main.h"
 
57
#include "http_protocol.h"
 
58
#include "http_connection.h"
 
59
#include "http_request.h"
 
60
#include "util_script.h"
 
61
#include "ap_mpm.h"
 
62
 
 
63
typedef struct
 
64
{
 
65
    const char *name;           /* matching module name */
 
66
    const char *info;           /* additional info */
 
67
} info_entry;
 
68
 
 
69
typedef struct
 
70
{
 
71
    apr_array_header_t *more_info;
 
72
} info_svr_conf;
 
73
 
 
74
module AP_MODULE_DECLARE_DATA info_module;
 
75
 
 
76
static void *create_info_config(apr_pool_t * p, server_rec * s)
 
77
{
 
78
    info_svr_conf *conf =
 
79
        (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
 
80
 
 
81
    conf->more_info = apr_array_make(p, 20, sizeof(info_entry));
 
82
    return conf;
 
83
}
 
84
 
 
85
static void *merge_info_config(apr_pool_t * p, void *basev, void *overridesv)
 
86
{
 
87
    info_svr_conf *new =
 
88
        (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
 
89
    info_svr_conf *base = (info_svr_conf *) basev;
 
90
    info_svr_conf *overrides = (info_svr_conf *) overridesv;
 
91
 
 
92
    new->more_info =
 
93
        apr_array_append(p, overrides->more_info, base->more_info);
 
94
    return new;
 
95
}
 
96
 
 
97
static void put_int_flush_right(request_rec * r, int i, int field)
 
98
{
 
99
    if (field > 1 || i > 9)
 
100
        put_int_flush_right(r, i / 10, field - 1);
 
101
    if (i)
 
102
        ap_rputc('0' + i % 10, r);
 
103
    else
 
104
        ap_rputs("&nbsp;", r);
 
105
}
 
106
 
 
107
static void mod_info_indent(request_rec * r, int nest,
 
108
                            const char *thisfn, int linenum)
 
109
{
 
110
    int i;
 
111
    const char *prevfn =
 
112
        ap_get_module_config(r->request_config, &info_module);
 
113
    if (thisfn == NULL)
 
114
        thisfn = "*UNKNOWN*";
 
115
    if (prevfn == NULL || 0 != strcmp(prevfn, thisfn)) {
 
116
        thisfn = ap_escape_html(r->pool, thisfn);
 
117
        ap_rprintf(r, "<dd><tt><strong>In file: %s</strong></tt></dd>\n",
 
118
                   thisfn);
 
119
        ap_set_module_config(r->request_config, &info_module,
 
120
                             (void *) thisfn);
 
121
    }
 
122
 
 
123
    ap_rputs("<dd><tt>", r);
 
124
    put_int_flush_right(r, linenum > 0 ? linenum : 0, 4);
 
125
    ap_rputs(":&nbsp;", r);
 
126
 
 
127
    for (i = 1; i <= nest; ++i) {
 
128
        ap_rputs("&nbsp;&nbsp;", r);
 
129
    }
 
130
}
 
131
 
 
132
static void mod_info_show_cmd(request_rec * r, const ap_directive_t * dir,
 
133
                              int nest)
 
134
{
 
135
    mod_info_indent(r, nest, dir->filename, dir->line_num);
 
136
    ap_rprintf(r, "%s <i>%s</i></tt></dd>\n",
 
137
               ap_escape_html(r->pool, dir->directive),
 
138
               ap_escape_html(r->pool, dir->args));
 
139
}
 
140
 
 
141
static void mod_info_show_open(request_rec * r, const ap_directive_t * dir,
 
142
                               int nest)
 
143
{
 
144
    mod_info_indent(r, nest, dir->filename, dir->line_num);
 
145
    ap_rprintf(r, "%s %s</tt></dd>\n",
 
146
               ap_escape_html(r->pool, dir->directive),
 
147
               ap_escape_html(r->pool, dir->args));
 
148
}
 
149
 
 
150
static void mod_info_show_close(request_rec * r, const ap_directive_t * dir,
 
151
                                int nest)
 
152
{
 
153
    const char *dirname = dir->directive;
 
154
    mod_info_indent(r, nest, dir->filename, 0);
 
155
    if (*dirname == '<') {
 
156
        ap_rprintf(r, "&lt;/%s&gt;</tt></dd>",
 
157
                   ap_escape_html(r->pool, dirname + 1));
 
158
    }
 
159
    else {
 
160
        ap_rprintf(r, "/%s</tt></dd>", ap_escape_html(r->pool, dirname));
 
161
    }
 
162
}
 
163
 
 
164
static int mod_info_has_cmd(const command_rec * cmds, ap_directive_t * dir)
 
165
{
 
166
    const command_rec *cmd;
 
167
    if (cmds == NULL)
 
168
        return 1;
 
169
    for (cmd = cmds; cmd->name; ++cmd) {
 
170
        if (strcasecmp(cmd->name, dir->directive) == 0)
 
171
            return 1;
 
172
    }
 
173
    return 0;
 
174
}
 
175
 
 
176
static void mod_info_show_parents(request_rec * r, ap_directive_t * node,
 
177
                                  int from, int to)
 
178
{
 
179
    if (from < to)
 
180
        mod_info_show_parents(r, node->parent, from, to - 1);
 
181
    mod_info_show_open(r, node, to);
 
182
}
 
183
 
 
184
static int mod_info_module_cmds(request_rec * r, const command_rec * cmds,
 
185
                                ap_directive_t * node, int from, int level)
 
186
{
 
187
    int shown = from;
 
188
    ap_directive_t *dir;
 
189
    if (level == 0)
 
190
        ap_set_module_config(r->request_config, &info_module, NULL);
 
191
    for (dir = node; dir; dir = dir->next) {
 
192
        if (dir->first_child != NULL) {
 
193
            if (level < mod_info_module_cmds(r, cmds, dir->first_child,
 
194
                                             shown, level + 1)) {
 
195
                shown = level;
 
196
                mod_info_show_close(r, dir, level);
 
197
            }
 
198
        }
 
199
        else if (mod_info_has_cmd(cmds, dir)) {
 
200
            if (shown < level) {
 
201
                mod_info_show_parents(r, dir->parent, shown, level - 1);
 
202
                shown = level;
 
203
            }
 
204
            mod_info_show_cmd(r, dir, level);
 
205
        }
 
206
    }
 
207
    return shown;
 
208
}
 
209
 
 
210
typedef struct
 
211
{                               /*XXX: should get something from apr_hooks.h instead */
 
212
    void (*pFunc) (void);       /* just to get the right size */
 
213
    const char *szName;
 
214
    const char *const *aszPredecessors;
 
215
    const char *const *aszSuccessors;
 
216
    int nOrder;
 
217
} hook_struct_t;
 
218
 
 
219
/*
 
220
 * hook_get_t is a pointer to a function that takes void as an argument and
 
221
 * returns a pointer to an apr_array_header_t.  The nasty WIN32 ifdef
 
222
 * is required to account for the fact that the ap_hook* calls all use
 
223
 * STDCALL calling convention.
 
224
 */
 
225
typedef apr_array_header_t *(
 
226
#ifdef WIN32
 
227
                                __stdcall
 
228
#endif
 
229
                                * hook_get_t)      (void);
 
230
 
 
231
typedef struct
 
232
{
 
233
    const char *name;
 
234
    hook_get_t get;
 
235
} hook_lookup_t;
 
236
 
 
237
static hook_lookup_t startup_hooks[] = {
 
238
    {"Pre-Config", ap_hook_get_pre_config},
 
239
    {"Test Configuration", ap_hook_get_test_config},
 
240
    {"Post Configuration", ap_hook_get_post_config},
 
241
    {"Open Logs", ap_hook_get_open_logs},
 
242
    {"Child Init", ap_hook_get_child_init},
 
243
    {NULL},
 
244
};
 
245
 
 
246
static hook_lookup_t request_hooks[] = {
 
247
    {"Pre-Connection", ap_hook_get_pre_connection},
 
248
    {"Create Connection", ap_hook_get_create_connection},
 
249
    {"Process Connection", ap_hook_get_process_connection},
 
250
    {"Create Request", ap_hook_get_create_request},
 
251
    {"Post-Read Request", ap_hook_get_post_read_request},
 
252
    {"Header Parse", ap_hook_get_header_parser},
 
253
    {"HTTP Scheme", ap_hook_get_http_scheme},
 
254
    {"Default Port", ap_hook_get_default_port},
 
255
    {"Quick Handler", ap_hook_get_quick_handler},
 
256
    {"Translate Name", ap_hook_get_translate_name},
 
257
    {"Map to Storage", ap_hook_get_map_to_storage},
 
258
    {"Check Access", ap_hook_get_access_checker},
 
259
    {"Verify User ID", ap_hook_get_check_user_id},
 
260
    {"Verify User Access", ap_hook_get_auth_checker},
 
261
    {"Check Type", ap_hook_get_type_checker},
 
262
    {"Fixups", ap_hook_get_fixups},
 
263
    {"Insert Filters", ap_hook_get_insert_filter},
 
264
    {"Content Handlers", ap_hook_get_handler},
 
265
    {"Logging", ap_hook_get_log_transaction},
 
266
    {"Insert Errors", ap_hook_get_insert_error_filter},
 
267
    {NULL},
 
268
};
 
269
 
 
270
static int module_find_hook(module * modp, hook_get_t hook_get)
 
271
{
 
272
    int i;
 
273
    apr_array_header_t *hooks = hook_get();
 
274
    hook_struct_t *elts;
 
275
 
 
276
    if (!hooks) {
 
277
        return 0;
 
278
    }
 
279
 
 
280
    elts = (hook_struct_t *) hooks->elts;
 
281
 
 
282
    for (i = 0; i < hooks->nelts; i++) {
 
283
        if (strcmp(elts[i].szName, modp->name) == 0) {
 
284
            return 1;
 
285
        }
 
286
    }
 
287
 
 
288
    return 0;
 
289
}
 
290
 
 
291
static void module_participate(request_rec * r,
 
292
                               module * modp,
 
293
                               hook_lookup_t * lookup, int *comma)
 
294
{
 
295
    if (module_find_hook(modp, lookup->get)) {
 
296
        if (*comma) {
 
297
            ap_rputs(", ", r);
 
298
        }
 
299
        ap_rvputs(r, "<tt>", lookup->name, "</tt>", NULL);
 
300
        *comma = 1;
 
301
    }
 
302
}
 
303
 
 
304
static void module_request_hook_participate(request_rec * r, module * modp)
 
305
{
 
306
    int i, comma = 0;
 
307
 
 
308
    ap_rputs("<dt><strong>Request Phase Participation:</strong>\n", r);
 
309
 
 
310
    for (i = 0; request_hooks[i].name; i++) {
 
311
        module_participate(r, modp, &request_hooks[i], &comma);
 
312
    }
 
313
 
 
314
    if (!comma) {
 
315
        ap_rputs("<tt> <em>none</em></tt>", r);
 
316
    }
 
317
    ap_rputs("</dt>\n", r);
 
318
}
 
319
 
 
320
static const char *find_more_info(server_rec * s, const char *module_name)
 
321
{
 
322
    int i;
 
323
    info_svr_conf *conf =
 
324
        (info_svr_conf *) ap_get_module_config(s->module_config,
 
325
                                               &info_module);
 
326
    info_entry *entry = (info_entry *) conf->more_info->elts;
 
327
 
 
328
    if (!module_name) {
 
329
        return 0;
 
330
    }
 
331
    for (i = 0; i < conf->more_info->nelts; i++) {
 
332
        if (!strcmp(module_name, entry->name)) {
 
333
            return entry->info;
 
334
        }
 
335
        entry++;
 
336
    }
 
337
    return 0;
 
338
}
 
339
 
 
340
static int show_server_settings(request_rec * r)
 
341
{
 
342
    server_rec *serv = r->server;
 
343
    int max_daemons, forked, threaded;
 
344
 
 
345
    ap_rputs("<h2><a name=\"server\">Server Settings</a></h2>", r);
 
346
    ap_rprintf(r,
 
347
               "<dl><dt><strong>Server Version:</strong> "
 
348
               "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
 
349
               ap_get_server_version());
 
350
    ap_rprintf(r,
 
351
               "<dt><strong>Server Built:</strong> "
 
352
               "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
 
353
               ap_get_server_built());
 
354
    ap_rprintf(r,
 
355
               "<dt><strong>Module Magic Number:</strong> "
 
356
               "<tt>%d:%d</tt></dt>\n", MODULE_MAGIC_NUMBER_MAJOR,
 
357
               MODULE_MAGIC_NUMBER_MINOR);
 
358
    ap_rprintf(r,
 
359
               "<dt><strong>Hostname/port:</strong> "
 
360
               "<tt>%s:%u</tt></dt>\n", ap_get_server_name(r),
 
361
               ap_get_server_port(r));
 
362
    ap_rprintf(r,
 
363
               "<dt><strong>Timeouts:</strong> "
 
364
               "<tt>connection: %d &nbsp;&nbsp; "
 
365
               "keep-alive: %d</tt></dt>",
 
366
               (int) (apr_time_sec(serv->timeout)),
 
367
               (int) (apr_time_sec(serv->timeout)));
 
368
    ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons);
 
369
    ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
 
370
    ap_mpm_query(AP_MPMQ_IS_FORKED, &forked);
 
371
    ap_rprintf(r, "<dt><strong>MPM Name:</strong> <tt>%s</tt></dt>\n",
 
372
               ap_show_mpm());
 
373
    ap_rprintf(r,
 
374
               "<dt><strong>MPM Information:</strong> "
 
375
               "<tt>Max Daemons: %d Threaded: %s Forked: %s</tt></dt>\n",
 
376
               max_daemons, threaded ? "yes" : "no", forked ? "yes" : "no");
 
377
    ap_rprintf(r,
 
378
               "<dt><strong>Server Architecture:</strong> "
 
379
               "<tt>%ld-bit</tt></dt>\n", 8 * (long) sizeof(void *));
 
380
    ap_rprintf(r,
 
381
               "<dt><strong>Server Root:</strong> "
 
382
               "<tt>%s</tt></dt>\n", ap_server_root);
 
383
    ap_rprintf(r,
 
384
               "<dt><strong>Config File:</strong> "
 
385
               "<tt>%s</tt></dt>\n", ap_conftree->filename);
 
386
 
 
387
    ap_rputs("<dt><strong>Server Built With:</strong>\n"
 
388
             "<tt style=\"white-space: pre;\">\n", r);
 
389
 
 
390
    /* TODO: Not all of these defines are getting set like they do in main.c.
 
391
     *       Missing some headers?
 
392
     */
 
393
 
 
394
#ifdef BIG_SECURITY_HOLE
 
395
    ap_rputs(" -D BIG_SECURITY_HOLE\n", r);
 
396
#endif
 
397
 
 
398
#ifdef SECURITY_HOLE_PASS_AUTHORIZATION
 
399
    ap_rputs(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n", r);
 
400
#endif
 
401
 
 
402
#ifdef OS
 
403
    ap_rputs(" -D OS=\"" OS "\"\n", r);
 
404
#endif
 
405
 
 
406
#ifdef APACHE_MPM_DIR
 
407
    ap_rputs(" -D APACHE_MPM_DIR=\"" APACHE_MPM_DIR "\"\n", r);
 
408
#endif
 
409
 
 
410
#ifdef HAVE_SHMGET
 
411
    ap_rputs(" -D HAVE_SHMGET\n", r);
 
412
#endif
 
413
 
 
414
#if APR_FILE_BASED_SHM
 
415
    ap_rputs(" -D APR_FILE_BASED_SHM\n", r);
 
416
#endif
 
417
 
 
418
#if APR_HAS_SENDFILE
 
419
    ap_rputs(" -D APR_HAS_SENDFILE\n", r);
 
420
#endif
 
421
 
 
422
#if APR_HAS_MMAP
 
423
    ap_rputs(" -D APR_HAS_MMAP\n", r);
 
424
#endif
 
425
 
 
426
#ifdef NO_WRITEV
 
427
    ap_rputs(" -D NO_WRITEV\n", r);
 
428
#endif
 
429
 
 
430
#ifdef NO_LINGCLOSE
 
431
    ap_rputs(" -D NO_LINGCLOSE\n", r);
 
432
#endif
 
433
 
 
434
#if APR_HAVE_IPV6
 
435
    ap_rputs(" -D APR_HAVE_IPV6 (IPv4-mapped addresses ", r);
 
436
#ifdef AP_ENABLE_V4_MAPPED
 
437
    ap_rputs("enabled)\n", r);
 
438
#else
 
439
    ap_rputs("disabled)\n", r);
 
440
#endif
 
441
#endif
 
442
 
 
443
#if APR_USE_FLOCK_SERIALIZE
 
444
    ap_rputs(" -D APR_USE_FLOCK_SERIALIZE\n", r);
 
445
#endif
 
446
 
 
447
#if APR_USE_SYSVSEM_SERIALIZE
 
448
    ap_rputs(" -D APR_USE_SYSVSEM_SERIALIZE\n", r);
 
449
#endif
 
450
 
 
451
#if APR_USE_POSIXSEM_SERIALIZE
 
452
    ap_rputs(" -D APR_USE_POSIXSEM_SERIALIZE\n", r);
 
453
#endif
 
454
 
 
455
#if APR_USE_FCNTL_SERIALIZE
 
456
    ap_rputs(" -D APR_USE_FCNTL_SERIALIZE\n", r);
 
457
#endif
 
458
 
 
459
#if APR_USE_PROC_PTHREAD_SERIALIZE
 
460
    ap_rputs(" -D APR_USE_PROC_PTHREAD_SERIALIZE\n", r);
 
461
#endif
 
462
#if APR_PROCESS_LOCK_IS_GLOBAL
 
463
    ap_rputs(" -D APR_PROCESS_LOCK_IS_GLOBAL\n", r);
 
464
#endif
 
465
 
 
466
#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 
467
    ap_rputs(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n", r);
 
468
#endif
 
469
 
 
470
#if APR_HAS_OTHER_CHILD
 
471
    ap_rputs(" -D APR_HAS_OTHER_CHILD\n", r);
 
472
#endif
 
473
 
 
474
#ifdef AP_HAVE_RELIABLE_PIPED_LOGS
 
475
    ap_rputs(" -D AP_HAVE_RELIABLE_PIPED_LOGS\n", r);
 
476
#endif
 
477
 
 
478
#ifdef BUFFERED_LOGS
 
479
    ap_rputs(" -D BUFFERED_LOGS\n", r);
 
480
#ifdef PIPE_BUF
 
481
    ap_rputs(" -D PIPE_BUF=%ld\n", (long) PIPE_BUF, r);
 
482
#endif
 
483
#endif
 
484
 
 
485
#if APR_CHARSET_EBCDIC
 
486
    ap_rputs(" -D APR_CHARSET_EBCDIC\n", r);
 
487
#endif
 
488
 
 
489
#ifdef NEED_HASHBANG_EMUL
 
490
    ap_rputs(" -D NEED_HASHBANG_EMUL\n", r);
 
491
#endif
 
492
 
 
493
#ifdef SHARED_CORE
 
494
    ap_rputs(" -D SHARED_CORE\n", r);
 
495
#endif
 
496
 
 
497
/* This list displays the compiled in default paths: */
 
498
#ifdef HTTPD_ROOT
 
499
    ap_rputs(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n", r);
 
500
#endif
 
501
 
 
502
#ifdef SUEXEC_BIN
 
503
    ap_rputs(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n", r);
 
504
#endif
 
505
 
 
506
#if defined(SHARED_CORE) && defined(SHARED_CORE_DIR)
 
507
    ap_rputs(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n", r);
 
508
#endif
 
509
 
 
510
#ifdef DEFAULT_PIDLOG
 
511
    ap_rputs(" -D DEFAULT_PIDLOG=\"" DEFAULT_PIDLOG "\"\n", r);
 
512
#endif
 
513
 
 
514
#ifdef DEFAULT_SCOREBOARD
 
515
    ap_rputs(" -D DEFAULT_SCOREBOARD=\"" DEFAULT_SCOREBOARD "\"\n", r);
 
516
#endif
 
517
 
 
518
#ifdef DEFAULT_LOCKFILE
 
519
    ap_rputs(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n", r);
 
520
#endif
 
521
 
 
522
#ifdef DEFAULT_ERRORLOG
 
523
    ap_rputs(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n", r);
 
524
#endif
 
525
 
 
526
 
 
527
#ifdef AP_TYPES_CONFIG_FILE
 
528
    ap_rputs(" -D AP_TYPES_CONFIG_FILE=\"" AP_TYPES_CONFIG_FILE "\"\n", r);
 
529
#endif
 
530
 
 
531
#ifdef SERVER_CONFIG_FILE
 
532
    ap_rputs(" -D SERVER_CONFIG_FILE=\"" SERVER_CONFIG_FILE "\"\n", r);
 
533
#endif
 
534
    ap_rputs("</tt></dt>\n", r);
 
535
    ap_rputs("</dl><hr />", r);
 
536
    return 0;
 
537
}
 
538
 
 
539
static int dump_a_hook(request_rec * r, hook_get_t hook_get)
 
540
{
 
541
    int i;
 
542
    char qs;
 
543
    hook_struct_t *elts;
 
544
    apr_array_header_t *hooks = hook_get();
 
545
 
 
546
    if (!hooks) {
 
547
        return 0;
 
548
    }
 
549
 
 
550
    if (r->args && strcasecmp(r->args, "hooks") == 0) {
 
551
        qs = '?';
 
552
    }
 
553
    else {
 
554
        qs = '#';
 
555
    }
 
556
 
 
557
    elts = (hook_struct_t *) hooks->elts;
 
558
 
 
559
    for (i = 0; i < hooks->nelts; i++) {
 
560
        ap_rprintf(r,
 
561
                   "&nbsp;&nbsp; %02d <a href=\"%c%s\">%s</a> <br/>",
 
562
                   elts[i].nOrder, qs, elts[i].szName, elts[i].szName);
 
563
    }
 
564
    return 0;
 
565
}
 
566
 
 
567
static int show_active_hooks(request_rec * r)
 
568
{
 
569
    int i;
 
570
    ap_rputs("<h2><a name=\"startup_hooks\">Startup Hooks</a></h2>\n<dl>", r);
 
571
 
 
572
    for (i = 0; startup_hooks[i].name; i++) {
 
573
        ap_rprintf(r, "<dt><strong>%s:</strong>\n <br /><tt>\n",
 
574
                   startup_hooks[i].name);
 
575
        dump_a_hook(r, startup_hooks[i].get);
 
576
        ap_rputs("\n  </tt>\n</dt>\n", r);
 
577
    }
 
578
 
 
579
    ap_rputs
 
580
        ("</dl>\n<hr />\n<h2><a name=\"request_hooks\">Request Hooks</a></h2>\n<dl>",
 
581
         r);
 
582
 
 
583
    for (i = 0; request_hooks[i].name; i++) {
 
584
        ap_rprintf(r, "<dt><strong>%s:</strong>\n <br /><tt>\n",
 
585
                   request_hooks[i].name);
 
586
        dump_a_hook(r, request_hooks[i].get);
 
587
        ap_rputs("\n  </tt>\n</dt>\n", r);
 
588
    }
 
589
 
 
590
    ap_rputs("</dl>\n<hr />\n", r);
 
591
 
 
592
    return 0;
 
593
}
 
594
 
 
595
static int display_info(request_rec * r)
 
596
{
 
597
    module *modp = NULL;
 
598
    server_rec *serv = r->server;
 
599
    const char *more_info;
 
600
    const command_rec *cmd = NULL;
 
601
    int comma = 0;
 
602
 
 
603
    if (strcmp(r->handler, "server-info"))
 
604
        return DECLINED;
 
605
 
 
606
    r->allowed |= (AP_METHOD_BIT << M_GET);
 
607
    if (r->method_number != M_GET)
 
608
        return DECLINED;
 
609
 
 
610
    ap_set_content_type(r, "text/html");
 
611
 
 
612
    ap_rputs(DOCTYPE_XHTML_1_0T
 
613
             "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
 
614
             "<head>\n"
 
615
             "  <title>Server Information</title>\n" "</head>\n", r);
 
616
    ap_rputs("<body><h1 style=\"text-align: center\">"
 
617
             "Apache Server Information</h1>\n", r);
 
618
    if (!r->args || strcasecmp(r->args, "list")) {
 
619
        if (!r->args) {
 
620
            ap_rputs("<dl><dt><tt>Subpages:<br />", r);
 
621
            ap_rputs("<a href=\"?config\">Configuration Files</a>, "
 
622
                     "<a href=\"?server\">Server Settings</a>, "
 
623
                     "<a href=\"?list\">Module List</a>,  "
 
624
                     "<a href=\"?hooks\">Active Hooks</a>", r);
 
625
            ap_rputs("</tt></dt></dl><hr />", r);
 
626
 
 
627
            ap_rputs("<dl><dt><tt>Sections:<br />", r);
 
628
            ap_rputs("<a href=\"#server\">Server Settings</a>, "
 
629
                     "<a href=\"#startup_hooks\">Startup Hooks</a>, "
 
630
                     "<a href=\"#request_hooks\">Request Hooks</a>", r);
 
631
            ap_rputs("</tt></dt></dl><hr />", r);
 
632
 
 
633
            ap_rputs("<dl><dt><tt>Loaded Modules: <br />", r);
 
634
            /* TODO: Sort by Alpha */
 
635
            for (modp = ap_top_module; modp; modp = modp->next) {
 
636
                ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name,
 
637
                           modp->name);
 
638
                if (modp->next) {
 
639
                    ap_rputs(", ", r);
 
640
                }
 
641
            }
 
642
            ap_rputs("</tt></dt></dl><hr />", r);
 
643
        }
 
644
 
 
645
        if (!r->args || !strcasecmp(r->args, "server")) {
 
646
            show_server_settings(r);
 
647
        }
 
648
 
 
649
        if (!r->args || !strcasecmp(r->args, "hooks")) {
 
650
            show_active_hooks(r);
 
651
        }
 
652
 
 
653
        if (r->args && 0 == strcasecmp(r->args, "config")) {
 
654
            ap_rputs("<dl><dt><strong>Configuration:</strong>\n", r);
 
655
            mod_info_module_cmds(r, NULL, ap_conftree, 0, 0);
 
656
            ap_rputs("</dl><hr />", r);
 
657
        }
 
658
        else {
 
659
            for (modp = ap_top_module; modp; modp = modp->next) {
 
660
                if (!r->args || !strcasecmp(modp->name, r->args)) {
 
661
                    ap_rprintf(r,
 
662
                               "<dl><dt><a name=\"%s\"><strong>Module Name:</strong></a> "
 
663
                               "<font size=\"+1\"><tt><a href=\"?%s\">%s</a></tt></font></dt>\n",
 
664
                               modp->name, modp->name, modp->name);
 
665
                    ap_rputs("<dt><strong>Content handlers:</strong> ", r);
 
666
 
 
667
                    if (module_find_hook(modp, ap_hook_get_handler)) {
 
668
                        ap_rputs("<tt> <em>yes</em></tt>", r);
 
669
                    }
 
670
                    else {
 
671
                        ap_rputs("<tt> <em>none</em></tt>", r);
 
672
                    }
 
673
 
 
674
                    ap_rputs("</dt>", r);
 
675
                    ap_rputs
 
676
                        ("<dt><strong>Configuration Phase Participation:</strong>\n",
 
677
                         r);
 
678
                    if (modp->create_dir_config) {
 
679
                        if (comma) {
 
680
                            ap_rputs(", ", r);
 
681
                        }
 
682
                        ap_rputs("<tt>Create Directory Config</tt>", r);
 
683
                        comma = 1;
 
684
                    }
 
685
                    if (modp->merge_dir_config) {
 
686
                        if (comma) {
 
687
                            ap_rputs(", ", r);
 
688
                        }
 
689
                        ap_rputs("<tt>Merge Directory Configs</tt>", r);
 
690
                        comma = 1;
 
691
                    }
 
692
                    if (modp->create_server_config) {
 
693
                        if (comma) {
 
694
                            ap_rputs(", ", r);
 
695
                        }
 
696
                        ap_rputs("<tt>Create Server Config</tt>", r);
 
697
                        comma = 1;
 
698
                    }
 
699
                    if (modp->merge_server_config) {
 
700
                        if (comma) {
 
701
                            ap_rputs(", ", r);
 
702
                        }
 
703
                        ap_rputs("<tt>Merge Server Configs</tt>", r);
 
704
                        comma = 1;
 
705
                    }
 
706
                    if (!comma)
 
707
                        ap_rputs("<tt> <em>none</em></tt>", r);
 
708
                    comma = 0;
 
709
                    ap_rputs("</dt>", r);
 
710
 
 
711
                    module_request_hook_participate(r, modp);
 
712
 
 
713
                    cmd = modp->cmds;
 
714
                    if (cmd) {
 
715
                        ap_rputs
 
716
                            ("<dt><strong>Module Directives:</strong></dt>",
 
717
                             r);
 
718
                        while (cmd) {
 
719
                            if (cmd->name) {
 
720
                                ap_rprintf(r, "<dd><tt>%s%s - <i>",
 
721
                                           ap_escape_html(r->pool, cmd->name),
 
722
                                           cmd->name[0] == '<' ? "&gt;" : "");
 
723
                                if (cmd->errmsg) {
 
724
                                    ap_rputs(cmd->errmsg, r);
 
725
                                }
 
726
                                ap_rputs("</i></tt></dd>\n", r);
 
727
                            }
 
728
                            else {
 
729
                                break;
 
730
                            }
 
731
                            cmd++;
 
732
                        }
 
733
                        ap_rputs
 
734
                            ("<dt><strong>Current Configuration:</strong></dt>\n",
 
735
                             r);
 
736
                        mod_info_module_cmds(r, modp->cmds, ap_conftree, 0,
 
737
                                             0);
 
738
                    }
 
739
                    else {
 
740
                        ap_rputs
 
741
                            ("<dt><strong>Module Directives:</strong> <tt>none</tt></dt>",
 
742
                             r);
 
743
                    }
 
744
                    more_info = find_more_info(serv, modp->name);
 
745
                    if (more_info) {
 
746
                        ap_rputs
 
747
                            ("<dt><strong>Additional Information:</strong>\n</dt><dd>",
 
748
                             r);
 
749
                        ap_rputs(more_info, r);
 
750
                        ap_rputs("</dd>", r);
 
751
                    }
 
752
                    ap_rputs("</dl><hr />\n", r);
 
753
                    if (r->args) {
 
754
                        break;
 
755
                    }
 
756
                }
 
757
            }
 
758
            if (!modp && r->args && strcasecmp(r->args, "server")) {
 
759
                ap_rputs("<p><b>No such module</b></p>\n", r);
 
760
            }
 
761
        }
 
762
    }
 
763
    else {
 
764
        ap_rputs("<dl><dt>Server Module List</dt>", r);
 
765
        for (modp = ap_top_module; modp; modp = modp->next) {
 
766
            ap_rputs("<dd>", r);
 
767
            ap_rputs(modp->name, r);
 
768
            ap_rputs("</dd>", r);
 
769
        }
 
770
        ap_rputs("</dl><hr />", r);
 
771
    }
 
772
    ap_rputs(ap_psignature("", r), r);
 
773
    ap_rputs("</body></html>\n", r);
 
774
    /* Done, turn off timeout, close file and return */
 
775
    return 0;
 
776
}
 
777
 
 
778
static const char *add_module_info(cmd_parms * cmd, void *dummy,
 
779
                                   const char *name, const char *info)
 
780
{
 
781
    server_rec *s = cmd->server;
 
782
    info_svr_conf *conf =
 
783
        (info_svr_conf *) ap_get_module_config(s->module_config,
 
784
                                               &info_module);
 
785
    info_entry *new = apr_array_push(conf->more_info);
 
786
 
 
787
    new->name = name;
 
788
    new->info = info;
 
789
    return NULL;
 
790
}
 
791
 
 
792
static const command_rec info_cmds[] = {
 
793
    AP_INIT_TAKE2("AddModuleInfo", add_module_info, NULL, RSRC_CONF,
 
794
                  "a module name and additional information on that module"),
 
795
    {NULL}
 
796
};
 
797
 
 
798
static void register_hooks(apr_pool_t * p)
 
799
{
 
800
    ap_hook_handler(display_info, NULL, NULL, APR_HOOK_MIDDLE);
 
801
}
 
802
 
 
803
module AP_MODULE_DECLARE_DATA info_module = {
 
804
    STANDARD20_MODULE_STUFF,
 
805
    NULL,                       /* dir config creater */
 
806
    NULL,                       /* dir merger --- default is to override */
 
807
    create_info_config,         /* server config */
 
808
    merge_info_config,          /* merge server config */
 
809
    info_cmds,                  /* command apr_table_t */
 
810
    register_hooks
 
811
};