Annotation of parser3/src/targets/apache13/mod_parser3.C, revision 1.29
1.1 parser 1: /** @file
1.29 ! paf 2: Parser: apache 1.3 module, part, compiled by Apache.
1.1 parser 3:
1.29 ! paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.17 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.25 paf 6: */
1.1 parser 7:
1.29 ! paf 8: static const char* IDENT_MOD_PARSER3_C="$Date: 2003/07/23 13:38:29 $";
1.18 paf 9:
1.1 parser 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"
1.29 ! paf 17: #include "ap_md5.h"
! 18: #include "ap_alloc.h"
1.1 parser 19:
1.29 ! paf 20: #include "pa_httpd.h"
1.1 parser 21:
22: /*
1.29 ! paf 23: * Declare ourselves so the configuration routines can find and know us.
! 24: * We'll fill it in at the end of the module.
! 25: */
! 26: extern module MODULE_VAR_EXPORT parser3_module;
1.1 parser 27:
28: /*
1.29 ! paf 29: * Locate our directory configuration record for the current request.
! 30: */
1.1 parser 31: static Parser_module_config *our_dconfig(request_rec *r) {
1.29 ! paf 32: return (Parser_module_config *)
1.9 paf 33: ap_get_module_config(r->per_dir_config, &parser3_module);
1.1 parser 34: }
35:
1.29 ! paf 36: static const char* cmd_parser_config(cmd_parms *cmd, void *mconfig, char *file_spec) {
! 37: Parser_module_config *cfg = (Parser_module_config *) mconfig;
! 38:
1.1 parser 39: // remember assigned filespec into cfg
1.22 paf 40: cfg->parser_config_filespec=file_spec;
1.29 ! paf 41:
! 42: return NULL;
1.1 parser 43: }
1.29 ! paf 44: static const char* cmd_parser_status_allowed(cmd_parms *cmd, void *mconfig, char *file_spec) {
1.9 paf 45: //_asm int 3;
1.29 ! paf 46: Parser_module_config *cfg = (Parser_module_config *) mconfig;
! 47:
! 48: cfg->parser_status_allowed=1;
! 49:
! 50: return NULL;
1.9 paf 51: }
1.1 parser 52:
53:
54: /*--------------------------------------------------------------------------*/
55: /* */
56: /* Now we declare our content handlers, which are invoked when the server */
57: /* encounters a document which our module is supposed to have a chance to */
58: /* see. (See mod_mime's SetHandler and AddHandler directives, and the */
59: /* mod_info and mod_status examples, for more details.) */
60: /* */
61: /* Since content handlers are dumping data directly into the connexion */
62: /* (using the r*() routines, such as rputs() and rprintf()) without */
63: /* intervention by other parts of the server, they need to make */
64: /* sure any accumulated HTTP headers are sent first. This is done by */
65: /* calling send_http_header(). Otherwise, no header will be sent at all, */
66: /* and the output sent to the client will actually be HTTP-uncompliant. */
67: /*--------------------------------------------------------------------------*/
68: /*
1.29 ! paf 69: * Sample content handler. All this does is display the call list that has
! 70: * been built up so far.
! 71: *
! 72: * The return value instructs the caller concerning what happened and what to
! 73: * do next:
! 74: * OK ("we did our thing")
! 75: * DECLINED ("this isn't something with which we want to get involved")
! 76: * HTTP_mumble ("an error status should be reported")
! 77: */
1.10 paf 78:
79:
1.1 parser 80: /*--------------------------------------------------------------------------*/
81: /* */
82: /* Now let's declare routines for each of the callback phase in order. */
83: /* (That's the order in which they're listed in the callback list, *not */
84: /* the order in which the server calls them! See the command_rec */
85: /* declaration near the bottom of this file.) Note that these may be */
86: /* called for situations that don't relate primarily to our function - in */
87: /* other words, the fixup handler shouldn't assume that the request has */
88: /* to do with "example" stuff. */
89: /* */
90: /* With the exception of the content handler, all of our routines will be */
91: /* called for each request, unless an earlier handler from another module */
92: /* aborted the sequence. */
93: /* */
94: /* Handlers that are declared as "int" can return the following: */
95: /* */
96: /* OK Handler accepted the request and did its thing with it. */
97: /* DECLINED Handler took no action. */
98: /* HTTP_mumble Handler looked at request and found it wanting. */
99: /* */
100: /* What the server does after calling a module handler depends upon the */
101: /* handler's return value. In all cases, if the handler returns */
102: /* DECLINED, the server will continue to the next module with an handler */
103: /* for the current phase. However, if the handler return a non-OK, */
104: /* non-DECLINED status, the server aborts the request right there. If */
105: /* the handler returns OK, the server's next action is phase-specific; */
106: /* see the individual handler comments below for details. */
107: /* */
108: /*--------------------------------------------------------------------------*/
1.10 paf 109:
1.29 ! paf 110: static int parser_handler(request_rec *ar) {
! 111: // record clone
! 112: pa_request_rec lr={
! 113: ar,
! 114: ar->pool,
! 115: ar->header_only,
! 116: ar->status,
! 117: ar->method,
! 118: ar->headers_out,
! 119: ar->subprocess_env,
! 120: ar->content_type,
! 121: ar->uri,
! 122: ar->filename,
! 123: ar->path_info,
! 124: ar->args,
! 125: &ar->finfo
! 126: };
1.10 paf 127:
1.29 ! paf 128: // config
! 129: Parser_module_config *dcfg=our_dconfig(ar);
! 130:
! 131: return pa_parser_handler(&lr, dcfg);
! 132: }
1.1 parser 133:
1.29 ! paf 134: /*
! 135: * This function is called during server initialisation. Any information
! 136: * that needs to be recorded must be in static cells, since there's no
! 137: * configuration record.
! 138: *
! 139: * There is no return value.
! 140: */
1.1 parser 141:
142: static void parser_server_init(server_rec *s, pool *p) {
143: #if MODULE_MAGIC_NUMBER >= 19980527
1.29 ! paf 144: ap_add_version_component(pa_version());
1.1 parser 145: #endif
1.29 ! paf 146:
! 147: /*
! 148: * Set up any module cells that ought to be initialised.
! 149: */
! 150: pa_setup_module_cells();
1.1 parser 151: }
152:
153: /*
1.29 ! paf 154: * This function gets called to create a per-directory configuration
! 155: * record. This will be called for the "default" server environment, and for
! 156: * each directory for which the parser finds any of our directives applicable.
! 157: * If a directory doesn't have any of our directives involved (i.e., they
! 158: * aren't in the .htaccess file, or a <Location>, <Directory>, or related
! 159: * block), this routine will *not* be called - the configuration for the
! 160: * closest ancestor is used.
! 161: *
! 162: * The return value is a pointer to the created module-specific
! 163: * structure.
! 164: */
1.1 parser 165: static void *parser_create_dir_config(pool *p, char *dirspec) {
1.13 paf 166: //_asm int 3;
1.1 parser 167: /*
1.29 ! paf 168: * Allocate the space for our record from the pool supplied.
! 169: */
! 170: Parser_module_config *cfg=
1.1 parser 171: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
1.29 ! paf 172: /*
! 173: * Now fill in the defaults. If there are any `parent' configuration
! 174: * records, they'll get merged as part of a separate callback.
! 175: */
! 176:
! 177: return (void *) cfg;
1.1 parser 178: }
179:
180: /*
1.29 ! paf 181: * This function gets called to merge two per-directory configuration
! 182: * records. This is typically done to cope with things like .htaccess files
! 183: * or <Location> directives for directories that are beneath one for which a
! 184: * configuration record was already created. The routine has the
! 185: * responsibility of creating a new record and merging the contents of the
! 186: * other two into it appropriately. If the module doesn't declare a merge
! 187: * routine, the record for the closest ancestor location (that has one) is
! 188: * used exclusively.
! 189: *
! 190: * The routine MUST NOT modify any of its arguments!
! 191: *
! 192: * The return value is a pointer to the created module-specific structure
! 193: * containing the merged values.
1.13 paf 194:
1.29 ! paf 195: 20011126 paf: noticed, that this is called even on virtual root merge with something "parent",
! 196: while thought that that is part of merge_server...
! 197:
! 198: */
1.1 parser 199: static void *parser_merge_dir_config(pool *p, void *parent_conf,
1.29 ! paf 200: void *newloc_conf) {
1.13 paf 201: //_asm int 3;
1.29 ! paf 202: Parser_module_config *merged_config =
1.1 parser 203: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
1.29 ! paf 204: Parser_module_config *pconf = (Parser_module_config *) parent_conf;
! 205: Parser_module_config *nconf = (Parser_module_config *) newloc_conf;
! 206:
! 207: merged_config->parser_config_filespec = ap_pstrdup(p, nconf->parser_config_filespec?
1.22 paf 208: nconf->parser_config_filespec:pconf->parser_config_filespec);
1.9 paf 209: merged_config->parser_status_allowed=
210: pconf->parser_status_allowed ||
211: nconf->parser_status_allowed;
1.29 ! paf 212:
! 213: /*
! 214: * Some things get copied directly from the more-specific record, rather
! 215: * than getting merged.
! 216: */
! 217:
! 218: return (void *) merged_config;
1.1 parser 219: }
220:
221: /*
1.29 ! paf 222: * This function gets called to create a per-server configuration
! 223: * record. It will always be called for the "default" server.
! 224: *
! 225: * The return value is a pointer to the created module-specific
! 226: * structure.
! 227: */
1.1 parser 228: static void *parser_create_server_config(pool *p, server_rec *s) {
1.13 paf 229: //_asm int 3;
1.29 ! paf 230: /*
! 231: * As with the parser_create_dir_config() routine, we allocate and fill
! 232: * in an empty record.
! 233: */
! 234: Parser_module_config *cfg=
1.1 parser 235: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
1.29 ! paf 236:
! 237: return (void *) cfg;
1.1 parser 238: }
239:
240: /*
1.29 ! paf 241: * This function gets called to merge two per-server configuration
! 242: * records. This is typically done to cope with things like virtual hosts and
! 243: * the default server configuration The routine has the responsibility of
! 244: * creating a new record and merging the contents of the other two into it
! 245: * appropriately. If the module doesn't declare a merge routine, the more
! 246: * specific existing record is used exclusively.
! 247: *
! 248: * The routine MUST NOT modify any of its arguments!
! 249: *
! 250: * The return value is a pointer to the created module-specific structure
! 251: * containing the merged values.
! 252: */
1.1 parser 253: static void *parser_merge_server_config(pool *p, void *server1_conf,
1.29 ! paf 254: void *server2_conf)
1.1 parser 255: {
1.13 paf 256: //_asm int 3;
1.29 ! paf 257:
! 258: Parser_module_config *merged_config =
1.1 parser 259: (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
1.29 ! paf 260: Parser_module_config *s1conf = (Parser_module_config *) server1_conf;
! 261: Parser_module_config *s2conf = (Parser_module_config *) server2_conf;
! 262:
! 263: /*
! 264: * Our inheritance rules are our own, and part of our module's semantics.
! 265: * Basically, just note whence we came.
! 266: */
! 267: merged_config->parser_config_filespec = ap_pstrdup(p, s2conf->parser_config_filespec?
1.22 paf 268: s2conf->parser_config_filespec:s1conf->parser_config_filespec);
1.9 paf 269: merged_config->parser_status_allowed=
270: s1conf->parser_status_allowed ||
271: s2conf->parser_status_allowed;
1.29 ! paf 272:
1.1 parser 273: return (void *) merged_config;
274: }
275:
276: /*
1.29 ! paf 277: * This routine gives our module an opportunity to translate the URI into an
! 278: * actual filename. If we don't do anything special, the server's default
! 279: * rules (Alias directives and the like) will continue to be followed.
! 280: *
! 281: * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
! 282: * further modules are called for this phase.
! 283: */
1.1 parser 284: static int parser_translate_handler(request_rec *r) {
1.29 ! paf 285: Parser_module_config *cfg=our_dconfig(r);
! 286: return DECLINED;
1.1 parser 287: }
288:
289: /*
1.29 ! paf 290: * This routine is called to check the authentication information sent with
! 291: * the request (such as looking up the user in a database and verifying that
! 292: * the [encrypted] password sent matches the one in the database).
! 293: *
! 294: * The return value is OK, DECLINED, or some HTTP_mumble error (typically
! 295: * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance
! 296: * at the request during this phase.
! 297: */
1.1 parser 298: static int parser_check_user_id(request_rec *r) {
1.29 ! paf 299: Parser_module_config *cfg=our_dconfig(r);
! 300: return DECLINED;
1.1 parser 301: }
302:
303: /*
1.29 ! paf 304: * This routine is called to check to see if the resource being requested
! 305: * requires authorisation.
! 306: *
! 307: * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
! 308: * other modules are called during this phase.
! 309: *
! 310: * If *all* modules return DECLINED, the request is aborted with a server
! 311: * error.
! 312: */
1.1 parser 313: static int parser_auth_checker(request_rec *r) {
1.29 ! paf 314: Parser_module_config *cfg=our_dconfig(r);
! 315: return DECLINED;
1.1 parser 316: }
317:
318: /*
1.29 ! paf 319: * This routine is called to check for any module-specific restrictions placed
! 320: * upon the requested resource. (See the mod_access module for an example.)
! 321: *
! 322: * The return value is OK, DECLINED, or HTTP_mumble. All modules with an
! 323: * handler for this phase are called regardless of whether their predecessors
! 324: * return OK or DECLINED. The first one to return any other status, however,
! 325: * will abort the sequence (and the request) as usual.
! 326: */
1.1 parser 327: static int parser_access_checker(request_rec *r) {
1.29 ! paf 328:
! 329: Parser_module_config *cfg=our_dconfig(r);
! 330: return DECLINED;
1.1 parser 331: }
332:
333: /*--------------------------------------------------------------------------*/
334: /* */
335: /* All of the routines have been declared now. Here's the list of */
336: /* directives specific to our module, and information about where they */
337: /* may appear and how the command parser should pass them to us for */
338: /* processing. Note that care must be taken to ensure that there are NO */
339: /* collisions of directive names between modules. */
340: /* */
341: /*--------------------------------------------------------------------------*/
342: /*
1.29 ! paf 343: * List of directives specific to our module.
! 344: */
1.1 parser 345: static const command_rec parser_cmds[] =
346: {
1.29 ! paf 347: {
! 348: "ParserConfig", /* directive name */
! 349: (const char* (*)(void))((void *)cmd_parser_config), // config action routine
! 350: (void*)0, /* argument to include in call */
! 351: (int)(OR_OPTIONS), /* where available */
! 352: TAKE1, /* arguments */
! 353: "Parser config filespec" // directive description
! 354: },
1.9 paf 355: {
356: "ParserStatusAllowed", /* directive name */
1.29 ! paf 357: (const char* (*)(void))((void *)cmd_parser_status_allowed), // config action routine
! 358: (void*)0, /* argument to include in call */
! 359: (int)(ACCESS_CONF), /* where available */
! 360: NO_ARGS, /* arguments */
! 361: "Parser status class can be used" // directive description
1.9 paf 362: },
1.29 ! paf 363: {NULL}
1.1 parser 364: };
365:
366: /*--------------------------------------------------------------------------*/
367: /* */
368: /* Now the list of content handlers available from this module. */
369: /* */
370: /*--------------------------------------------------------------------------*/
371: /*
1.29 ! paf 372: * List of content handlers our module supplies. Each handler is defined by
! 373: * two parts: a name by which it can be referenced (such as by
! 374: * {Add,Set}Handler), and the actual routine name. The list is terminated by
! 375: * a NULL block, since it can be of variable length.
! 376: *
! 377: * Note that content-handlers are invoked on a most-specific to least-specific
! 378: * basis; that is, a handler that is declared for "text/plain" will be
! 379: * invoked before one that was declared for "text / *". Note also that
! 380: * if a content-handler returns anything except DECLINED, no other
! 381: * content-handlers will be called.
! 382: */
1.1 parser 383: static const handler_rec parser_handlers[] =
384: {
1.29 ! paf 385: {"parser3-handler", parser_handler},
! 386: {NULL}
1.1 parser 387: };
388:
389: /*--------------------------------------------------------------------------*/
390: /* */
391: /* Finally, the list of callback routines and data structures that */
392: /* provide the hooks into our module from the other parts of the server. */
393: /* */
394: /*--------------------------------------------------------------------------*/
395: /*
1.29 ! paf 396: * Module definition for configuration. If a particular callback is not
! 397: * needed, replace its routine name below with the word NULL.
! 398: *
! 399: * The number in brackets indicates the order in which the routine is called
! 400: * during request processing. Note that not all routines are necessarily
! 401: * called (such as if a resource doesn't have access restrictions).
! 402: */
1.9 paf 403: module MODULE_VAR_EXPORT parser3_module =
1.1 parser 404: {
1.29 ! paf 405: STANDARD_MODULE_STUFF,
! 406: parser_server_init, /* module initializer */
! 407: parser_create_dir_config, /* per-directory config creator */
! 408: parser_merge_dir_config, /* dir config merger */
! 409: parser_create_server_config, /* server config creator */
! 410: parser_merge_server_config, /* server config merger */
! 411: parser_cmds, /* command table */
! 412: parser_handlers, /* [9] list of handlers */
! 413: parser_translate_handler, /* [2] filename-to-URI translation */
! 414: parser_check_user_id, /* [5] check/validate user_id */
! 415: parser_auth_checker, /* [6] check user_id is valid *here* */
! 416: parser_access_checker, /* [4] check access by host address */
! 417: 0, /* [7] MIME type checker/setter */
! 418: 0, /* [8] fixups */
! 419: 0 /* [10] logger */
1.1 parser 420: };
421:
422: #if defined(_MSC_VER)
1.20 paf 423: # define APACHE_WIN32_SRC "/parser3project/win32/apache13/src"
1.1 parser 424: # ifdef _DEBUG
425: # pragma comment(lib, APACHE_WIN32_SRC "/CoreD/ApacheCore.lib")
426: # else
427: # pragma comment(lib, APACHE_WIN32_SRC "/CoreR/ApacheCore.lib")
428: # endif
429: #endif
1.29 ! paf 430:
! 431:
! 432: // interface to C++
! 433:
! 434: #define PA_APLOG_EMERG 0 /* system is unusable */
! 435: #define PA_APLOG_ALERT 1 /* action must be taken immediately */
! 436: #define PA_APLOG_CRIT 2 /* critical conditions */
! 437: #define PA_APLOG_ERR 3 /* error conditions */
! 438: #define PA_APLOG_WARNING 4 /* warning conditions */
! 439: #define PA_APLOG_NOTICE 5 /* normal but significant condition */
! 440: #define PA_APLOG_INFO 6 /* informational */
! 441: #define PA_APLOG_DEBUG 7 /* debug-level messages */
! 442:
! 443: #define PA_APLOG_LEVELMASK 7 /* mask off the level value */
! 444:
! 445: #define PA_APLOG_NOERRNO (PA_APLOG_LEVELMASK + 1)
! 446:
! 447: #define PA_APLOG_MARK __FILE__,__LINE__
! 448:
! 449: void pa_ap_log_rerror(const char *file, int line, int level,
! 450: const pa_request_rec *s, const char *fmt, ...) {
! 451: const char* str;
! 452: va_list l;
! 453: va_start(l, fmt);
! 454: str=va_arg(l, const char*);
! 455: va_end(l);
! 456:
! 457: ap_log_rerror(file, line, level,
! 458: (request_rec*)s->real_request_rec, "%s", str);
! 459: }
! 460:
! 461:
! 462: void pa_ap_log_error(const char *file, int line, int level,
! 463: const pa_server_rec *s, const char *fmt, ...) {
! 464: const char* str;
! 465: va_list l;
! 466: va_start(l, fmt);
! 467: str=va_arg(l, const char*);
! 468: va_end(l);
! 469:
! 470: ap_log_error(file, line, level,
! 471: (server_rec*)s, "%s", str);
! 472: }
! 473:
! 474: // ap_alloc.h
! 475:
! 476: const char* pa_ap_table_get(const pa_table *t, const char *name) {
! 477: return ap_table_get((const table*)t, name);
! 478: }
! 479: void pa_ap_table_addn(pa_table *t, const char *name, const char *val) {
! 480: ap_table_addn((table*)t, name, val);
! 481: }
! 482:
! 483: int pa_ap_table_size(const pa_table *t) {
! 484: return ap_table_elts((const table*)t)->nelts;
! 485: }
! 486:
! 487: void pa_ap_table_do(int (*comp) (void *, const char *, const char *),
! 488: void *rec, const pa_table *t, ...) {
! 489: ap_table_do(comp, rec, (table*)t, 0);
! 490: }
! 491:
! 492: char * pa_ap_pstrdup(pa_pool *p, const char *s) {
! 493: return ap_pstrdup((pool*)p, s);
! 494: }
! 495:
! 496: // http_protocol.h
! 497:
! 498: int pa_ap_setup_client_block(pa_request_rec *r, int read_policy) {
! 499: return ap_setup_client_block((request_rec*)r->real_request_rec,
! 500: read_policy);
! 501: }
! 502: int pa_ap_should_client_block(pa_request_rec *r) {
! 503: return ap_should_client_block((request_rec*)r->real_request_rec);
! 504: }
! 505: long pa_ap_get_client_block(pa_request_rec *r, char *buffer, int bufsiz) {
! 506: return ap_get_client_block((request_rec*)r->real_request_rec,
! 507: buffer, bufsiz);
! 508: }
! 509: void pa_ap_send_http_header(pa_request_rec *r) {
! 510: ap_send_http_header((request_rec*)r->real_request_rec);
! 511: }
! 512: int pa_ap_rwrite(const void *buf, int nbyte, pa_request_rec *r) {
! 513: return ap_rwrite(buf, nbyte, (request_rec*)r->real_request_rec);
! 514: }
! 515:
! 516:
! 517: // http_main.h
! 518:
! 519: void pa_ap_hard_timeout(char *s, pa_request_rec *r) {
! 520: ap_hard_timeout(s, (request_rec*)r->real_request_rec);
! 521: }
! 522: void pa_ap_reset_timeout(pa_request_rec *r) {
! 523: ap_reset_timeout((request_rec*)r->real_request_rec);
! 524: }
! 525: void pa_ap_kill_timeout(pa_request_rec *r) {
! 526: ap_kill_timeout((request_rec*)r->real_request_rec);
! 527: }
! 528:
! 529:
! 530: // util_script.h
! 531:
! 532: void pa_ap_add_cgi_vars(pa_request_rec *r) {
! 533: ap_add_cgi_vars((request_rec*)r->real_request_rec);
! 534: }
! 535: void pa_ap_add_common_vars(pa_request_rec *r) {
! 536: ap_add_common_vars((request_rec*)r->real_request_rec);
! 537: }
! 538:
! 539:
! 540: // ap_md5.h
! 541:
! 542: void pa_MD5Init(PA_MD5_CTX *context) { ap_MD5Init((AP_MD5_CTX*)context); }
! 543: void pa_MD5Update(PA_MD5_CTX *context, const unsigned char *input,
! 544: unsigned int inputLen) { ap_MD5Update((AP_MD5_CTX *)context, input, inputLen); }
! 545: void pa_MD5Final(unsigned char digest[MD5_DIGESTSIZE],
! 546: PA_MD5_CTX *context) { ap_MD5Final(digest, (AP_MD5_CTX *)context); }
! 547: void pa_MD5Encode(const unsigned char *password,
! 548: const unsigned char *salt,
! 549: char *result, size_t nbytes) { ap_MD5Encode(password, salt, result, nbytes); }
! 550: void pa_to64(char *s, unsigned long v, int n) { ap_to64(s, v, n); }
! 551:
! 552:
! 553: // signal.h
! 554:
! 555: void (*pa_signal (int sig, void (*disp)(int)))(int) {
! 556: if(sig==PA_SIGPIPE && disp==PA_SIG_IGN)
! 557: return signal(SIGPIPE, SIG_IGN);
! 558:
! 559: return 0;
! 560: }
E-mail: