Annotation of parser3/src/targets/apache13/modules/extra/mod_parser3.C, revision 1.1.2.1

1.1.2.1 ! paf         1: /* ====================================================================
        !             2:  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
        !             3:  *
        !             4:  * Redistribution and use in source and binary forms, with or without
        !             5:  * modification, are permitted provided that the following conditions
        !             6:  * are met:
        !             7:  *
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer. 
        !            10:  *
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in
        !            13:  *    the documentation and/or other materials provided with the
        !            14:  *    distribution.
        !            15:  *
        !            16:  * 3. All advertising materials mentioning features or use of this
        !            17:  *    software must display the following acknowledgment:
        !            18:  *    "This product includes software developed by the Apache Group
        !            19:  *    for use in the Apache HTTP server project (http://www.apache.org/)."
        !            20:  *
        !            21:  * 4. The names "Apache Server" and "Apache Group" must not be used to
        !            22:  *    endorse or promote products derived from this software without
        !            23:  *    prior written permission. For written permission, please contact
        !            24:  *    apache@apache.org.
        !            25:  *
        !            26:  * 5. Products derived from this software may not be called "Apache"
        !            27:  *    nor may "Apache" appear in their names without prior written
        !            28:  *    permission of the Apache Group.
        !            29:  *
        !            30:  * 6. Redistributions of any form whatsoever must retain the following
        !            31:  *    acknowledgment:
        !            32:  *    "This product includes software developed by the Apache Group
        !            33:  *    for use in the Apache HTTP server project (http://www.apache.org/)."
        !            34:  *
        !            35:  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
        !            36:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            37:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            38:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
        !            39:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            40:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            41:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        !            42:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            44:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            45:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
        !            46:  * OF THE POSSIBILITY OF SUCH DAMAGE.
        !            47:  * ====================================================================
        !            48:  *
        !            49:  * This software consists of voluntary contributions made by many
        !            50:  * individuals on behalf of the Apache Group and was originally based
        !            51:  * on public domain software written at the National Center for
        !            52:  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
        !            53:  * For more information on the Apache Group and the Apache HTTP server
        !            54:  * project, please see <http://www.apache.org/>.
        !            55:  *
        !            56:  */
        !            57: 
        !            58: /* 
        !            59:  * Apache example module.  Provide demonstrations of how modules do things.
        !            60:  *
        !            61:  */
        !            62: 
        !            63: #include "httpd.h"
        !            64: #include "http_config.h"
        !            65: #include "http_core.h"
        !            66: #include "http_log.h"
        !            67: #include "http_main.h"
        !            68: #include "http_protocol.h"
        !            69: #include "util_script.h"
        !            70: 
        !            71: #include <stdio.h>
        !            72: 
        !            73: /*--------------------------------------------------------------------------*/
        !            74: /*                                                                          */
        !            75: /* Data declarations.                                                       */
        !            76: /*                                                                          */
        !            77: /* Here are the static cells and structure declarations private to our      */
        !            78: /* module.                                                                  */
        !            79: /*                                                                          */
        !            80: /*--------------------------------------------------------------------------*/
        !            81: 
        !            82: /*
        !            83:  * Sample configuration record.  Used for both per-directory and per-server
        !            84:  * configuration data.
        !            85:  *
        !            86:  * It's perfectly reasonable to have two different structures for the two
        !            87:  * different environments.  The same command handlers will be called for
        !            88:  * both, though, so the handlers need to be able to tell them apart.  One
        !            89:  * possibility is for both structures to start with an int which is zero for
        !            90:  * one and 1 for the other.
        !            91:  *
        !            92:  * Note that while the per-directory and per-server configuration records are
        !            93:  * available to most of the module handlers, they should be treated as
        !            94:  * READ-ONLY by all except the command and merge handlers.  Sometimes handlers
        !            95:  * are handed a record that applies to the current location by implication or
        !            96:  * inheritance, and modifying it will change the rules for other locations.
        !            97:  */
        !            98: typedef struct excfg {
        !            99:     int cmode;                  /* Environment to which record applies (directory,
        !           100:                                  * server, or combination).
        !           101:                                  */
        !           102: #define CONFIG_MODE_SERVER 1
        !           103: #define CONFIG_MODE_DIRECTORY 2
        !           104: #define CONFIG_MODE_COMBO 3     /* Shouldn't ever happen. */
        !           105:     int local;                  /* Boolean: "Example" directive declared here? */
        !           106:     int congenital;             /* Boolean: did we inherit an "Example"? */
        !           107:     char *trace;                /* Pointer to trace string. */
        !           108:     char *loc;                  /* Location to which this record applies. */
        !           109: } excfg;
        !           110: 
        !           111: /*
        !           112:  * Let's set up a module-local static cell to point to the accreting callback
        !           113:  * trace.  As each API callback is made to us, we'll tack on the particulars
        !           114:  * to whatever we've already recorded.  To avoid massive memory bloat as
        !           115:  * directories are walked again and again, we record the routine/environment
        !           116:  * the first time (non-request context only), and ignore subsequent calls for
        !           117:  * the same routine/environment.
        !           118:  */
        !           119: static const char *trace = NULL;
        !           120: static table *static_calls_made = NULL;
        !           121: 
        !           122: /*
        !           123:  * To avoid leaking memory from pools other than the per-request one, we
        !           124:  * allocate a module-private pool, and then use a sub-pool of that which gets
        !           125:  * freed each time we modify the trace.  That way previous layers of trace
        !           126:  * data don't get lost.
        !           127:  */
        !           128: static pool *example_pool = NULL;
        !           129: static pool *example_subpool = NULL;
        !           130: 
        !           131: /*
        !           132:  * Declare ourselves so the configuration routines can find and know us.
        !           133:  * We'll fill it in at the end of the module.
        !           134:  */
        !           135: module MODULE_VAR_EXPORT example_module;
        !           136: 
        !           137: /*--------------------------------------------------------------------------*/
        !           138: /*                                                                          */
        !           139: /* The following pseudo-prototype declarations illustrate the parameters    */
        !           140: /* passed to command handlers for the different types of directive          */
        !           141: /* syntax.  If an argument was specified in the directive definition        */
        !           142: /* (look for "command_rec" below), it's available to the command handler    */
        !           143: /* via the (void *) info field in the cmd_parms argument passed to the      */
        !           144: /* handler (cmd->info for the examples below).                              */
        !           145: /*                                                                          */
        !           146: /*--------------------------------------------------------------------------*/
        !           147: 
        !           148: /*
        !           149:  * Command handler for a NO_ARGS directive.
        !           150:  *
        !           151:  * static const char *handle_NO_ARGS(cmd_parms *cmd, void *mconfig);
        !           152:  */
        !           153: 
        !           154: /*
        !           155:  * Command handler for a RAW_ARGS directive.  The "args" argument is the text
        !           156:  * of the commandline following the directive itself.
        !           157:  *
        !           158:  * static const char *handle_RAW_ARGS(cmd_parms *cmd, void *mconfig,
        !           159:  *                                    const char *args);
        !           160:  */
        !           161: 
        !           162: /*
        !           163:  * Command handler for a FLAG directive.  The single parameter is passed in
        !           164:  * "bool", which is either zero or not for Off or On respectively.
        !           165:  *
        !           166:  * static const char *handle_FLAG(cmd_parms *cmd, void *mconfig, int bool);
        !           167:  */
        !           168: 
        !           169: /*
        !           170:  * Command handler for a TAKE1 directive.  The single parameter is passed in
        !           171:  * "word1".
        !           172:  *
        !           173:  * static const char *handle_TAKE1(cmd_parms *cmd, void *mconfig,
        !           174:  *                                 char *word1);
        !           175:  */
        !           176: 
        !           177: /*
        !           178:  * Command handler for a TAKE2 directive.  TAKE2 commands must always have
        !           179:  * exactly two arguments.
        !           180:  *
        !           181:  * static const char *handle_TAKE2(cmd_parms *cmd, void *mconfig,
        !           182:  *                                 char *word1, char *word2);
        !           183:  */
        !           184: 
        !           185: /*
        !           186:  * Command handler for a TAKE3 directive.  Like TAKE2, these must have exactly
        !           187:  * three arguments, or the parser complains and doesn't bother calling us.
        !           188:  *
        !           189:  * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig,
        !           190:  *                                 char *word1, char *word2, char *word3);
        !           191:  */
        !           192: 
        !           193: /*
        !           194:  * Command handler for a TAKE12 directive.  These can take either one or two
        !           195:  * arguments.
        !           196:  * - word2 is a NULL pointer if no second argument was specified.
        !           197:  *
        !           198:  * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig,
        !           199:  *                                  char *word1, char *word2);
        !           200:  */
        !           201: 
        !           202: /*
        !           203:  * Command handler for a TAKE123 directive.  A TAKE123 directive can be given,
        !           204:  * as might be expected, one, two, or three arguments.
        !           205:  * - word2 is a NULL pointer if no second argument was specified.
        !           206:  * - word3 is a NULL pointer if no third argument was specified.
        !           207:  *
        !           208:  * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig,
        !           209:  *                                   char *word1, char *word2, char *word3);
        !           210:  */
        !           211: 
        !           212: /*
        !           213:  * Command handler for a TAKE13 directive.  Either one or three arguments are
        !           214:  * permitted - no two-parameters-only syntax is allowed.
        !           215:  * - word2 and word3 are NULL pointers if only one argument was specified.
        !           216:  *
        !           217:  * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig,
        !           218:  *                                  char *word1, char *word2, char *word3);
        !           219:  */
        !           220: 
        !           221: /*
        !           222:  * Command handler for a TAKE23 directive.  At least two and as many as three
        !           223:  * arguments must be specified.
        !           224:  * - word3 is a NULL pointer if no third argument was specified.
        !           225:  *
        !           226:  * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig,
        !           227:  *                                  char *word1, char *word2, char *word3);
        !           228:  */
        !           229: 
        !           230: /*
        !           231:  * Command handler for a ITERATE directive.
        !           232:  * - Handler is called once for each of n arguments given to the directive.
        !           233:  * - word1 points to each argument in turn.
        !           234:  *
        !           235:  * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig,
        !           236:  *                                   char *word1);
        !           237:  */
        !           238: 
        !           239: /*
        !           240:  * Command handler for a ITERATE2 directive.
        !           241:  * - Handler is called once for each of the second and subsequent arguments
        !           242:  *   given to the directive.
        !           243:  * - word1 is the same for each call for a particular directive instance (the
        !           244:  *   first argument).
        !           245:  * - word2 points to each of the second and subsequent arguments in turn.
        !           246:  *
        !           247:  * static const char *handle_ITERATE2(cmd_parms *cmd, void *mconfig,
        !           248:  *                                    char *word1, char *word2);
        !           249:  */
        !           250: 
        !           251: /*--------------------------------------------------------------------------*/
        !           252: /*                                                                          */
        !           253: /* These routines are strictly internal to this module, and support its     */
        !           254: /* operation.  They are not referenced by any external portion of the       */
        !           255: /* server.                                                                  */
        !           256: /*                                                                          */
        !           257: /*--------------------------------------------------------------------------*/
        !           258: 
        !           259: /*
        !           260:  * Locate our directory configuration record for the current request.
        !           261:  */
        !           262: static excfg *our_dconfig(request_rec *r)
        !           263: {
        !           264: 
        !           265:     return (excfg *) ap_get_module_config(r->per_dir_config, &example_module);
        !           266: }
        !           267: 
        !           268: #if 0
        !           269: /*
        !           270:  * Locate our server configuration record for the specified server.
        !           271:  */
        !           272: static excfg *our_sconfig(server_rec *s)
        !           273: {
        !           274: 
        !           275:     return (excfg *) ap_get_module_config(s->module_config, &example_module);
        !           276: }
        !           277: 
        !           278: /*
        !           279:  * Likewise for our configuration record for the specified request.
        !           280:  */
        !           281: static excfg *our_rconfig(request_rec *r)
        !           282: {
        !           283: 
        !           284:     return (excfg *) ap_get_module_config(r->request_config, &example_module);
        !           285: }
        !           286: #endif
        !           287: 
        !           288: /*
        !           289:  * This routine sets up some module-wide cells if they haven't been already.
        !           290:  */
        !           291: static void setup_module_cells()
        !           292: {
        !           293:     /*
        !           294:      * If we haven't already allocated our module-private pool, do so now.
        !           295:      */
        !           296:     if (example_pool == NULL) {
        !           297:         example_pool = ap_make_sub_pool(NULL);
        !           298:     };
        !           299:     /*
        !           300:      * Likewise for the table of routine/environment pairs we visit outside of
        !           301:      * request context.
        !           302:      */
        !           303:     if (static_calls_made == NULL) {
        !           304:         static_calls_made = ap_make_table(example_pool, 16);
        !           305:     };
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * This routine is used to add a trace of a callback to the list.  We're
        !           310:  * passed the server record (if available), the request record (if available),
        !           311:  * a pointer to our private configuration record (if available) for the
        !           312:  * environment to which the callback is supposed to apply, and some text.  We
        !           313:  * turn this into a textual representation and add it to the tail of the list.
        !           314:  * The list can be displayed by the example_handler() routine.
        !           315:  *
        !           316:  * If the call occurs within a request context (i.e., we're passed a request
        !           317:  * record), we put the trace into the request pool and attach it to the
        !           318:  * request via the notes mechanism.  Otherwise, the trace gets added
        !           319:  * to the static (non-request-specific) list.
        !           320:  *
        !           321:  * Note that the r->notes table is only for storing strings; if you need to
        !           322:  * maintain per-request data of any other type, you need to use another
        !           323:  * mechanism.
        !           324:  */
        !           325: 
        !           326: #define TRACE_NOTE "example-trace"
        !           327: 
        !           328: static void trace_add(server_rec *s, request_rec *r, excfg *mconfig,
        !           329:                       const char *note)
        !           330: {
        !           331: 
        !           332:     const char *sofar;
        !           333:     char *addon;
        !           334:     char *where;
        !           335:     pool *p;
        !           336:     const char *trace_copy;
        !           337: 
        !           338:     /*
        !           339:      * Make sure our pools and tables are set up - we need 'em.
        !           340:      */
        !           341:     setup_module_cells();
        !           342:     /*
        !           343:      * Now, if we're in request-context, we use the request pool.
        !           344:      */
        !           345:     if (r != NULL) {
        !           346:         p = r->pool;
        !           347:         if ((trace_copy = ap_table_get(r->notes, TRACE_NOTE)) == NULL) {
        !           348:             trace_copy = "";
        !           349:         }
        !           350:     }
        !           351:     else {
        !           352:         /*
        !           353:          * We're not in request context, so the trace gets attached to our
        !           354:          * module-wide pool.  We do the create/destroy every time we're called
        !           355:          * in non-request context; this avoids leaking memory in some of
        !           356:          * the subsequent calls that allocate memory only once (such as the
        !           357:          * key formation below).
        !           358:          *
        !           359:          * Make a new sub-pool and copy any existing trace to it.  Point the
        !           360:          * trace cell at the copied value.
        !           361:          */
        !           362:         p = ap_make_sub_pool(example_pool);
        !           363:         if (trace != NULL) {
        !           364:             trace = ap_pstrdup(p, trace);
        !           365:         }
        !           366:         /*
        !           367:          * Now, if we have a sub-pool from before, nuke it and replace with
        !           368:          * the one we just allocated.
        !           369:          */
        !           370:         if (example_subpool != NULL) {
        !           371:             ap_destroy_pool(example_subpool);
        !           372:         }
        !           373:         example_subpool = p;
        !           374:         trace_copy = trace;
        !           375:     }
        !           376:     /*
        !           377:      * If we weren't passed a configuration record, we can't figure out to
        !           378:      * what location this call applies.  This only happens for co-routines
        !           379:      * that don't operate in a particular directory or server context.  If we
        !           380:      * got a valid record, extract the location (directory or server) to which
        !           381:      * it applies.
        !           382:      */
        !           383:     where = (mconfig != NULL) ? mconfig->loc : "nowhere";
        !           384:     where = (where != NULL) ? where : "";
        !           385:     /*
        !           386:      * Now, if we're not in request context, see if we've been called with
        !           387:      * this particular combination before.  The table is allocated in the
        !           388:      * module's private pool, which doesn't get destroyed.
        !           389:      */
        !           390:     if (r == NULL) {
        !           391:         char *key;
        !           392: 
        !           393:         key = ap_pstrcat(p, note, ":", where, NULL);
        !           394:         if (ap_table_get(static_calls_made, key) != NULL) {
        !           395:             /*
        !           396:              * Been here, done this.
        !           397:              */
        !           398:             return;
        !           399:         }
        !           400:         else {
        !           401:             /*
        !           402:              * First time for this combination of routine and environment -
        !           403:              * log it so we don't do it again.
        !           404:              */
        !           405:             ap_table_set(static_calls_made, key, "been here");
        !           406:         }
        !           407:     }
        !           408:     addon = ap_pstrcat(p, "   <LI>\n", "    <DL>\n", "     <DT><SAMP>",
        !           409:                     note, "</SAMP>\n", "     </DT>\n", "     <DD><SAMP>[",
        !           410:                     where, "]</SAMP>\n", "     </DD>\n", "    </DL>\n",
        !           411:                     "   </LI>\n", NULL);
        !           412:     sofar = (trace_copy == NULL) ? "" : trace_copy;
        !           413:     trace_copy = ap_pstrcat(p, sofar, addon, NULL);
        !           414:     if (r != NULL) {
        !           415:         ap_table_set(r->notes, TRACE_NOTE, trace_copy);
        !           416:     }
        !           417:     else {
        !           418:         trace = trace_copy;
        !           419:     }
        !           420:     /*
        !           421:      * You *could* change the following if you wanted to see the calling
        !           422:      * sequence reported in the server's error_log, but beware - almost all of
        !           423:      * these co-routines are called for every single request, and the impact
        !           424:      * on the size (and readability) of the error_log is considerable.
        !           425:      */
        !           426: #define EXAMPLE_LOG_EACH 0
        !           427: #if EXAMPLE_LOG_EACH
        !           428:     if (s != NULL) {
        !           429:         ap_log_error(APLOG_MARK, APLOG_DEBUG, s, "mod_example: %s", note);
        !           430:     }
        !           431: #endif
        !           432: }
        !           433: 
        !           434: /*--------------------------------------------------------------------------*/
        !           435: /* We prototyped the various syntax for command handlers (routines that     */
        !           436: /* are called when the configuration parser detects a directive declared    */
        !           437: /* by our module) earlier.  Now we actually declare a "real" routine that   */
        !           438: /* will be invoked by the parser when our "real" directive is               */
        !           439: /* encountered.                                                             */
        !           440: /*                                                                          */
        !           441: /* If a command handler encounters a problem processing the directive, it   */
        !           442: /* signals this fact by returning a non-NULL pointer to a string            */
        !           443: /* describing the problem.                                                  */
        !           444: /*                                                                          */
        !           445: /* The magic return value DECLINE_CMD is used to deal with directives       */
        !           446: /* that might be declared by multiple modules.  If the command handler      */
        !           447: /* returns NULL, the directive was processed; if it returns DECLINE_CMD,    */
        !           448: /* the next module (if any) that declares the directive is given a chance   */
        !           449: /* at it.  If it returns any other value, it's treated as the text of an    */
        !           450: /* error message.                                                           */
        !           451: /*--------------------------------------------------------------------------*/
        !           452: /* 
        !           453:  * Command handler for the NO_ARGS "Example" directive.  All we do is mark the
        !           454:  * call in the trace log, and flag the applicability of the directive to the
        !           455:  * current location in that location's configuration record.
        !           456:  */
        !           457: static const char *cmd_example(cmd_parms *cmd, void *mconfig)
        !           458: {
        !           459: 
        !           460:     excfg *cfg = (excfg *) mconfig;
        !           461: 
        !           462:     /*
        !           463:      * "Example Wuz Here"
        !           464:      */
        !           465:     cfg->local = 1;
        !           466:     trace_add(cmd->server, NULL, cfg, "cmd_example()");
        !           467:     return NULL;
        !           468: }
        !           469: 
        !           470: /*--------------------------------------------------------------------------*/
        !           471: /*                                                                          */
        !           472: /* Now we declare our content handlers, which are invoked when the server   */
        !           473: /* encounters a document which our module is supposed to have a chance to   */
        !           474: /* see.  (See mod_mime's SetHandler and AddHandler directives, and the      */
        !           475: /* mod_info and mod_status examples, for more details.)                     */
        !           476: /*                                                                          */
        !           477: /* Since content handlers are dumping data directly into the connexion      */
        !           478: /* (using the r*() routines, such as rputs() and rprintf()) without         */
        !           479: /* intervention by other parts of the server, they need to make             */
        !           480: /* sure any accumulated HTTP headers are sent first.  This is done by       */
        !           481: /* calling send_http_header().  Otherwise, no header will be sent at all,   */
        !           482: /* and the output sent to the client will actually be HTTP-uncompliant.     */
        !           483: /*--------------------------------------------------------------------------*/
        !           484: /* 
        !           485:  * Sample content handler.  All this does is display the call list that has
        !           486:  * been built up so far.
        !           487:  *
        !           488:  * The return value instructs the caller concerning what happened and what to
        !           489:  * do next:
        !           490:  *  OK ("we did our thing")
        !           491:  *  DECLINED ("this isn't something with which we want to get involved")
        !           492:  *  HTTP_mumble ("an error status should be reported")
        !           493:  */
        !           494: static int example_handler(request_rec *r)
        !           495: {
        !           496: 
        !           497:     excfg *dcfg;
        !           498: 
        !           499:     dcfg = our_dconfig(r);
        !           500:     trace_add(r->server, r, dcfg, "example_handler()");
        !           501:     /*
        !           502:      * We're about to start sending content, so we need to force the HTTP
        !           503:      * headers to be sent at this point.  Otherwise, no headers will be sent
        !           504:      * at all.  We can set any we like first, of course.  **NOTE** Here's
        !           505:      * where you set the "Content-type" header, and you do so by putting it in
        !           506:      * r->content_type, *not* r->headers_out("Content-type").  If you don't
        !           507:      * set it, it will be filled in with the server's default type (typically
        !           508:      * "text/plain").  You *must* also ensure that r->content_type is lower
        !           509:      * case.
        !           510:      *
        !           511:      * We also need to start a timer so the server can know if the connexion
        !           512:      * is broken.
        !           513:      */
        !           514:     r->content_type = "text/html";
        !           515:     ap_soft_timeout("send example call trace", r);
        !           516:     ap_send_http_header(r);
        !           517:     /*
        !           518:      * If we're only supposed to send header information (HEAD request), we're
        !           519:      * already there.
        !           520:      */
        !           521:     if (r->header_only) {
        !           522:         ap_kill_timeout(r);
        !           523:         return OK;
        !           524:     }
        !           525: 
        !           526:     /*
        !           527:      * Now send our actual output.  Since we tagged this as being
        !           528:      * "text/html", we need to embed any HTML.
        !           529:      */
        !           530:     ap_rputs(DOCTYPE_HTML_3_2, r);
        !           531:     ap_rputs("<HTML>\n", r);
        !           532:     ap_rputs(" <HEAD>\n", r);
        !           533:     ap_rputs("  <TITLE>mod_example Module Content-Handler Output\n", r);
        !           534:     ap_rputs("  </TITLE>\n", r);
        !           535:     ap_rputs(" </HEAD>\n", r);
        !           536:     ap_rputs(" <BODY>\n", r);
        !           537:     ap_rputs("  <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r);
        !           538:     ap_rputs("  </H1>\n", r);
        !           539:     ap_rputs("  <P>\n", r);
        !           540:     ap_rprintf(r, "  Apache HTTP Server version: \"%s\"\n",
        !           541:            ap_get_server_version());
        !           542:     ap_rputs("  <BR>\n", r);
        !           543:     ap_rprintf(r, "  Server built: \"%s\"\n", ap_get_server_built());
        !           544:     ap_rputs("  </P>\n", r);;
        !           545:     ap_rputs("  <P>\n", r);
        !           546:     ap_rputs("  The format for the callback trace is:\n", r);
        !           547:     ap_rputs("  </P>\n", r);
        !           548:     ap_rputs("  <DL>\n", r);
        !           549:     ap_rputs("   <DT><EM>n</EM>.<SAMP>&lt;routine-name&gt;", r);
        !           550:     ap_rputs("(&lt;routine-data&gt;)</SAMP>\n", r);
        !           551:     ap_rputs("   </DT>\n", r);
        !           552:     ap_rputs("   <DD><SAMP>[&lt;applies-to&gt;]</SAMP>\n", r);
        !           553:     ap_rputs("   </DD>\n", r);
        !           554:     ap_rputs("  </DL>\n", r);
        !           555:     ap_rputs("  <P>\n", r);
        !           556:     ap_rputs("  The <SAMP>&lt;routine-data&gt;</SAMP> is supplied by\n", r);
        !           557:     ap_rputs("  the routine when it requests the trace,\n", r);
        !           558:     ap_rputs("  and the <SAMP>&lt;applies-to&gt;</SAMP> is extracted\n", r);
        !           559:     ap_rputs("  from the configuration record at the time of the trace.\n", r);
        !           560:     ap_rputs("  <STRONG>SVR()</STRONG> indicates a server environment\n", r);
        !           561:     ap_rputs("  (blank means the main or default server, otherwise it's\n", r);
        !           562:     ap_rputs("  the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r);
        !           563:     ap_rputs("  indicates a location in the URL or filesystem\n", r);
        !           564:     ap_rputs("  namespace.\n", r);
        !           565:     ap_rputs("  </P>\n", r);
        !           566:     ap_rprintf(r, "  <H2>Static callbacks so far:</H2>\n  <OL>\n%s  </OL>\n",
        !           567:             trace);
        !           568:     ap_rputs("  <H2>Request-specific callbacks so far:</H2>\n", r);
        !           569:     ap_rprintf(r, "  <OL>\n%s  </OL>\n", ap_table_get(r->notes, TRACE_NOTE));
        !           570:     ap_rputs("  <H2>Environment for <EM>this</EM> call:</H2>\n", r);
        !           571:     ap_rputs("  <UL>\n", r);
        !           572:     ap_rprintf(r, "   <LI>Applies-to: <SAMP>%s</SAMP>\n   </LI>\n", dcfg->loc);
        !           573:     ap_rprintf(r, "   <LI>\"Example\" directive declared here: %s\n   </LI>\n",
        !           574:             (dcfg->local ? "YES" : "NO"));
        !           575:     ap_rprintf(r, "   <LI>\"Example\" inherited: %s\n   </LI>\n",
        !           576:             (dcfg->congenital ? "YES" : "NO"));
        !           577:     ap_rputs("  </UL>\n", r);
        !           578:     ap_rputs(" </BODY>\n", r);
        !           579:     ap_rputs("</HTML>\n", r);
        !           580:     /*
        !           581:      * We're all done, so cancel the timeout we set.  Since this is probably
        !           582:      * the end of the request we *could* assume this would be done during
        !           583:      * post-processing - but it's possible that another handler might be
        !           584:      * called and inherit our outstanding timer.  Not good; to each its own.
        !           585:      */
        !           586:     ap_kill_timeout(r);
        !           587:     /*
        !           588:      * We did what we wanted to do, so tell the rest of the server we
        !           589:      * succeeded.
        !           590:      */
        !           591:     return OK;
        !           592: }
        !           593: 
        !           594: /*--------------------------------------------------------------------------*/
        !           595: /*                                                                          */
        !           596: /* Now let's declare routines for each of the callback phase in order.      */
        !           597: /* (That's the order in which they're listed in the callback list, *not     */
        !           598: /* the order in which the server calls them!  See the command_rec           */
        !           599: /* declaration near the bottom of this file.)  Note that these may be       */
        !           600: /* called for situations that don't relate primarily to our function - in   */
        !           601: /* other words, the fixup handler shouldn't assume that the request has     */
        !           602: /* to do with "example" stuff.                                              */
        !           603: /*                                                                          */
        !           604: /* With the exception of the content handler, all of our routines will be   */
        !           605: /* called for each request, unless an earlier handler from another module   */
        !           606: /* aborted the sequence.                                                    */
        !           607: /*                                                                          */
        !           608: /* Handlers that are declared as "int" can return the following:            */
        !           609: /*                                                                          */
        !           610: /*  OK          Handler accepted the request and did its thing with it.     */
        !           611: /*  DECLINED    Handler took no action.                                     */
        !           612: /*  HTTP_mumble Handler looked at request and found it wanting.             */
        !           613: /*                                                                          */
        !           614: /* What the server does after calling a module handler depends upon the     */
        !           615: /* handler's return value.  In all cases, if the handler returns            */
        !           616: /* DECLINED, the server will continue to the next module with an handler    */
        !           617: /* for the current phase.  However, if the handler return a non-OK,         */
        !           618: /* non-DECLINED status, the server aborts the request right there.  If      */
        !           619: /* the handler returns OK, the server's next action is phase-specific;      */
        !           620: /* see the individual handler comments below for details.                   */
        !           621: /*                                                                          */
        !           622: /*--------------------------------------------------------------------------*/
        !           623: /* 
        !           624:  * This function is called during server initialisation.  Any information
        !           625:  * that needs to be recorded must be in static cells, since there's no
        !           626:  * configuration record.
        !           627:  *
        !           628:  * There is no return value.
        !           629:  */
        !           630: 
        !           631: /*
        !           632:  * All our module-initialiser does is add its trace to the log.
        !           633:  */
        !           634: static void example_init(server_rec *s, pool *p)
        !           635: {
        !           636: 
        !           637:     char *note;
        !           638:     char *sname = s->server_hostname;
        !           639: 
        !           640:     /*
        !           641:      * Set up any module cells that ought to be initialised.
        !           642:      */
        !           643:     setup_module_cells();
        !           644:     /*
        !           645:      * The arbitrary text we add to our trace entry indicates for which server
        !           646:      * we're being called.
        !           647:      */
        !           648:     sname = (sname != NULL) ? sname : "";
        !           649:     note = ap_pstrcat(p, "example_init(", sname, ")", NULL);
        !           650:     trace_add(s, NULL, NULL, note);
        !           651: }
        !           652: 
        !           653: /* 
        !           654:  * This function is called during server initialisation when an heavy-weight
        !           655:  * process (such as a child) is being initialised.  As with the
        !           656:  * module-initialisation function, any information that needs to be recorded
        !           657:  * must be in static cells, since there's no configuration record.
        !           658:  *
        !           659:  * There is no return value.
        !           660:  */
        !           661: 
        !           662: /*
        !           663:  * All our process-initialiser does is add its trace to the log.
        !           664:  */
        !           665: static void example_child_init(server_rec *s, pool *p)
        !           666: {
        !           667: 
        !           668:     char *note;
        !           669:     char *sname = s->server_hostname;
        !           670: 
        !           671:     /*
        !           672:      * Set up any module cells that ought to be initialised.
        !           673:      */
        !           674:     setup_module_cells();
        !           675:     /*
        !           676:      * The arbitrary text we add to our trace entry indicates for which server
        !           677:      * we're being called.
        !           678:      */
        !           679:     sname = (sname != NULL) ? sname : "";
        !           680:     note = ap_pstrcat(p, "example_child_init(", sname, ")", NULL);
        !           681:     trace_add(s, NULL, NULL, note);
        !           682: }
        !           683: 
        !           684: /* 
        !           685:  * This function is called when an heavy-weight process (such as a child) is
        !           686:  * being run down or destroyed.  As with the child-initialisation function,
        !           687:  * any information that needs to be recorded must be in static cells, since
        !           688:  * there's no configuration record.
        !           689:  *
        !           690:  * There is no return value.
        !           691:  */
        !           692: 
        !           693: /*
        !           694:  * All our process-death routine does is add its trace to the log.
        !           695:  */
        !           696: static void example_child_exit(server_rec *s, pool *p)
        !           697: {
        !           698: 
        !           699:     char *note;
        !           700:     char *sname = s->server_hostname;
        !           701: 
        !           702:     /*
        !           703:      * The arbitrary text we add to our trace entry indicates for which server
        !           704:      * we're being called.
        !           705:      */
        !           706:     sname = (sname != NULL) ? sname : "";
        !           707:     note = ap_pstrcat(p, "example_child_exit(", sname, ")", NULL);
        !           708:     trace_add(s, NULL, NULL, note);
        !           709: }
        !           710: 
        !           711: /*
        !           712:  * This function gets called to create a per-directory configuration
        !           713:  * record.  This will be called for the "default" server environment, and for
        !           714:  * each directory for which the parser finds any of our directives applicable.
        !           715:  * If a directory doesn't have any of our directives involved (i.e., they
        !           716:  * aren't in the .htaccess file, or a <Location>, <Directory>, or related
        !           717:  * block), this routine will *not* be called - the configuration for the
        !           718:  * closest ancestor is used.
        !           719:  *
        !           720:  * The return value is a pointer to the created module-specific
        !           721:  * structure.
        !           722:  */
        !           723: static void *example_create_dir_config(pool *p, char *dirspec)
        !           724: {
        !           725: 
        !           726:     excfg *cfg;
        !           727:     char *dname = dirspec;
        !           728: 
        !           729:     /*
        !           730:      * Allocate the space for our record from the pool supplied.
        !           731:      */
        !           732:     cfg = (excfg *) ap_pcalloc(p, sizeof(excfg));
        !           733:     /*
        !           734:      * Now fill in the defaults.  If there are any `parent' configuration
        !           735:      * records, they'll get merged as part of a separate callback.
        !           736:      */
        !           737:     cfg->local = 0;
        !           738:     cfg->congenital = 0;
        !           739:     cfg->cmode = CONFIG_MODE_DIRECTORY;
        !           740:     /*
        !           741:      * Finally, add our trace to the callback list.
        !           742:      */
        !           743:     dname = (dname != NULL) ? dname : "";
        !           744:     cfg->loc = ap_pstrcat(p, "DIR(", dname, ")", NULL);
        !           745:     trace_add(NULL, NULL, cfg, "example_create_dir_config()");
        !           746:     return (void *) cfg;
        !           747: }
        !           748: 
        !           749: /*
        !           750:  * This function gets called to merge two per-directory configuration
        !           751:  * records.  This is typically done to cope with things like .htaccess files
        !           752:  * or <Location> directives for directories that are beneath one for which a
        !           753:  * configuration record was already created.  The routine has the
        !           754:  * responsibility of creating a new record and merging the contents of the
        !           755:  * other two into it appropriately.  If the module doesn't declare a merge
        !           756:  * routine, the record for the closest ancestor location (that has one) is
        !           757:  * used exclusively.
        !           758:  *
        !           759:  * The routine MUST NOT modify any of its arguments!
        !           760:  *
        !           761:  * The return value is a pointer to the created module-specific structure
        !           762:  * containing the merged values.
        !           763:  */
        !           764: static void *example_merge_dir_config(pool *p, void *parent_conf,
        !           765:                                       void *newloc_conf)
        !           766: {
        !           767: 
        !           768:     excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg));
        !           769:     excfg *pconf = (excfg *) parent_conf;
        !           770:     excfg *nconf = (excfg *) newloc_conf;
        !           771:     char *note;
        !           772: 
        !           773:     /*
        !           774:      * Some things get copied directly from the more-specific record, rather
        !           775:      * than getting merged.
        !           776:      */
        !           777:     merged_config->local = nconf->local;
        !           778:     merged_config->loc = ap_pstrdup(p, nconf->loc);
        !           779:     /*
        !           780:      * Others, like the setting of the `congenital' flag, get ORed in.  The
        !           781:      * setting of that particular flag, for instance, is TRUE if it was ever
        !           782:      * true anywhere in the upstream configuration.
        !           783:      */
        !           784:     merged_config->congenital = (pconf->congenital | pconf->local);
        !           785:     /*
        !           786:      * If we're merging records for two different types of environment (server
        !           787:      * and directory), mark the new record appropriately.  Otherwise, inherit
        !           788:      * the current value.
        !           789:      */
        !           790:     merged_config->cmode =
        !           791:         (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO;
        !           792:     /*
        !           793:      * Now just record our being called in the trace list.  Include the
        !           794:      * locations we were asked to merge.
        !           795:      */
        !           796:     note = ap_pstrcat(p, "example_merge_dir_config(\"", pconf->loc, "\",\"",
        !           797:                    nconf->loc, "\")", NULL);
        !           798:     trace_add(NULL, NULL, merged_config, note);
        !           799:     return (void *) merged_config;
        !           800: }
        !           801: 
        !           802: /*
        !           803:  * This function gets called to create a per-server configuration
        !           804:  * record.  It will always be called for the "default" server.
        !           805:  *
        !           806:  * The return value is a pointer to the created module-specific
        !           807:  * structure.
        !           808:  */
        !           809: static void *example_create_server_config(pool *p, server_rec *s)
        !           810: {
        !           811: 
        !           812:     excfg *cfg;
        !           813:     char *sname = s->server_hostname;
        !           814: 
        !           815:     /*
        !           816:      * As with the example_create_dir_config() reoutine, we allocate and fill
        !           817:      * in an empty record.
        !           818:      */
        !           819:     cfg = (excfg *) ap_pcalloc(p, sizeof(excfg));
        !           820:     cfg->local = 0;
        !           821:     cfg->congenital = 0;
        !           822:     cfg->cmode = CONFIG_MODE_SERVER;
        !           823:     /*
        !           824:      * Note that we were called in the trace list.
        !           825:      */
        !           826:     sname = (sname != NULL) ? sname : "";
        !           827:     cfg->loc = ap_pstrcat(p, "SVR(", sname, ")", NULL);
        !           828:     trace_add(s, NULL, cfg, "example_create_server_config()");
        !           829:     return (void *) cfg;
        !           830: }
        !           831: 
        !           832: /*
        !           833:  * This function gets called to merge two per-server configuration
        !           834:  * records.  This is typically done to cope with things like virtual hosts and
        !           835:  * the default server configuration  The routine has the responsibility of
        !           836:  * creating a new record and merging the contents of the other two into it
        !           837:  * appropriately.  If the module doesn't declare a merge routine, the more
        !           838:  * specific existing record is used exclusively.
        !           839:  *
        !           840:  * The routine MUST NOT modify any of its arguments!
        !           841:  *
        !           842:  * The return value is a pointer to the created module-specific structure
        !           843:  * containing the merged values.
        !           844:  */
        !           845: static void *example_merge_server_config(pool *p, void *server1_conf,
        !           846:                                          void *server2_conf)
        !           847: {
        !           848: 
        !           849:     excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg));
        !           850:     excfg *s1conf = (excfg *) server1_conf;
        !           851:     excfg *s2conf = (excfg *) server2_conf;
        !           852:     char *note;
        !           853: 
        !           854:     /*
        !           855:      * Our inheritance rules are our own, and part of our module's semantics.
        !           856:      * Basically, just note whence we came.
        !           857:      */
        !           858:     merged_config->cmode =
        !           859:         (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO;
        !           860:     merged_config->local = s2conf->local;
        !           861:     merged_config->congenital = (s1conf->congenital | s1conf->local);
        !           862:     merged_config->loc = ap_pstrdup(p, s2conf->loc);
        !           863:     /*
        !           864:      * Trace our call, including what we were asked to merge.
        !           865:      */
        !           866:     note = ap_pstrcat(p, "example_merge_server_config(\"", s1conf->loc, "\",\"",
        !           867:                    s2conf->loc, "\")", NULL);
        !           868:     trace_add(NULL, NULL, merged_config, note);
        !           869:     return (void *) merged_config;
        !           870: }
        !           871: 
        !           872: /*
        !           873:  * This routine is called after the request has been read but before any other
        !           874:  * phases have been processed.  This allows us to make decisions based upon
        !           875:  * the input header fields.
        !           876:  *
        !           877:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
        !           878:  * further modules are called for this phase.
        !           879:  */
        !           880: static int example_post_read_request(request_rec *r)
        !           881: {
        !           882: 
        !           883:     excfg *cfg;
        !           884: 
        !           885:     cfg = our_dconfig(r);
        !           886:     /*
        !           887:      * We don't actually *do* anything here, except note the fact that we were
        !           888:      * called.
        !           889:      */
        !           890:     trace_add(r->server, r, cfg, "example_post_read_request()");
        !           891:     return DECLINED;
        !           892: }
        !           893: 
        !           894: /*
        !           895:  * This routine gives our module an opportunity to translate the URI into an
        !           896:  * actual filename.  If we don't do anything special, the server's default
        !           897:  * rules (Alias directives and the like) will continue to be followed.
        !           898:  *
        !           899:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
        !           900:  * further modules are called for this phase.
        !           901:  */
        !           902: static int example_translate_handler(request_rec *r)
        !           903: {
        !           904: 
        !           905:     excfg *cfg;
        !           906: 
        !           907:     cfg = our_dconfig(r);
        !           908:     /*
        !           909:      * We don't actually *do* anything here, except note the fact that we were
        !           910:      * called.
        !           911:      */
        !           912:     trace_add(r->server, r, cfg, "example_translate_handler()");
        !           913:     return DECLINED;
        !           914: }
        !           915: 
        !           916: /*
        !           917:  * This routine is called to check the authentication information sent with
        !           918:  * the request (such as looking up the user in a database and verifying that
        !           919:  * the [encrypted] password sent matches the one in the database).
        !           920:  *
        !           921:  * The return value is OK, DECLINED, or some HTTP_mumble error (typically
        !           922:  * HTTP_UNAUTHORIZED).  If we return OK, no other modules are given a chance
        !           923:  * at the request during this phase.
        !           924:  */
        !           925: static int example_check_user_id(request_rec *r)
        !           926: {
        !           927: 
        !           928:     excfg *cfg;
        !           929: 
        !           930:     cfg = our_dconfig(r);
        !           931:     /*
        !           932:      * Don't do anything except log the call.
        !           933:      */
        !           934:     trace_add(r->server, r, cfg, "example_check_user_id()");
        !           935:     return DECLINED;
        !           936: }
        !           937: 
        !           938: /*
        !           939:  * This routine is called to check to see if the resource being requested
        !           940:  * requires authorisation.
        !           941:  *
        !           942:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
        !           943:  * other modules are called during this phase.
        !           944:  *
        !           945:  * If *all* modules return DECLINED, the request is aborted with a server
        !           946:  * error.
        !           947:  */
        !           948: static int example_auth_checker(request_rec *r)
        !           949: {
        !           950: 
        !           951:     excfg *cfg;
        !           952: 
        !           953:     cfg = our_dconfig(r);
        !           954:     /*
        !           955:      * Log the call and return OK, or access will be denied (even though we
        !           956:      * didn't actually do anything).
        !           957:      */
        !           958:     trace_add(r->server, r, cfg, "example_auth_checker()");
        !           959:     return DECLINED;
        !           960: }
        !           961: 
        !           962: /*
        !           963:  * This routine is called to check for any module-specific restrictions placed
        !           964:  * upon the requested resource.  (See the mod_access module for an example.)
        !           965:  *
        !           966:  * The return value is OK, DECLINED, or HTTP_mumble.  All modules with an
        !           967:  * handler for this phase are called regardless of whether their predecessors
        !           968:  * return OK or DECLINED.  The first one to return any other status, however,
        !           969:  * will abort the sequence (and the request) as usual.
        !           970:  */
        !           971: static int example_access_checker(request_rec *r)
        !           972: {
        !           973: 
        !           974:     excfg *cfg;
        !           975: 
        !           976:     cfg = our_dconfig(r);
        !           977:     trace_add(r->server, r, cfg, "example_access_checker()");
        !           978:     return DECLINED;
        !           979: }
        !           980: 
        !           981: /*
        !           982:  * This routine is called to determine and/or set the various document type
        !           983:  * information bits, like Content-type (via r->content_type), language, et
        !           984:  * cetera.
        !           985:  *
        !           986:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
        !           987:  * further modules are given a chance at the request for this phase.
        !           988:  */
        !           989: static int example_type_checker(request_rec *r)
        !           990: {
        !           991: 
        !           992:     excfg *cfg;
        !           993: 
        !           994:     cfg = our_dconfig(r);
        !           995:     /*
        !           996:      * Log the call, but don't do anything else - and report truthfully that
        !           997:      * we didn't do anything.
        !           998:      */
        !           999:     trace_add(r->server, r, cfg, "example_type_checker()");
        !          1000:     return DECLINED;
        !          1001: }
        !          1002: 
        !          1003: /*
        !          1004:  * This routine is called to perform any module-specific fixing of header
        !          1005:  * fields, et cetera.  It is invoked just before any content-handler.
        !          1006:  *
        !          1007:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, the
        !          1008:  * server will still call any remaining modules with an handler for this
        !          1009:  * phase.
        !          1010:  */
        !          1011: static int example_fixer_upper(request_rec *r)
        !          1012: {
        !          1013: 
        !          1014:     excfg *cfg;
        !          1015: 
        !          1016:     cfg = our_dconfig(r);
        !          1017:     /*
        !          1018:      * Log the call and exit.
        !          1019:      */
        !          1020:     trace_add(r->server, r, cfg, "example_fixer_upper()");
        !          1021:     return OK;
        !          1022: }
        !          1023: 
        !          1024: /*
        !          1025:  * This routine is called to perform any module-specific logging activities
        !          1026:  * over and above the normal server things.
        !          1027:  *
        !          1028:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, any
        !          1029:  * remaining modules with an handler for this phase will still be called.
        !          1030:  */
        !          1031: static int example_logger(request_rec *r)
        !          1032: {
        !          1033: 
        !          1034:     excfg *cfg;
        !          1035: 
        !          1036:     cfg = our_dconfig(r);
        !          1037:     trace_add(r->server, r, cfg, "example_logger()");
        !          1038:     return DECLINED;
        !          1039: }
        !          1040: 
        !          1041: /*
        !          1042:  * This routine is called to give the module a chance to look at the request
        !          1043:  * headers and take any appropriate specific actions early in the processing
        !          1044:  * sequence.
        !          1045:  *
        !          1046:  * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, any
        !          1047:  * remaining modules with handlers for this phase will still be called.
        !          1048:  */
        !          1049: static int example_header_parser(request_rec *r)
        !          1050: {
        !          1051: 
        !          1052:     excfg *cfg;
        !          1053: 
        !          1054:     cfg = our_dconfig(r);
        !          1055:     trace_add(r->server, r, cfg, "example_header_parser()");
        !          1056:     return DECLINED;
        !          1057: }
        !          1058: 
        !          1059: /*--------------------------------------------------------------------------*/
        !          1060: /*                                                                          */
        !          1061: /* All of the routines have been declared now.  Here's the list of          */
        !          1062: /* directives specific to our module, and information about where they      */
        !          1063: /* may appear and how the command parser should pass them to us for         */
        !          1064: /* processing.  Note that care must be taken to ensure that there are NO    */
        !          1065: /* collisions of directive names between modules.                           */
        !          1066: /*                                                                          */
        !          1067: /*--------------------------------------------------------------------------*/
        !          1068: /* 
        !          1069:  * List of directives specific to our module.
        !          1070:  */
        !          1071: static const command_rec example_cmds[] =
        !          1072: {
        !          1073:     {
        !          1074:         "Example",              /* directive name */
        !          1075:         cmd_example,            /* config action routine */
        !          1076:         NULL,                   /* argument to include in call */
        !          1077:         OR_OPTIONS,             /* where available */
        !          1078:         NO_ARGS,                /* arguments */
        !          1079:         "Example directive - no arguments"
        !          1080:                                 /* directive description */
        !          1081:     },
        !          1082:     {NULL}
        !          1083: };
        !          1084: 
        !          1085: /*--------------------------------------------------------------------------*/
        !          1086: /*                                                                          */
        !          1087: /* Now the list of content handlers available from this module.             */
        !          1088: /*                                                                          */
        !          1089: /*--------------------------------------------------------------------------*/
        !          1090: /* 
        !          1091:  * List of content handlers our module supplies.  Each handler is defined by
        !          1092:  * two parts: a name by which it can be referenced (such as by
        !          1093:  * {Add,Set}Handler), and the actual routine name.  The list is terminated by
        !          1094:  * a NULL block, since it can be of variable length.
        !          1095:  *
        !          1096:  * Note that content-handlers are invoked on a most-specific to least-specific
        !          1097:  * basis; that is, a handler that is declared for "text/plain" will be
        !          1098:  * invoked before one that was declared for "text / *".  Note also that
        !          1099:  * if a content-handler returns anything except DECLINED, no other
        !          1100:  * content-handlers will be called.
        !          1101:  */
        !          1102: static const handler_rec example_handlers[] =
        !          1103: {
        !          1104:     {"example-handler", example_handler},
        !          1105:     {NULL}
        !          1106: };
        !          1107: 
        !          1108: /*--------------------------------------------------------------------------*/
        !          1109: /*                                                                          */
        !          1110: /* Finally, the list of callback routines and data structures that          */
        !          1111: /* provide the hooks into our module from the other parts of the server.    */
        !          1112: /*                                                                          */
        !          1113: /*--------------------------------------------------------------------------*/
        !          1114: /* 
        !          1115:  * Module definition for configuration.  If a particular callback is not
        !          1116:  * needed, replace its routine name below with the word NULL.
        !          1117:  *
        !          1118:  * The number in brackets indicates the order in which the routine is called
        !          1119:  * during request processing.  Note that not all routines are necessarily
        !          1120:  * called (such as if a resource doesn't have access restrictions).
        !          1121:  */
        !          1122: module MODULE_VAR_EXPORT example_module =
        !          1123: {
        !          1124:     STANDARD_MODULE_STUFF,
        !          1125:     example_init,               /* module initializer */
        !          1126:     example_create_dir_config,  /* per-directory config creator */
        !          1127:     example_merge_dir_config,   /* dir config merger */
        !          1128:     example_create_server_config,       /* server config creator */
        !          1129:     example_merge_server_config,        /* server config merger */
        !          1130:     example_cmds,               /* command table */
        !          1131:     example_handlers,           /* [9] list of handlers */
        !          1132:     example_translate_handler,  /* [2] filename-to-URI translation */
        !          1133:     example_check_user_id,      /* [5] check/validate user_id */
        !          1134:     example_auth_checker,       /* [6] check user_id is valid *here* */
        !          1135:     example_access_checker,     /* [4] check access by host address */
        !          1136:     example_type_checker,       /* [7] MIME type checker/setter */
        !          1137:     example_fixer_upper,        /* [8] fixups */
        !          1138:     example_logger,             /* [10] logger */
        !          1139: #if MODULE_MAGIC_NUMBER >= 19970103
        !          1140:     example_header_parser,      /* [3] header parser */
        !          1141: #endif
        !          1142: #if MODULE_MAGIC_NUMBER >= 19970719
        !          1143:     example_child_init,         /* process initializer */
        !          1144: #endif
        !          1145: #if MODULE_MAGIC_NUMBER >= 19970728
        !          1146:     example_child_exit,         /* process exit/cleanup */
        !          1147: #endif
        !          1148: #if MODULE_MAGIC_NUMBER >= 19970902
        !          1149:     example_post_read_request   /* [1] post read_request handling */
        !          1150: #endif
        !          1151: };

E-mail: