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 * Apache example module. Provide demonstrations of how modules do things. 19 * It is not meant to be used in a production server. Since it participates 20 * in all of the processing phases, it could conceivable interfere with 21 * the proper operation of other modules -- particularly the ones related 22 * to security. 23 * 24 * In the interest of brevity, all functions and structures internal to 25 * this module, but which may have counterparts in *real* modules, are 26 * prefixed with 'x_' instead of 'example_'. 27 * 28 * IMPORTANT NOTE 29 * ============== 30 * 31 * Some of the code in this module has problems. 32 * Before using it to base your work on, see 33 * 34 * http://issues.apache.org/bugzilla/show_bug.cgi?id=29709 35 * http://issues.apache.org/bugzilla/show_bug.cgi?id=32051 36 */ 37 38#include "httpd.h" 39#include "http_config.h" 40#include "http_core.h" 41#include "http_log.h" 42#include "http_main.h" 43#include "http_protocol.h" 44#include "http_request.h" 45#include "util_script.h" 46#include "http_connection.h" 47 48#include "apr_strings.h" 49 50#include <stdio.h> 51 52/*--------------------------------------------------------------------------*/ 53/* */ 54/* Data declarations. */ 55/* */ 56/* Here are the static cells and structure declarations private to our */ 57/* module. */ 58/* */ 59/*--------------------------------------------------------------------------*/ 60 61/* 62 * Sample configuration record. Used for both per-directory and per-server 63 * configuration data. 64 * 65 * It's perfectly reasonable to have two different structures for the two 66 * different environments. The same command handlers will be called for 67 * both, though, so the handlers need to be able to tell them apart. One 68 * possibility is for both structures to start with an int which is 0 for 69 * one and 1 for the other. 70 * 71 * Note that while the per-directory and per-server configuration records are 72 * available to most of the module handlers, they should be treated as 73 * READ-ONLY by all except the command and merge handlers. Sometimes handlers 74 * are handed a record that applies to the current location by implication or 75 * inheritance, and modifying it will change the rules for other locations. 76 */ 77typedef struct x_cfg { 78 int cmode; /* Environment to which record applies 79 * (directory, server, or combination). 80 */ 81#define CONFIG_MODE_SERVER 1 82#define CONFIG_MODE_DIRECTORY 2 83#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */ 84 int local; /* Boolean: "Example" directive declared 85 * here? 86 */ 87 int congenital; /* Boolean: did we inherit an "Example"? */ 88 char *trace; /* Pointer to trace string. */ 89 char *loc; /* Location to which this record applies. */ 90} x_cfg; 91 92/* 93 * Let's set up a module-local static cell to point to the accreting callback 94 * trace. As each API callback is made to us, we'll tack on the particulars 95 * to whatever we've already recorded. To avoid massive memory bloat as 96 * directories are walked again and again, we record the routine/environment 97 * the first time (non-request context only), and ignore subsequent calls for 98 * the same routine/environment. 99 */ 100static const char *trace = NULL; 101static apr_table_t *static_calls_made = NULL; 102 103/* 104 * To avoid leaking memory from pools other than the per-request one, we 105 * allocate a module-private pool, and then use a sub-pool of that which gets 106 * freed each time we modify the trace. That way previous layers of trace 107 * data don't get lost. 108 */ 109static apr_pool_t *x_pool = NULL; 110static apr_pool_t *x_subpool = NULL; 111 112/* 113 * Declare ourselves so the configuration routines can find and know us. 114 * We'll fill it in at the end of the module. 115 */ 116module AP_MODULE_DECLARE_DATA example_module; 117 118/*--------------------------------------------------------------------------*/ 119/* */ 120/* The following pseudo-prototype declarations illustrate the parameters */ 121/* passed to command handlers for the different types of directive */ 122/* syntax. If an argument was specified in the directive definition */ 123/* (look for "command_rec" below), it's available to the command handler */ 124/* via the (void *) info field in the cmd_parms argument passed to the */ 125/* handler (cmd->info for the examples below). */ 126/* */ 127/*--------------------------------------------------------------------------*/ 128 129/* 130 * Command handler for a NO_ARGS directive. Declared in the command_rec 131 * list with 132 * AP_INIT_NO_ARGS("directive", function, mconfig, where, help) 133 * 134 * static const char *handle_NO_ARGS(cmd_parms *cmd, void *mconfig); 135 */ 136 137/* 138 * Command handler for a RAW_ARGS directive. The "args" argument is the text 139 * of the commandline following the directive itself. Declared in the 140 * command_rec list with 141 * AP_INIT_RAW_ARGS("directive", function, mconfig, where, help) 142 * 143 * static const char *handle_RAW_ARGS(cmd_parms *cmd, void *mconfig, 144 * const char *args); 145 */ 146 147/* 148 * Command handler for a FLAG directive. The single parameter is passed in 149 * "bool", which is either zero or not for Off or On respectively. 150 * Declared in the command_rec list with 151 * AP_INIT_FLAG("directive", function, mconfig, where, help) 152 * 153 * static const char *handle_FLAG(cmd_parms *cmd, void *mconfig, int bool); 154 */ 155 156/* 157 * Command handler for a TAKE1 directive. The single parameter is passed in 158 * "word1". Declared in the command_rec list with 159 * AP_INIT_TAKE1("directive", function, mconfig, where, help) 160 * 161 * static const char *handle_TAKE1(cmd_parms *cmd, void *mconfig, 162 * char *word1); 163 */ 164 165/* 166 * Command handler for a TAKE2 directive. TAKE2 commands must always have 167 * exactly two arguments. Declared in the command_rec list with 168 * AP_INIT_TAKE2("directive", function, mconfig, where, help) 169 * 170 * static const char *handle_TAKE2(cmd_parms *cmd, void *mconfig, 171 * char *word1, char *word2); 172 */ 173 174/* 175 * Command handler for a TAKE3 directive. Like TAKE2, these must have exactly 176 * three arguments, or the parser complains and doesn't bother calling us. 177 * Declared in the command_rec list with 178 * AP_INIT_TAKE3("directive", function, mconfig, where, help) 179 * 180 * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig, 181 * char *word1, char *word2, char *word3); 182 */ 183 184/* 185 * Command handler for a TAKE12 directive. These can take either one or two 186 * arguments. 187 * - word2 is a NULL pointer if no second argument was specified. 188 * Declared in the command_rec list with 189 * AP_INIT_TAKE12("directive", function, mconfig, where, help) 190 * 191 * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig, 192 * char *word1, char *word2); 193 */ 194 195/* 196 * Command handler for a TAKE123 directive. A TAKE123 directive can be given, 197 * as might be expected, one, two, or three arguments. 198 * - word2 is a NULL pointer if no second argument was specified. 199 * - word3 is a NULL pointer if no third argument was specified. 200 * Declared in the command_rec list with 201 * AP_INIT_TAKE123("directive", function, mconfig, where, help) 202 * 203 * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig, 204 * char *word1, char *word2, char *word3); 205 */ 206 207/* 208 * Command handler for a TAKE13 directive. Either one or three arguments are 209 * permitted - no two-parameters-only syntax is allowed. 210 * - word2 and word3 are NULL pointers if only one argument was specified. 211 * Declared in the command_rec list with 212 * AP_INIT_TAKE13("directive", function, mconfig, where, help) 213 * 214 * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig, 215 * char *word1, char *word2, char *word3); 216 */ 217 218/* 219 * Command handler for a TAKE23 directive. At least two and as many as three 220 * arguments must be specified. 221 * - word3 is a NULL pointer if no third argument was specified. 222 * Declared in the command_rec list with 223 * AP_INIT_TAKE23("directive", function, mconfig, where, help) 224 * 225 * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig, 226 * char *word1, char *word2, char *word3); 227 */ 228 229/* 230 * Command handler for a ITERATE directive. 231 * - Handler is called once for each of n arguments given to the directive. 232 * - word1 points to each argument in turn. 233 * Declared in the command_rec list with 234 * AP_INIT_ITERATE("directive", function, mconfig, where, help) 235 * 236 * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig, 237 * char *word1); 238 */ 239 240/* 241 * Command handler for a ITERATE2 directive. 242 * - Handler is called once for each of the second and subsequent arguments 243 * given to the directive. 244 * - word1 is the same for each call for a particular directive instance (the 245 * first argument). 246 * - word2 points to each of the second and subsequent arguments in turn. 247 * Declared in the command_rec list with 248 * AP_INIT_ITERATE2("directive", function, mconfig, where, help) 249 * 250 * static const char *handle_ITERATE2(cmd_parms *cmd, void *mconfig, 251 * char *word1, char *word2); 252 */ 253 254/*--------------------------------------------------------------------------*/ 255/* */ 256/* These routines are strictly internal to this module, and support its */ 257/* operation. They are not referenced by any external portion of the */ 258/* server. */ 259/* */ 260/*--------------------------------------------------------------------------*/ 261 262/* 263 * Locate our directory configuration record for the current request. 264 */ 265static x_cfg *our_dconfig(const request_rec *r) 266{ 267 return (x_cfg *) ap_get_module_config(r->per_dir_config, &example_module); 268} 269 270#if 0 271/* 272 * Locate our server configuration record for the specified server. 273 */ 274static x_cfg *our_sconfig(const server_rec *s) 275{ 276 return (x_cfg *) ap_get_module_config(s->module_config, &example_module); 277} 278 279/* 280 * Likewise for our configuration record for the specified request. 281 */ 282static x_cfg *our_rconfig(const request_rec *r) 283{ 284 return (x_cfg *) ap_get_module_config(r->request_config, &example_module); 285} 286#endif 287 288/* 289 * Likewise for our configuration record for a connection. 290 */ 291static x_cfg *our_cconfig(const conn_rec *c) 292{ 293 return (x_cfg *) ap_get_module_config(c->conn_config, &example_module); 294} 295 296/* 297 * This routine sets up some module-wide cells if they haven't been already. 298 */ 299static void setup_module_cells(void) 300{ 301 /* 302 * If we haven't already allocated our module-private pool, do so now. 303 */ 304 if (x_pool == NULL) { 305 apr_pool_create(&x_pool, NULL); 306 }; 307 /* 308 * Likewise for the table of routine/environment pairs we visit outside of 309 * request context. 310 */ 311 if (static_calls_made == NULL) { 312 static_calls_made = apr_table_make(x_pool, 16); 313 }; 314} 315 316/* 317 * This routine is used to add a trace of a callback to the list. We're 318 * passed the server record (if available), the request record (if available), 319 * a pointer to our private configuration record (if available) for the 320 * environment to which the callback is supposed to apply, and some text. We 321 * turn this into a textual representation and add it to the tail of the list. 322 * The list can be displayed by the x_handler() routine. 323 * 324 * If the call occurs within a request context (i.e., we're passed a request 325 * record), we put the trace into the request apr_pool_t and attach it to the 326 * request via the notes mechanism. Otherwise, the trace gets added 327 * to the static (non-request-specific) list. 328 * 329 * Note that the r->notes table is only for storing strings; if you need to 330 * maintain per-request data of any other type, you need to use another 331 * mechanism. 332 */ 333 334#define TRACE_NOTE "example-trace" 335 336static void trace_add(server_rec *s, request_rec *r, x_cfg *mconfig, 337 const char *note) 338{ 339 const char *sofar; 340 char *addon; 341 char *where; 342 apr_pool_t *p; 343 const char *trace_copy; 344 345 /* 346 * Make sure our pools and tables are set up - we need 'em. 347 */ 348 setup_module_cells(); 349 /* 350 * Now, if we're in request-context, we use the request pool. 351 */ 352 if (r != NULL) { 353 p = r->pool; 354 if ((trace_copy = apr_table_get(r->notes, TRACE_NOTE)) == NULL) { 355 trace_copy = ""; 356 } 357 } 358 else { 359 /* 360 * We're not in request context, so the trace gets attached to our 361 * module-wide pool. We do the create/destroy every time we're called 362 * in non-request context; this avoids leaking memory in some of 363 * the subsequent calls that allocate memory only once (such as the 364 * key formation below). 365 * 366 * Make a new sub-pool and copy any existing trace to it. Point the 367 * trace cell at the copied value. 368 */ 369 apr_pool_create(&p, x_pool); 370 if (trace != NULL) { 371 trace = apr_pstrdup(p, trace); 372 } 373 /* 374 * Now, if we have a sub-pool from before, nuke it and replace with 375 * the one we just allocated. 376 */ 377 if (x_subpool != NULL) { 378 apr_pool_destroy(x_subpool); 379 } 380 x_subpool = p; 381 trace_copy = trace; 382 } 383 /* 384 * If we weren't passed a configuration record, we can't figure out to 385 * what location this call applies. This only happens for co-routines 386 * that don't operate in a particular directory or server context. If we 387 * got a valid record, extract the location (directory or server) to which 388 * it applies. 389 */ 390 where = (mconfig != NULL) ? mconfig->loc : "nowhere"; 391 where = (where != NULL) ? where : ""; 392 /* 393 * Now, if we're not in request context, see if we've been called with 394 * this particular combination before. The apr_table_t is allocated in the 395 * module's private pool, which doesn't get destroyed. 396 */ 397 if (r == NULL) { 398 char *key; 399 400 key = apr_pstrcat(p, note, ":", where, NULL); 401 if (apr_table_get(static_calls_made, key) != NULL) { 402 /* 403 * Been here, done this. 404 */ 405 return; 406 } 407 else { 408 /* 409 * First time for this combination of routine and environment - 410 * log it so we don't do it again. 411 */ 412 apr_table_set(static_calls_made, key, "been here"); 413 } 414 } 415 addon = apr_pstrcat(p, 416 " <li>\n" 417 " <dl>\n" 418 " <dt><samp>", note, "</samp></dt>\n" 419 " <dd><samp>[", where, "]</samp></dd>\n" 420 " </dl>\n" 421 " </li>\n", 422 NULL); 423 sofar = (trace_copy == NULL) ? "" : trace_copy; 424 trace_copy = apr_pstrcat(p, sofar, addon, NULL); 425 if (r != NULL) { 426 apr_table_set(r->notes, TRACE_NOTE, trace_copy); 427 } 428 else { 429 trace = trace_copy; 430 } 431 /* 432 * You *could* change the following if you wanted to see the calling 433 * sequence reported in the server's error_log, but beware - almost all of 434 * these co-routines are called for every single request, and the impact 435 * on the size (and readability) of the error_log is considerable. 436 */ 437#define EXAMPLE_LOG_EACH 0 438 if (EXAMPLE_LOG_EACH && (s != NULL)) { 439 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_example: %s", note); 440 } 441} 442 443/*--------------------------------------------------------------------------*/ 444/* We prototyped the various syntax for command handlers (routines that */ 445/* are called when the configuration parser detects a directive declared */ 446/* by our module) earlier. Now we actually declare a "real" routine that */ 447/* will be invoked by the parser when our "real" directive is */ 448/* encountered. */ 449/* */ 450/* If a command handler encounters a problem processing the directive, it */ 451/* signals this fact by returning a non-NULL pointer to a string */ 452/* describing the problem. */ 453/* */ 454/* The magic return value DECLINE_CMD is used to deal with directives */ 455/* that might be declared by multiple modules. If the command handler */ 456/* returns NULL, the directive was processed; if it returns DECLINE_CMD, */ 457/* the next module (if any) that declares the directive is given a chance */ 458/* at it. If it returns any other value, it's treated as the text of an */ 459/* error message. */ 460/*--------------------------------------------------------------------------*/ 461/* 462 * Command handler for the NO_ARGS "Example" directive. All we do is mark the 463 * call in the trace log, and flag the applicability of the directive to the 464 * current location in that location's configuration record. 465 */ 466static const char *cmd_example(cmd_parms *cmd, void *mconfig) 467{ 468 x_cfg *cfg = (x_cfg *) mconfig; 469 470 /* 471 * "Example Wuz Here" 472 */ 473 cfg->local = 1; 474 trace_add(cmd->server, NULL, cfg, "cmd_example()"); 475 return NULL; 476} 477 478/*--------------------------------------------------------------------------*/ 479/* */ 480/* Now we declare our content handlers, which are invoked when the server */ 481/* encounters a document which our module is supposed to have a chance to */ 482/* see. (See mod_mime's SetHandler and AddHandler directives, and the */ 483/* mod_info and mod_status examples, for more details.) */ 484/* */ 485/* Since content handlers are dumping data directly into the connection */ 486/* (using the r*() routines, such as rputs() and rprintf()) without */ 487/* intervention by other parts of the server, they need to make */ 488/* sure any accumulated HTTP headers are sent first. This is done by */ 489/* calling send_http_header(). Otherwise, no header will be sent at all, */ 490/* and the output sent to the client will actually be HTTP-uncompliant. */ 491/*--------------------------------------------------------------------------*/ 492/* 493 * Sample content handler. All this does is display the call list that has 494 * been built up so far. 495 * 496 * The return value instructs the caller concerning what happened and what to 497 * do next: 498 * OK ("we did our thing") 499 * DECLINED ("this isn't something with which we want to get involved") 500 * HTTP_mumble ("an error status should be reported") 501 */ 502static int x_handler(request_rec *r) 503{ 504 x_cfg *dcfg; 505 506 if (strcmp(r->handler, "example-handler")) { 507 return DECLINED; 508 } 509 510 dcfg = our_dconfig(r); 511 trace_add(r->server, r, dcfg, "x_handler()"); 512 /* 513 * We're about to start sending content, so we need to force the HTTP 514 * headers to be sent at this point. Otherwise, no headers will be sent 515 * at all. We can set any we like first, of course. **NOTE** Here's 516 * where you set the "Content-type" header, and you do so by putting it in 517 * r->content_type, *not* r->headers_out("Content-type"). If you don't 518 * set it, it will be filled in with the server's default type (typically 519 * "text/plain"). You *must* also ensure that r->content_type is lower 520 * case. 521 * 522 * We also need to start a timer so the server can know if the connexion 523 * is broken. 524 */ 525 ap_set_content_type(r, "text/html"); 526 /* 527 * If we're only supposed to send header information (HEAD request), we're 528 * already there. 529 */ 530 if (r->header_only) { 531 return OK; 532 } 533 534 /* 535 * Now send our actual output. Since we tagged this as being 536 * "text/html", we need to embed any HTML. 537 */ 538 ap_rputs(DOCTYPE_HTML_3_2, r); 539 ap_rputs("<HTML>\n", r); 540 ap_rputs(" <HEAD>\n", r); 541 ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r); 542 ap_rputs(" </TITLE>\n", r); 543 ap_rputs(" </HEAD>\n", r); 544 ap_rputs(" <BODY>\n", r); 545 ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); 546 ap_rputs(" </H1>\n", r); 547 ap_rputs(" <P>\n", r); 548 ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", 549 ap_get_server_banner()); 550 ap_rputs(" <BR>\n", r); 551 ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); 552 ap_rputs(" </P>\n", r);; 553 ap_rputs(" <P>\n", r); 554 ap_rputs(" The format for the callback trace is:\n", r); 555 ap_rputs(" </P>\n", r); 556 ap_rputs(" <DL>\n", r); 557 ap_rputs(" <DT><EM>n</EM>.<SAMP><routine-name>", r); 558 ap_rputs("(<routine-data>)</SAMP>\n", r); 559 ap_rputs(" </DT>\n", r); 560 ap_rputs(" <DD><SAMP>[<applies-to>]</SAMP>\n", r); 561 ap_rputs(" </DD>\n", r); 562 ap_rputs(" </DL>\n", r); 563 ap_rputs(" <P>\n", r); 564 ap_rputs(" The <SAMP><routine-data></SAMP> is supplied by\n", r); 565 ap_rputs(" the routine when it requests the trace,\n", r); 566 ap_rputs(" and the <SAMP><applies-to></SAMP> is extracted\n", r); 567 ap_rputs(" from the configuration record at the time of the trace.\n", r); 568 ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r); 569 ap_rputs(" (blank means the main or default server, otherwise it's\n", r); 570 ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r); 571 ap_rputs(" indicates a location in the URL or filesystem\n", r); 572 ap_rputs(" namespace.\n", r); 573 ap_rputs(" </P>\n", r); 574 ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n", 575 trace); 576 ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r); 577 ap_rprintf(r, " <OL>\n%s </OL>\n", apr_table_get(r->notes, TRACE_NOTE)); 578 ap_rputs(" <H2>Environment for <EM>this</EM> call:</H2>\n", r); 579 ap_rputs(" <UL>\n", r); 580 ap_rprintf(r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc); 581 ap_rprintf(r, " <LI>\"Example\" directive declared here: %s\n </LI>\n", 582 (dcfg->local ? "YES" : "NO")); 583 ap_rprintf(r, " <LI>\"Example\" inherited: %s\n </LI>\n", 584 (dcfg->congenital ? "YES" : "NO")); 585 ap_rputs(" </UL>\n", r); 586 ap_rputs(" </BODY>\n", r); 587 ap_rputs("</HTML>\n", r); 588 /* 589 * We're all done, so cancel the timeout we set. Since this is probably 590 * the end of the request we *could* assume this would be done during 591 * post-processing - but it's possible that another handler might be 592 * called and inherit our outstanding timer. Not good; to each its own. 593 */ 594 /* 595 * We did what we wanted to do, so tell the rest of the server we 596 * succeeded. 597 */ 598 return OK; 599} 600 601/*--------------------------------------------------------------------------*/ 602/* */ 603/* Now let's declare routines for each of the callback phase in order. */ 604/* (That's the order in which they're listed in the callback list, *not */ 605/* the order in which the server calls them! See the command_rec */ 606/* declaration near the bottom of this file.) Note that these may be */ 607/* called for situations that don't relate primarily to our function - in */ 608/* other words, the fixup handler shouldn't assume that the request has */ 609/* to do with "example" stuff. */ 610/* */ 611/* With the exception of the content handler, all of our routines will be */ 612/* called for each request, unless an earlier handler from another module */ 613/* aborted the sequence. */ 614/* */ 615/* Handlers that are declared as "int" can return the following: */ 616/* */ 617/* OK Handler accepted the request and did its thing with it. */ 618/* DECLINED Handler took no action. */ 619/* HTTP_mumble Handler looked at request and found it wanting. */ 620/* */ 621/* What the server does after calling a module handler depends upon the */ 622/* handler's return value. In all cases, if the handler returns */ 623/* DECLINED, the server will continue to the next module with an handler */ 624/* for the current phase. However, if the handler return a non-OK, */ 625/* non-DECLINED status, the server aborts the request right there. If */ 626/* the handler returns OK, the server's next action is phase-specific; */ 627/* see the individual handler comments below for details. */ 628/* */ 629/*--------------------------------------------------------------------------*/ 630/* 631 * This function is called during server initialisation. Any information 632 * that needs to be recorded must be in static cells, since there's no 633 * configuration record. 634 * 635 * There is no return value. 636 */ 637 638/* 639 * This function is called when an heavy-weight process (such as a child) is 640 * being run down or destroyed. As with the child initialisation function, 641 * any information that needs to be recorded must be in static cells, since 642 * there's no configuration record. 643 * 644 * There is no return value. 645 */ 646 647/* 648 * This function is called during server initialisation when an heavy-weight 649 * process (such as a child) is being initialised. As with the 650 * module initialisation function, any information that needs to be recorded 651 * must be in static cells, since there's no configuration record. 652 * 653 * There is no return value. 654 */ 655 656/* 657 * This function gets called to create a per-directory configuration 658 * record. This will be called for the "default" server environment, and for 659 * each directory for which the parser finds any of our directives applicable. 660 * If a directory doesn't have any of our directives involved (i.e., they 661 * aren't in the .htaccess file, or a <Location>, <Directory>, or related 662 * block), this routine will *not* be called - the configuration for the 663 * closest ancestor is used. 664 * 665 * The return value is a pointer to the created module-specific 666 * structure. 667 */ 668static void *x_create_dir_config(apr_pool_t *p, char *dirspec) 669{ 670 x_cfg *cfg; 671 char *dname = dirspec; 672 673 /* 674 * Allocate the space for our record from the pool supplied. 675 */ 676 cfg = (x_cfg *) apr_pcalloc(p, sizeof(x_cfg)); 677 /* 678 * Now fill in the defaults. If there are any `parent' configuration 679 * records, they'll get merged as part of a separate callback. 680 */ 681 cfg->local = 0; 682 cfg->congenital = 0; 683 cfg->cmode = CONFIG_MODE_DIRECTORY; 684 /* 685 * Finally, add our trace to the callback list. 686 */ 687 dname = (dname != NULL) ? dname : ""; 688 cfg->loc = apr_pstrcat(p, "DIR(", dname, ")", NULL); 689 trace_add(NULL, NULL, cfg, "x_create_dir_config()"); 690 return (void *) cfg; 691} 692 693/* 694 * This function gets called to merge two per-directory configuration 695 * records. This is typically done to cope with things like .htaccess files 696 * or <Location> directives for directories that are beneath one for which a 697 * configuration record was already created. The routine has the 698 * responsibility of creating a new record and merging the contents of the 699 * other two into it appropriately. If the module doesn't declare a merge 700 * routine, the record for the closest ancestor location (that has one) is 701 * used exclusively. 702 * 703 * The routine MUST NOT modify any of its arguments! 704 * 705 * The return value is a pointer to the created module-specific structure 706 * containing the merged values. 707 */ 708static void *x_merge_dir_config(apr_pool_t *p, void *parent_conf, 709 void *newloc_conf) 710{ 711 712 x_cfg *merged_config = (x_cfg *) apr_pcalloc(p, sizeof(x_cfg)); 713 x_cfg *pconf = (x_cfg *) parent_conf; 714 x_cfg *nconf = (x_cfg *) newloc_conf; 715 char *note; 716 717 /* 718 * Some things get copied directly from the more-specific record, rather 719 * than getting merged. 720 */ 721 merged_config->local = nconf->local; 722 merged_config->loc = apr_pstrdup(p, nconf->loc); 723 /* 724 * Others, like the setting of the `congenital' flag, get ORed in. The 725 * setting of that particular flag, for instance, is TRUE if it was ever 726 * true anywhere in the upstream configuration. 727 */ 728 merged_config->congenital = (pconf->congenital | pconf->local); 729 /* 730 * If we're merging records for two different types of environment (server 731 * and directory), mark the new record appropriately. Otherwise, inherit 732 * the current value. 733 */ 734 merged_config->cmode = 735 (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO; 736 /* 737 * Now just record our being called in the trace list. Include the 738 * locations we were asked to merge. 739 */ 740 note = apr_pstrcat(p, "x_merge_dir_config(\"", pconf->loc, "\",\"", 741 nconf->loc, "\")", NULL); 742 trace_add(NULL, NULL, merged_config, note); 743 return (void *) merged_config; 744} 745 746/* 747 * This function gets called to create a per-server configuration 748 * record. It will always be called for the "default" server. 749 * 750 * The return value is a pointer to the created module-specific 751 * structure. 752 */ 753static void *x_create_server_config(apr_pool_t *p, server_rec *s) 754{ 755 756 x_cfg *cfg; 757 char *sname = s->server_hostname; 758 759 /* 760 * As with the x_create_dir_config() reoutine, we allocate and fill 761 * in an empty record. 762 */ 763 cfg = (x_cfg *) apr_pcalloc(p, sizeof(x_cfg)); 764 cfg->local = 0; 765 cfg->congenital = 0; 766 cfg->cmode = CONFIG_MODE_SERVER; 767 /* 768 * Note that we were called in the trace list. 769 */ 770 sname = (sname != NULL) ? sname : ""; 771 cfg->loc = apr_pstrcat(p, "SVR(", sname, ")", NULL); 772 trace_add(s, NULL, cfg, "x_create_server_config()"); 773 return (void *) cfg; 774} 775 776/* 777 * This function gets called to merge two per-server configuration 778 * records. This is typically done to cope with things like virtual hosts and 779 * the default server configuration The routine has the responsibility of 780 * creating a new record and merging the contents of the other two into it 781 * appropriately. If the module doesn't declare a merge routine, the more 782 * specific existing record is used exclusively. 783 * 784 * The routine MUST NOT modify any of its arguments! 785 * 786 * The return value is a pointer to the created module-specific structure 787 * containing the merged values. 788 */ 789static void *x_merge_server_config(apr_pool_t *p, void *server1_conf, 790 void *server2_conf) 791{ 792 793 x_cfg *merged_config = (x_cfg *) apr_pcalloc(p, sizeof(x_cfg)); 794 x_cfg *s1conf = (x_cfg *) server1_conf; 795 x_cfg *s2conf = (x_cfg *) server2_conf; 796 char *note; 797 798 /* 799 * Our inheritance rules are our own, and part of our module's semantics. 800 * Basically, just note whence we came. 801 */ 802 merged_config->cmode = 803 (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO; 804 merged_config->local = s2conf->local; 805 merged_config->congenital = (s1conf->congenital | s1conf->local); 806 merged_config->loc = apr_pstrdup(p, s2conf->loc); 807 /* 808 * Trace our call, including what we were asked to merge. 809 */ 810 note = apr_pstrcat(p, "x_merge_server_config(\"", s1conf->loc, "\",\"", 811 s2conf->loc, "\")", NULL); 812 trace_add(NULL, NULL, merged_config, note); 813 return (void *) merged_config; 814} 815 816/* 817 * This routine is called before the server processes the configuration 818 * files. There is no return value. 819 */ 820static int x_pre_config(apr_pool_t *pconf, apr_pool_t *plog, 821 apr_pool_t *ptemp) 822{ 823 /* 824 * Log the call and exit. 825 */ 826 trace_add(NULL, NULL, NULL, "x_pre_config()"); 827 828 return OK; 829} 830 831/* 832 * This routine is called to perform any module-specific fixing of header 833 * fields, et cetera. It is invoked just before any content-handler. 834 * 835 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 836 * server will still call any remaining modules with an handler for this 837 * phase. 838 */ 839static int x_post_config(apr_pool_t *pconf, apr_pool_t *plog, 840 apr_pool_t *ptemp, server_rec *s) 841{ 842 /* 843 * Log the call and exit. 844 */ 845 trace_add(NULL, NULL, NULL, "x_post_config()"); 846 return OK; 847} 848 849/* 850 * This routine is called to perform any module-specific log file 851 * openings. It is invoked just before the post_config phase 852 * 853 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 854 * server will still call any remaining modules with an handler for this 855 * phase. 856 */ 857static int x_open_logs(apr_pool_t *pconf, apr_pool_t *plog, 858 apr_pool_t *ptemp, server_rec *s) 859{ 860 /* 861 * Log the call and exit. 862 */ 863 trace_add(s, NULL, NULL, "x_open_logs()"); 864 return OK; 865} 866 867/* 868 * All our process-death routine does is add its trace to the log. 869 */ 870static apr_status_t x_child_exit(void *data) 871{ 872 char *note; 873 server_rec *s = data; 874 char *sname = s->server_hostname; 875 876 /* 877 * The arbitrary text we add to our trace entry indicates for which server 878 * we're being called. 879 */ 880 sname = (sname != NULL) ? sname : ""; 881 note = apr_pstrcat(s->process->pool, "x_child_exit(", sname, ")", NULL); 882 trace_add(s, NULL, NULL, note); 883 return APR_SUCCESS; 884} 885 886/* 887 * All our process initialiser does is add its trace to the log. 888 */ 889static void x_child_init(apr_pool_t *p, server_rec *s) 890{ 891 char *note; 892 char *sname = s->server_hostname; 893 894 /* 895 * Set up any module cells that ought to be initialised. 896 */ 897 setup_module_cells(); 898 /* 899 * The arbitrary text we add to our trace entry indicates for which server 900 * we're being called. 901 */ 902 sname = (sname != NULL) ? sname : ""; 903 note = apr_pstrcat(p, "x_child_init(", sname, ")", NULL); 904 trace_add(s, NULL, NULL, note); 905 906 apr_pool_cleanup_register(p, s, x_child_exit, x_child_exit); 907} 908 909/* 910 * XXX: This routine is called XXX 911 * 912 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 913 * server will still call any remaining modules with an handler for this 914 * phase. 915 */ 916#if 0 917static const char *x_http_scheme(const request_rec *r) 918{ 919 x_cfg *cfg; 920 921 cfg = our_dconfig(r); 922 /* 923 * Log the call and exit. 924 */ 925 trace_add(r->server, NULL, cfg, "x_http_scheme()"); 926 return "example"; 927} 928 929/* 930 * XXX: This routine is called XXX 931 * 932 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 933 * server will still call any remaining modules with an handler for this 934 * phase. 935 */ 936static apr_port_t x_default_port(const request_rec *r) 937{ 938 x_cfg *cfg; 939 940 cfg = our_dconfig(r); 941 /* 942 * Log the call and exit. 943 */ 944 trace_add(r->server, NULL, cfg, "x_default_port()"); 945 return 80; 946} 947#endif /*0*/ 948 949/* 950 * XXX: This routine is called XXX 951 * 952 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 953 * server will still call any remaining modules with an handler for this 954 * phase. 955 */ 956static void x_insert_filter(request_rec *r) 957{ 958 x_cfg *cfg; 959 960 cfg = our_dconfig(r); 961 /* 962 * Log the call and exit. 963 */ 964 trace_add(r->server, NULL, cfg, "x_insert_filter()"); 965} 966 967/* 968 * XXX: This routine is called XXX 969 * 970 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 971 * server will still call any remaining modules with an handler for this 972 * phase. 973 */ 974static int x_quick_handler(request_rec *r, int lookup_uri) 975{ 976 x_cfg *cfg; 977 978 cfg = our_dconfig(r); 979 /* 980 * Log the call and exit. 981 */ 982 trace_add(r->server, NULL, cfg, "x_quick_handler()"); 983 return DECLINED; 984} 985 986/* 987 * This routine is called just after the server accepts the connection, 988 * but before it is handed off to a protocol module to be served. The point 989 * of this hook is to allow modules an opportunity to modify the connection 990 * as soon as possible. The core server uses this phase to setup the 991 * connection record based on the type of connection that is being used. 992 * 993 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 994 * server will still call any remaining modules with an handler for this 995 * phase. 996 */ 997static int x_pre_connection(conn_rec *c, void *csd) 998{ 999 x_cfg *cfg; 1000 1001 cfg = our_cconfig(c); 1002#if 0 1003 /* 1004 * Log the call and exit. 1005 */ 1006 trace_add(r->server, NULL, cfg, "x_pre_connection()"); 1007#endif 1008 return OK; 1009} 1010 1011/* This routine is used to actually process the connection that was received. 1012 * Only protocol modules should implement this hook, as it gives them an 1013 * opportunity to replace the standard HTTP processing with processing for 1014 * some other protocol. Both echo and POP3 modules are available as 1015 * examples. 1016 * 1017 * The return VALUE is OK, DECLINED, or HTTP_mumble. If we return OK, no 1018 * further modules are called for this phase. 1019 */ 1020static int x_process_connection(conn_rec *c) 1021{ 1022 return DECLINED; 1023} 1024 1025/* 1026 * This routine is called after the request has been read but before any other 1027 * phases have been processed. This allows us to make decisions based upon 1028 * the input header fields. 1029 * 1030 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no 1031 * further modules are called for this phase. 1032 */ 1033static int x_post_read_request(request_rec *r) 1034{ 1035 x_cfg *cfg; 1036 1037 cfg = our_dconfig(r); 1038 /* 1039 * We don't actually *do* anything here, except note the fact that we were 1040 * called. 1041 */ 1042 trace_add(r->server, r, cfg, "x_post_read_request()"); 1043 return DECLINED; 1044} 1045 1046/* 1047 * This routine gives our module an opportunity to translate the URI into an 1048 * actual filename. If we don't do anything special, the server's default 1049 * rules (Alias directives and the like) will continue to be followed. 1050 * 1051 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no 1052 * further modules are called for this phase. 1053 */ 1054static int x_translate_handler(request_rec *r) 1055{ 1056 1057 x_cfg *cfg; 1058 1059 cfg = our_dconfig(r); 1060 /* 1061 * We don't actually *do* anything here, except note the fact that we were 1062 * called. 1063 */ 1064 trace_add(r->server, r, cfg, "x_translate_handler()"); 1065 return DECLINED; 1066} 1067 1068/* 1069 * This routine maps r->filename to a physical file on disk. Useful for 1070 * overriding default core behavior, including skipping mapping for 1071 * requests that are not file based. 1072 * 1073 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no 1074 * further modules are called for this phase. 1075 */ 1076static int x_map_to_storage_handler(request_rec *r) 1077{ 1078 1079 x_cfg *cfg; 1080 1081 cfg = our_dconfig(r); 1082 /* 1083 * We don't actually *do* anything here, except note the fact that we were 1084 * called. 1085 */ 1086 trace_add(r->server, r, cfg, "x_map_to_storage_handler()"); 1087 return DECLINED; 1088} 1089 1090/* 1091 * this routine gives our module another chance to examine the request 1092 * headers and to take special action. This is the first phase whose 1093 * hooks' configuration directives can appear inside the <Directory> 1094 * and similar sections, because at this stage the URI has been mapped 1095 * to the filename. For example this phase can be used to block evil 1096 * clients, while little resources were wasted on these. 1097 * 1098 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, 1099 * the server will still call any remaining modules with an handler 1100 * for this phase. 1101 */ 1102static int x_header_parser_handler(request_rec *r) 1103{ 1104 1105 x_cfg *cfg; 1106 1107 cfg = our_dconfig(r); 1108 /* 1109 * We don't actually *do* anything here, except note the fact that we were 1110 * called. 1111 */ 1112 trace_add(r->server, r, cfg, "header_parser_handler()"); 1113 return DECLINED; 1114} 1115 1116 1117/* 1118 * This routine is called to check the authentication information sent with 1119 * the request (such as looking up the user in a database and verifying that 1120 * the [encrypted] password sent matches the one in the database). 1121 * 1122 * The return value is OK, DECLINED, or some HTTP_mumble error (typically 1123 * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance 1124 * at the request during this phase. 1125 */ 1126static int x_check_user_id(request_rec *r) 1127{ 1128 1129 x_cfg *cfg; 1130 1131 cfg = our_dconfig(r); 1132 /* 1133 * Don't do anything except log the call. 1134 */ 1135 trace_add(r->server, r, cfg, "x_check_user_id()"); 1136 return DECLINED; 1137} 1138 1139/* 1140 * This routine is called to check to see if the resource being requested 1141 * requires authorisation. 1142 * 1143 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no 1144 * other modules are called during this phase. 1145 * 1146 * If *all* modules return DECLINED, the request is aborted with a server 1147 * error. 1148 */ 1149static int x_auth_checker(request_rec *r) 1150{ 1151 1152 x_cfg *cfg; 1153 1154 cfg = our_dconfig(r); 1155 /* 1156 * Log the call and return OK, or access will be denied (even though we 1157 * didn't actually do anything). 1158 */ 1159 trace_add(r->server, r, cfg, "x_auth_checker()"); 1160 return DECLINED; 1161} 1162 1163/* 1164 * This routine is called to check for any module-specific restrictions placed 1165 * upon the requested resource. (See the mod_access module for an example.) 1166 * 1167 * The return value is OK, DECLINED, or HTTP_mumble. All modules with an 1168 * handler for this phase are called regardless of whether their predecessors 1169 * return OK or DECLINED. The first one to return any other status, however, 1170 * will abort the sequence (and the request) as usual. 1171 */ 1172static int x_access_checker(request_rec *r) 1173{ 1174 1175 x_cfg *cfg; 1176 1177 cfg = our_dconfig(r); 1178 trace_add(r->server, r, cfg, "x_access_checker()"); 1179 return DECLINED; 1180} 1181 1182/* 1183 * This routine is called to determine and/or set the various document type 1184 * information bits, like Content-type (via r->content_type), language, et 1185 * cetera. 1186 * 1187 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no 1188 * further modules are given a chance at the request for this phase. 1189 */ 1190static int x_type_checker(request_rec *r) 1191{ 1192 1193 x_cfg *cfg; 1194 1195 cfg = our_dconfig(r); 1196 /* 1197 * Log the call, but don't do anything else - and report truthfully that 1198 * we didn't do anything. 1199 */ 1200 trace_add(r->server, r, cfg, "x_type_checker()"); 1201 return DECLINED; 1202} 1203 1204/* 1205 * This routine is called to perform any module-specific fixing of header 1206 * fields, et cetera. It is invoked just before any content-handler. 1207 * 1208 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the 1209 * server will still call any remaining modules with an handler for this 1210 * phase. 1211 */ 1212static int x_fixer_upper(request_rec *r) 1213{ 1214 1215 x_cfg *cfg; 1216 1217 cfg = our_dconfig(r); 1218 /* 1219 * Log the call and exit. 1220 */ 1221 trace_add(r->server, r, cfg, "x_fixer_upper()"); 1222 return OK; 1223} 1224 1225/* 1226 * This routine is called to perform any module-specific logging activities 1227 * over and above the normal server things. 1228 * 1229 * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any 1230 * remaining modules with an handler for this phase will still be called. 1231 */ 1232static int x_logger(request_rec *r) 1233{ 1234 1235 x_cfg *cfg; 1236 1237 cfg = our_dconfig(r); 1238 trace_add(r->server, r, cfg, "x_logger()"); 1239 return DECLINED; 1240} 1241 1242/*--------------------------------------------------------------------------*/ 1243/* */ 1244/* Which functions are responsible for which hooks in the server. */ 1245/* */ 1246/*--------------------------------------------------------------------------*/ 1247/* 1248 * Each function our module provides to handle a particular hook is 1249 * specified here. The functions are registered using 1250 * ap_hook_foo(name, predecessors, successors, position) 1251 * where foo is the name of the hook. 1252 * 1253 * The args are as follows: 1254 * name -> the name of the function to call. 1255 * predecessors -> a list of modules whose calls to this hook must be 1256 * invoked before this module. 1257 * successors -> a list of modules whose calls to this hook must be 1258 * invoked after this module. 1259 * position -> The relative position of this module. One of 1260 * APR_HOOK_FIRST, APR_HOOK_MIDDLE, or APR_HOOK_LAST. 1261 * Most modules will use APR_HOOK_MIDDLE. If multiple 1262 * modules use the same relative position, Apache will 1263 * determine which to call first. 1264 * If your module relies on another module to run first, 1265 * or another module running after yours, use the 1266 * predecessors and/or successors. 1267 * 1268 * The number in brackets indicates the order in which the routine is called 1269 * during request processing. Note that not all routines are necessarily 1270 * called (such as if a resource doesn't have access restrictions). 1271 * The actual delivery of content to the browser [9] is not handled by 1272 * a hook; see the handler declarations below. 1273 */ 1274static void x_register_hooks(apr_pool_t *p) 1275{ 1276 ap_hook_pre_config(x_pre_config, NULL, NULL, APR_HOOK_MIDDLE); 1277 ap_hook_post_config(x_post_config, NULL, NULL, APR_HOOK_MIDDLE); 1278 ap_hook_open_logs(x_open_logs, NULL, NULL, APR_HOOK_MIDDLE); 1279 ap_hook_child_init(x_child_init, NULL, NULL, APR_HOOK_MIDDLE); 1280 ap_hook_handler(x_handler, NULL, NULL, APR_HOOK_MIDDLE); 1281 ap_hook_quick_handler(x_quick_handler, NULL, NULL, APR_HOOK_MIDDLE); 1282 ap_hook_pre_connection(x_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); 1283 ap_hook_process_connection(x_process_connection, NULL, NULL, APR_HOOK_MIDDLE); 1284 /* [1] post read_request handling */ 1285 ap_hook_post_read_request(x_post_read_request, NULL, NULL, 1286 APR_HOOK_MIDDLE); 1287 ap_hook_log_transaction(x_logger, NULL, NULL, APR_HOOK_MIDDLE); 1288#if 0 1289 ap_hook_http_scheme(x_http_scheme, NULL, NULL, APR_HOOK_MIDDLE); 1290 ap_hook_default_port(x_default_port, NULL, NULL, APR_HOOK_MIDDLE); 1291#endif 1292 ap_hook_translate_name(x_translate_handler, NULL, NULL, APR_HOOK_MIDDLE); 1293 ap_hook_map_to_storage(x_map_to_storage_handler, NULL,NULL, APR_HOOK_MIDDLE); 1294 ap_hook_header_parser(x_header_parser_handler, NULL, NULL, APR_HOOK_MIDDLE); 1295 ap_hook_check_user_id(x_check_user_id, NULL, NULL, APR_HOOK_MIDDLE); 1296 ap_hook_fixups(x_fixer_upper, NULL, NULL, APR_HOOK_MIDDLE); 1297 ap_hook_type_checker(x_type_checker, NULL, NULL, APR_HOOK_MIDDLE); 1298 ap_hook_access_checker(x_access_checker, NULL, NULL, APR_HOOK_MIDDLE); 1299 ap_hook_auth_checker(x_auth_checker, NULL, NULL, APR_HOOK_MIDDLE); 1300 ap_hook_insert_filter(x_insert_filter, NULL, NULL, APR_HOOK_MIDDLE); 1301} 1302 1303/*--------------------------------------------------------------------------*/ 1304/* */ 1305/* All of the routines have been declared now. Here's the list of */ 1306/* directives specific to our module, and information about where they */ 1307/* may appear and how the command parser should pass them to us for */ 1308/* processing. Note that care must be taken to ensure that there are NO */ 1309/* collisions of directive names between modules. */ 1310/* */ 1311/*--------------------------------------------------------------------------*/ 1312/* 1313 * List of directives specific to our module. 1314 */ 1315static const command_rec x_cmds[] = 1316{ 1317 AP_INIT_NO_ARGS( 1318 "Example", /* directive name */ 1319 cmd_example, /* config action routine */ 1320 NULL, /* argument to include in call */ 1321 OR_OPTIONS, /* where available */ 1322 "Example directive - no arguments" /* directive description */ 1323 ), 1324 {NULL} 1325}; 1326/*--------------------------------------------------------------------------*/ 1327/* */ 1328/* Finally, the list of callback routines and data structures that provide */ 1329/* the static hooks into our module from the other parts of the server. */ 1330/* */ 1331/*--------------------------------------------------------------------------*/ 1332/* 1333 * Module definition for configuration. If a particular callback is not 1334 * needed, replace its routine name below with the word NULL. 1335 */ 1336module AP_MODULE_DECLARE_DATA example_module = 1337{ 1338 STANDARD20_MODULE_STUFF, 1339 x_create_dir_config, /* per-directory config creator */ 1340 x_merge_dir_config, /* dir config merger */ 1341 x_create_server_config, /* server config creator */ 1342 x_merge_server_config, /* server config merger */ 1343 x_cmds, /* command table */ 1344 x_register_hooks, /* set up other request processing hooks */ 1345}; 1346