Annotation of parser3/src/targets/apache13/mod_parser3.C, revision 1.1
1.1 ! parser 1: /** @file
! 2: Parser: apache 1.3 module.
! 3:
! 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
! 5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
! 6:
! 7: $Id: mod_parser3.C,v 1.49 2001/10/09 14:30:19 parser Exp $
! 8: */
! 9:
! 10: #include "httpd.h"
! 11: #include "http_config.h"
! 12: #include "http_core.h"
! 13: #include "http_log.h"
! 14: #include "http_main.h"
! 15: #include "http_protocol.h"
! 16: #include "util_script.h"
! 17:
! 18: #include "pa_sapi.h"
! 19: #include "classes.h"
! 20: #include "pa_common.h"
! 21: #include "pa_globals.h"
! 22: #include "pa_request.h"
! 23: #include "pa_version.h"
! 24: #include "pa_socks.h"
! 25:
! 26: #ifdef _DEBUG
! 27: # define DEBUG_PREFIX "debug_"
! 28: # define PARSER3_MODULE debug_parser3_module
! 29: #else
! 30: # define DEBUG_PREFIX
! 31: # define PARSER3_MODULE parser3_module
! 32: #endif
! 33:
! 34: // consts
! 35:
! 36: extern const char *main_RCSIds[];
! 37: #ifdef USE_SMTP
! 38: extern const char *smtp_RCSIds[];
! 39: #endif
! 40: extern const char *gd_RCSIds[];
! 41: extern const char *classes_RCSIds[];
! 42: extern const char *types_RCSIds[];
! 43: extern const char *ApacheModuleParser3_RCSIds[];
! 44: #ifdef XML
! 45: extern const char *xalan_patched_RCSIds[];
! 46: #endif
! 47: const char **RCSIds[]={
! 48: main_RCSIds,
! 49: #ifdef USE_SMTP
! 50: smtp_RCSIds,
! 51: #endif
! 52: gd_RCSIds,
! 53: classes_RCSIds,
! 54: types_RCSIds,
! 55: ApacheModuleParser3_RCSIds,
! 56: #ifdef XML
! 57: xalan_patched_RCSIds,
! 58: #endif
! 59: 0
! 60: };
! 61:
! 62:
! 63: /// apache parser module configuration [httpd.conf + .htaccess-es]
! 64: struct Parser_module_config {
! 65: const char* parser_root_config_filespec; ///< filespec of admin's config file
! 66: const char* parser_site_config_filespec; ///< filespec of site's config file
! 67: };
! 68:
! 69: /*
! 70: * Declare ourselves so the configuration routines can find and know us.
! 71: * We'll fill it in at the end of the module.
! 72: */
! 73: extern "C" module MODULE_VAR_EXPORT PARSER3_MODULE;
! 74:
! 75: /*
! 76: * Locate our directory configuration record for the current request.
! 77: */
! 78: static Parser_module_config *our_dconfig(request_rec *r) {
! 79: return (Parser_module_config *)
! 80: ap_get_module_config(r->per_dir_config, &PARSER3_MODULE);
! 81: }
! 82:
! 83: static const char *cmd_parser_config(cmd_parms *cmd, void *mconfig, char *file_spec) {
! 84: Parser_module_config *cfg = (Parser_module_config *) mconfig;
! 85:
! 86: // remember assigned filespec into cfg
! 87: (cmd->info?cfg->parser_root_config_filespec:cfg->parser_site_config_filespec)=file_spec;
! 88:
! 89: return NULL;
! 90: }
! 91:
! 92:
! 93: /*--------------------------------------------------------------------------*/
! 94: /* */
! 95: /* Now we declare our content handlers, which are invoked when the server */
! 96: /* encounters a document which our module is supposed to have a chance to */
! 97: /* see. (See mod_mime's SetHandler and AddHandler directives, and the */
! 98: /* mod_info and mod_status examples, for more details.) */
! 99: /* */
! 100: /* Since content handlers are dumping data directly into the connexion */
! 101: /* (using the r*() routines, such as rputs() and rprintf()) without */
! 102: /* intervention by other parts of the server, they need to make */
! 103: /* sure any accumulated HTTP headers are sent first. This is done by */
! 104: /* calling send_http_header(). Otherwise, no header will be sent at all, */
! 105: /* and the output sent to the client will actually be HTTP-uncompliant. */
! 106: /*--------------------------------------------------------------------------*/
! 107: /*
! 108: * Sample content handler. All this does is display the call list that has
! 109: * been built up so far.
! 110: *
! 111: * The return value instructs the caller concerning what happened and what to
! 112: * do next:
! 113: * OK ("we did our thing")
! 114: * DECLINED ("this isn't something with which we want to get involved")
! 115: * HTTP_mumble ("an error status should be reported")
! 116: */
! 117:
! 118:
! 119: //@{
! 120: /// SAPI func decl
! 121: void SAPI::log(Pool& pool, const char *fmt, ...) {
! 122: request_rec *r=static_cast<request_rec *>(pool.context());
! 123:
! 124: va_list args;
! 125: va_start(args,fmt);
! 126: char buf[MAX_STRING];
! 127: size_t size=vsnprintf(buf, MAX_STRING, fmt, args);
! 128: remove_crlf(buf, buf+size);
! 129: ap_log_rerror(0, 0, APLOG_ERR | APLOG_NOERRNO, r, "%s", buf);
! 130: va_end(args);
! 131: }
! 132:
! 133: const char *SAPI::get_env(Pool& pool, const char *name) {
! 134: request_rec *r=static_cast<request_rec *>(pool.context());
! 135: return (const char *)ap_table_get(r->subprocess_env, name);
! 136: }
! 137:
! 138: size_t SAPI::read_post(Pool& pool, char *buf, size_t max_bytes) {
! 139: request_rec *r=static_cast<request_rec *>(pool.context());
! 140:
! 141: /* ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server,
! 142: "mod_parser3: SAPI::read_post(max=%u)", max_bytes);
! 143: */
! 144: int retval;
! 145: if((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
! 146: return 0;
! 147: if(!ap_should_client_block(r))
! 148: return 0;
! 149:
! 150: uint total_read_bytes=0;
! 151: void (*handler)(int)=signal(SIGPIPE, SIG_IGN);
! 152: while (total_read_bytes<max_bytes) {
! 153: ap_hard_timeout("Read POST information", r); /* start timeout timer */
! 154: uint read_bytes=
! 155: ap_get_client_block(r, buf+total_read_bytes, max_bytes-total_read_bytes);
! 156: ap_reset_timeout(r);
! 157: if (read_bytes<=0)
! 158: break;
! 159: total_read_bytes+=read_bytes;
! 160: }
! 161: signal(SIGPIPE, handler);
! 162: return total_read_bytes;
! 163: }
! 164:
! 165: void SAPI::add_header_attribute(Pool& pool, const char *key, const char *value) {
! 166: request_rec *r=static_cast<request_rec *>(pool.context());
! 167:
! 168: if(strcasecmp(key, "location")==0)
! 169: r->status=302;
! 170:
! 171: if(strcasecmp(key, "content-type")==0) {
! 172: /* r->content_type, *not* r->headers_out("Content-type"). If you don't
! 173: * set it, it will be filled in with the server's default type (typically
! 174: * "text/plain"). You *must* also ensure that r->content_type is lower
! 175: * case.
! 176: */
! 177: r->content_type = value;
! 178: } else if(strcasecmp(key, "status")==0)
! 179: r->status=atoi(value);
! 180: else
! 181: ap_table_addn(r->headers_out, key, value);
! 182: }
! 183:
! 184: void SAPI::send_header(Pool& pool) {
! 185: request_rec *r=static_cast<request_rec *>(pool.context());
! 186:
! 187: ap_hard_timeout("Send header", r);
! 188: ap_send_http_header(r);
! 189: ap_kill_timeout(r);
! 190: }
! 191:
! 192: void SAPI::send_body(Pool& pool, const void *buf, size_t size) {
! 193: request_rec *r=static_cast<request_rec *>(pool.context());
! 194:
! 195: ap_hard_timeout("Send body", r);
! 196: ap_rwrite(buf, size, r);
! 197: ap_kill_timeout(r);
! 198: }
! 199:
! 200: //@}
! 201:
! 202: /**
! 203: main workhorse
! 204:
! 205: @todo intelligent cache-control
! 206: */
! 207: static int parser_handler(request_rec *r) {
! 208: // _asm int 3;
! 209: if(r->finfo.st_mode == 0)
! 210: return NOT_FOUND;
! 211:
! 212: Pool pool(r->pool);
! 213: pool.set_context(r);
! 214:
! 215: Parser_module_config *dcfg=our_dconfig(r);
! 216:
! 217:
! 218: /* A flag which modules can set, to indicate that the data being
! 219: * returned is volatile, and clients should be told not to cache it.
! 220: */
! 221: r->no_cache=1;
! 222:
! 223: PTRY { // global try
! 224: ap_add_common_vars(r);
! 225: ap_add_cgi_vars(r);
! 226:
! 227: // Request info
! 228: Request::Info request_info;
! 229: request_info.document_root=SAPI::get_env(pool, "DOCUMENT_ROOT");
! 230: request_info.path_translated=r->filename;
! 231: request_info.method=r->method;
! 232: request_info.query_string=r->args;
! 233: request_info.uri=SAPI::get_env(pool, "REQUEST_URI");
! 234: request_info.content_type=SAPI::get_env(pool, "CONTENT_TYPE");
! 235: const char *content_length=SAPI::get_env(pool, "CONTENT_LENGTH");
! 236: request_info.content_length=content_length?atoi(content_length):0;
! 237: request_info.cookie=SAPI::get_env(pool, "HTTP_COOKIE");
! 238: request_info.user_agent=SAPI::get_env(pool, "HTTP_USER_AGENT");
! 239:
! 240: //_asm int 3;
! 241: // prepare to process request
! 242: Request request(pool,
! 243: request_info,
! 244: String::UL_USER_HTML
! 245: );
! 246:
! 247: // process the request
! 248: request.core(
! 249: dcfg->parser_root_config_filespec, true, // /path/to/admin/config
! 250: dcfg->parser_site_config_filespec, true, // /path/to/site/config
! 251: r->header_only!=0);
! 252: // no actions with request' data past this point
! 253: // request.exception not not handled here, but all
! 254: // request' data are associated with it's pool=exception
! 255:
! 256: // successful finish
! 257: } PCATCH(e) { // global problem
! 258: // don't allocate anything on pool here:
! 259: // possible pool' exception not catch-ed now
! 260: // and there could be out-of-memory exception
! 261: const char *body=e.comment();
! 262: // log it
! 263: SAPI::log(pool, "exception in request exception handler: %s", body);
! 264:
! 265: //
! 266: int content_length=strlen(body);
! 267:
! 268: // prepare header
! 269: SAPI::add_header_attribute(pool, "content-type", "text/plain");
! 270: char content_length_cstr[MAX_NUMBER];
! 271: snprintf(content_length_cstr, MAX_NUMBER, "%u", content_length);
! 272: SAPI::add_header_attribute(pool, "content-length", content_length_cstr);
! 273:
! 274: // send header
! 275: SAPI::send_header(pool);
! 276:
! 277: // send body
! 278: if(!r->header_only)
! 279: SAPI::send_body(pool, body, content_length);
! 280:
! 281: // unsuccessful finish
! 282: }
! 283: PEND_CATCH
! 284:
! 285: /*
! 286: * We did what we wanted to do, so tell the rest of the server we
! 287: * succeeded.
! 288: */
! 289: return OK;
! 290: }
! 291:
! 292: /*--------------------------------------------------------------------------*/
! 293: /* */
! 294: /* Now let's declare routines for each of the callback phase in order. */
! 295: /* (That's the order in which they're listed in the callback list, *not */
! 296: /* the order in which the server calls them! See the command_rec */
! 297: /* declaration near the bottom of this file.) Note that these may be */
! 298: /* called for situations that don't relate primarily to our function - in */
! 299: /* other words, the fixup handler shouldn't assume that the request has */
! 300: /* to do with "example" stuff. */
! 301: /* */
! 302: /* With the exception of the content handler, all of our routines will be */
! 303: /* called for each request, unless an earlier handler from another module */
! 304: /* aborted the sequence. */
! 305: /* */
! 306: /* Handlers that are declared as "int" can return the following: */
! 307: /* */
! 308: /* OK Handler accepted the request and did its thing with it. */
! 309: /* DECLINED Handler took no action. */
! 310: /* HTTP_mumble Handler looked at request and found it wanting. */
! 311: /* */
! 312: /* What the server does after calling a module handler depends upon the */
! 313: /* handler's return value. In all cases, if the handler returns */
! 314: /* DECLINED, the server will continue to the next module with an handler */
! 315: /* for the current phase. However, if the handler return a non-OK, */
! 316: /* non-DECLINED status, the server aborts the request right there. If */
! 317: /* the handler returns OK, the server's next action is phase-specific; */
! 318: /* see the individual handler comments below for details. */
! 319: /* */
! 320: /*--------------------------------------------------------------------------*/
! 321: /*
! 322: * This function is called during server initialisation. Any information
! 323: * that needs to be recorded must be in static cells, since there's no
! 324: * configuration record.
! 325: *
! 326: * There is no return value.
! 327: */
! 328:
! 329: static void setup_module_cells() {
! 330: static bool globals_inited=false;
! 331: if(globals_inited)
! 332: return;
! 333: globals_inited=true;
! 334:
! 335: /*
! 336: * allocate our module-private pool.
! 337: */
! 338: static Pool pool(ap_make_sub_pool(NULL)); // global pool
! 339: PTRY {
! 340: // init socks
! 341: init_socks(pool);
! 342:
! 343: // init global classes
! 344: init_methoded_array(pool);
! 345: // init global variables
! 346: pa_globals_init(pool);
! 347: } PCATCH(e) { // global problem
! 348: ap_log_error(APLOG_MARK, APLOG_EMERG, 0,
! 349: "setup_module_cells failed: ", e.comment());
! 350: exit(1);
! 351: }
! 352: PEND_CATCH
! 353: }
! 354:
! 355: static void parser_server_init(server_rec *s, pool *p) {
! 356: #if MODULE_MAGIC_NUMBER >= 19980527
! 357: ap_add_version_component("Parser/"PARSER_VERSION);
! 358: #endif
! 359:
! 360: /*
! 361: * Set up any module cells that ought to be initialised.
! 362: */
! 363: setup_module_cells();
! 364: }
! 365:
! 366: /*
! 367: * This function gets called to create a per-directory configuration
! 368: * record. This will be called for the "default" server environment, and for
! 369: * each directory for which the parser finds any of our directives applicable.
! 370: * If a directory doesn't have any of our directives involved (i.e., they
! 371: * aren't in the .htaccess file, or a <Location>, <Directory>, or related
! 372: * block), this routine will *not* be called - the configuration for the
! 373: * closest ancestor is used.
! 374: *
! 375: * The return value is a pointer to the created module-specific
! 376: * structure.
! 377: */
! 378: static void *parser_create_dir_config(pool *p, char *dirspec) {
! 379: /*
! 380: * Allocate the space for our record from the pool supplied.
! 381: */
! 382: Parser_module_config *cfg=
! 383: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
! 384: /*
! 385: * Now fill in the defaults. If there are any `parent' configuration
! 386: * records, they'll get merged as part of a separate callback.
! 387: */
! 388: cfg->parser_root_config_filespec = 0;
! 389: cfg->parser_site_config_filespec = 0;
! 390: return (void *) cfg;
! 391: }
! 392:
! 393: /*
! 394: * This function gets called to merge two per-directory configuration
! 395: * records. This is typically done to cope with things like .htaccess files
! 396: * or <Location> directives for directories that are beneath one for which a
! 397: * configuration record was already created. The routine has the
! 398: * responsibility of creating a new record and merging the contents of the
! 399: * other two into it appropriately. If the module doesn't declare a merge
! 400: * routine, the record for the closest ancestor location (that has one) is
! 401: * used exclusively.
! 402: *
! 403: * The routine MUST NOT modify any of its arguments!
! 404: *
! 405: * The return value is a pointer to the created module-specific structure
! 406: * containing the merged values.
! 407: */
! 408: static void *parser_merge_dir_config(pool *p, void *parent_conf,
! 409: void *newloc_conf) {
! 410: Parser_module_config *merged_config =
! 411: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
! 412: Parser_module_config *pconf = (Parser_module_config *) parent_conf;
! 413: Parser_module_config *nconf = (Parser_module_config *) newloc_conf;
! 414:
! 415: // always from parent
! 416: merged_config->parser_root_config_filespec = ap_pstrdup(p, pconf->parser_root_config_filespec);
! 417: /*
! 418: * Some things get copied directly from the more-specific record, rather
! 419: * than getting merged.
! 420: */
! 421: merged_config->parser_site_config_filespec = ap_pstrdup(p, nconf->parser_site_config_filespec?
! 422: nconf->parser_site_config_filespec:pconf->parser_site_config_filespec);
! 423:
! 424: return (void *) merged_config;
! 425: }
! 426:
! 427: /*
! 428: * This function gets called to create a per-server configuration
! 429: * record. It will always be called for the "default" server.
! 430: *
! 431: * The return value is a pointer to the created module-specific
! 432: * structure.
! 433: */
! 434: static void *parser_create_server_config(pool *p, server_rec *s) {
! 435: /*
! 436: * As with the parser_create_dir_config() reoutine, we allocate and fill
! 437: * in an empty record.
! 438: */
! 439: Parser_module_config *cfg=
! 440: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
! 441:
! 442: cfg->parser_root_config_filespec = 0;
! 443: cfg->parser_site_config_filespec = 0;
! 444:
! 445: return (void *) cfg;
! 446: }
! 447:
! 448: /*
! 449: * This function gets called to merge two per-server configuration
! 450: * records. This is typically done to cope with things like virtual hosts and
! 451: * the default server configuration The routine has the responsibility of
! 452: * creating a new record and merging the contents of the other two into it
! 453: * appropriately. If the module doesn't declare a merge routine, the more
! 454: * specific existing record is used exclusively.
! 455: *
! 456: * The routine MUST NOT modify any of its arguments!
! 457: *
! 458: * The return value is a pointer to the created module-specific structure
! 459: * containing the merged values.
! 460: */
! 461: static void *parser_merge_server_config(pool *p, void *server1_conf,
! 462: void *server2_conf)
! 463: {
! 464:
! 465: Parser_module_config *merged_config =
! 466: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
! 467: Parser_module_config *s1conf = (Parser_module_config *) server1_conf;
! 468: Parser_module_config *s2conf = (Parser_module_config *) server2_conf;
! 469:
! 470: /*
! 471: * Our inheritance rules are our own, and part of our module's semantics.
! 472: * Basically, just note whence we came.
! 473: */
! 474: merged_config->parser_root_config_filespec = ap_pstrdup(p, s2conf->parser_root_config_filespec?
! 475: s2conf->parser_root_config_filespec:s1conf->parser_root_config_filespec);
! 476: merged_config->parser_site_config_filespec = ap_pstrdup(p, s2conf->parser_site_config_filespec?
! 477: s2conf->parser_site_config_filespec:s1conf->parser_site_config_filespec);
! 478:
! 479: return (void *) merged_config;
! 480: }
! 481:
! 482: /*
! 483: * This routine gives our module an opportunity to translate the URI into an
! 484: * actual filename. If we don't do anything special, the server's default
! 485: * rules (Alias directives and the like) will continue to be followed.
! 486: *
! 487: * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
! 488: * further modules are called for this phase.
! 489: */
! 490: static int parser_translate_handler(request_rec *r) {
! 491: Parser_module_config *cfg=our_dconfig(r);
! 492: return DECLINED;
! 493: }
! 494:
! 495: /*
! 496: * This routine is called to check the authentication information sent with
! 497: * the request (such as looking up the user in a database and verifying that
! 498: * the [encrypted] password sent matches the one in the database).
! 499: *
! 500: * The return value is OK, DECLINED, or some HTTP_mumble error (typically
! 501: * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance
! 502: * at the request during this phase.
! 503: */
! 504: static int parser_check_user_id(request_rec *r) {
! 505: Parser_module_config *cfg=our_dconfig(r);
! 506: return DECLINED;
! 507: }
! 508:
! 509: /*
! 510: * This routine is called to check to see if the resource being requested
! 511: * requires authorisation.
! 512: *
! 513: * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
! 514: * other modules are called during this phase.
! 515: *
! 516: * If *all* modules return DECLINED, the request is aborted with a server
! 517: * error.
! 518: */
! 519: static int parser_auth_checker(request_rec *r) {
! 520: Parser_module_config *cfg=our_dconfig(r);
! 521: return DECLINED;
! 522: }
! 523:
! 524: /*
! 525: * This routine is called to check for any module-specific restrictions placed
! 526: * upon the requested resource. (See the mod_access module for an example.)
! 527: *
! 528: * The return value is OK, DECLINED, or HTTP_mumble. All modules with an
! 529: * handler for this phase are called regardless of whether their predecessors
! 530: * return OK or DECLINED. The first one to return any other status, however,
! 531: * will abort the sequence (and the request) as usual.
! 532: */
! 533: static int parser_access_checker(request_rec *r) {
! 534:
! 535: Parser_module_config *cfg=our_dconfig(r);
! 536: return DECLINED;
! 537: }
! 538:
! 539: /*--------------------------------------------------------------------------*/
! 540: /* */
! 541: /* All of the routines have been declared now. Here's the list of */
! 542: /* directives specific to our module, and information about where they */
! 543: /* may appear and how the command parser should pass them to us for */
! 544: /* processing. Note that care must be taken to ensure that there are NO */
! 545: /* collisions of directive names between modules. */
! 546: /* */
! 547: /*--------------------------------------------------------------------------*/
! 548: /*
! 549: * List of directives specific to our module.
! 550: */
! 551: static const command_rec parser_cmds[] =
! 552: {
! 553: {
! 554: DEBUG_PREFIX"ParserRootConfig", /* directive name */
! 555: (const char *(*)(void))((void *)cmd_parser_config), // config action routine
! 556: (void*)true, /* argument to include in call */
! 557: (int)(ACCESS_CONF|RSRC_CONF), /* where available */
! 558: TAKE1, /* arguments */
! 559: "Parser root config filespec (Admin)" // directive description
! 560: },
! 561: {
! 562: DEBUG_PREFIX"ParserSiteConfig", /* directive name */
! 563: (const char *(*)(void))((void *)cmd_parser_config), // config action routine
! 564: (void*)false, /* argument to include in call */
! 565: (int)(OR_OPTIONS), /* where available */
! 566: TAKE1, /* arguments */
! 567: "Parser site config filespec" // directive description
! 568: },
! 569: {NULL}
! 570: };
! 571:
! 572: /*--------------------------------------------------------------------------*/
! 573: /* */
! 574: /* Now the list of content handlers available from this module. */
! 575: /* */
! 576: /*--------------------------------------------------------------------------*/
! 577: /*
! 578: * List of content handlers our module supplies. Each handler is defined by
! 579: * two parts: a name by which it can be referenced (such as by
! 580: * {Add,Set}Handler), and the actual routine name. The list is terminated by
! 581: * a NULL block, since it can be of variable length.
! 582: *
! 583: * Note that content-handlers are invoked on a most-specific to least-specific
! 584: * basis; that is, a handler that is declared for "text/plain" will be
! 585: * invoked before one that was declared for "text / *". Note also that
! 586: * if a content-handler returns anything except DECLINED, no other
! 587: * content-handlers will be called.
! 588: */
! 589: static const handler_rec parser_handlers[] =
! 590: {
! 591: {DEBUG_PREFIX"parser3-handler", parser_handler},
! 592: {NULL}
! 593: };
! 594:
! 595: /*--------------------------------------------------------------------------*/
! 596: /* */
! 597: /* Finally, the list of callback routines and data structures that */
! 598: /* provide the hooks into our module from the other parts of the server. */
! 599: /* */
! 600: /*--------------------------------------------------------------------------*/
! 601: /*
! 602: * Module definition for configuration. If a particular callback is not
! 603: * needed, replace its routine name below with the word NULL.
! 604: *
! 605: * The number in brackets indicates the order in which the routine is called
! 606: * during request processing. Note that not all routines are necessarily
! 607: * called (such as if a resource doesn't have access restrictions).
! 608: */
! 609: module MODULE_VAR_EXPORT PARSER3_MODULE =
! 610: {
! 611: STANDARD_MODULE_STUFF,
! 612: parser_server_init, /* module initializer */
! 613: parser_create_dir_config, /* per-directory config creator */
! 614: parser_merge_dir_config, /* dir config merger */
! 615: parser_create_server_config, /* server config creator */
! 616: parser_merge_server_config, /* server config merger */
! 617: parser_cmds, /* command table */
! 618: parser_handlers, /* [9] list of handlers */
! 619: parser_translate_handler, /* [2] filename-to-URI translation */
! 620: parser_check_user_id, /* [5] check/validate user_id */
! 621: parser_auth_checker, /* [6] check user_id is valid *here* */
! 622: parser_access_checker, /* [4] check access by host address */
! 623: 0, /* [7] MIME type checker/setter */
! 624: 0, /* [8] fixups */
! 625: 0 /* [10] logger */
! 626: };
! 627:
! 628: #if defined(_MSC_VER)
! 629: # define APACHE_WIN32_SRC "/parser3project/win32apache13/src"
! 630: # ifdef _DEBUG
! 631: # pragma comment(lib, APACHE_WIN32_SRC "/CoreD/ApacheCore.lib")
! 632: # else
! 633: # pragma comment(lib, APACHE_WIN32_SRC "/CoreR/ApacheCore.lib")
! 634: # endif
! 635: #endif
E-mail: