Annotation of parser3/src/targets/apache/mod_parser3.c, revision 1.1

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

E-mail: