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