Annotation of parser3/src/targets/apache/mod_parser3_core.C, revision 1.1

1.1     ! moko        1: /** @file
        !             2: Parser: apache 1.3 module, part, compiled by parser3project.
        !             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_MAIN_C="$Date: 2009-10-06 11:40:23 $";
        !             9: 
        !            10: #include "pa_config_includes.h"
        !            11: 
        !            12: #include "pa_globals.h"
        !            13: 
        !            14: #include "pa_httpd.h"
        !            15: 
        !            16: #include "pa_common.h"
        !            17: #include "pa_sapi.h"
        !            18: #include "classes.h"
        !            19: #include "pa_request.h"
        !            20: #include "pa_version.h"
        !            21: #include "pa_socks.h"
        !            22: 
        !            23: #if _MSC_VER && !defined(_DEBUG)
        !            24: #      include <windows.h>
        !            25: #      define PA_SUPPRESS_SYSTEM_EXCEPTION
        !            26: #endif
        !            27: 
        !            28: // generals
        !            29: 
        !            30: const char* pa_version() {
        !            31:        return "Parser/"PARSER_VERSION;
        !            32: }
        !            33: 
        !            34: void pa_setup_module_cells() {
        !            35:        static bool  globals_inited=false;
        !            36:        if(globals_inited)
        !            37:                return;
        !            38:        globals_inited=true;
        !            39:        
        !            40:        /// no trying to __try here [yet]
        !            41:        try {
        !            42:                // init socks
        !            43:                pa_socks_init();
        !            44:                
        !            45:                // init global variables
        !            46:                pa_globals_init();
        !            47:        } catch(const Exception& e) { // global problem 
        !            48:                SAPI::abort("setup_module_cells failed: %s", e.comment());
        !            49:        }
        !            50: }
        !            51: 
        !            52: void pa_destroy_module_cells() {
        !            53:        pa_globals_done();
        !            54: 
        !            55:        pa_socks_done();
        !            56: }
        !            57: 
        !            58: 
        !            59: //@{
        !            60: /// SAPI func decl
        !            61: 
        !            62: class SAPI_Info {
        !            63: public:
        !            64:        pa_request_rec* r;
        !            65: };
        !            66: 
        !            67: void SAPI::log(SAPI_Info& SAPI_info, const char* fmt, ...) {
        !            68:        va_list args;
        !            69:        va_start(args,fmt);
        !            70:        char buf[MAX_LOG_STRING];
        !            71:        size_t size=vsnprintf(buf, MAX_LOG_STRING, fmt, args);
        !            72:        size=remove_crlf(buf, buf+size);
        !            73:        pa_ap_log_rerror(0, 0, PA_APLOG_ERR | PA_APLOG_NOERRNO, SAPI_info.r, "%s", buf);
        !            74:        va_end(args);
        !            75: }
        !            76: 
        !            77: static void die_or_abort(const char* fmt, va_list args, bool write_core) {
        !            78:        char buf[MAX_LOG_STRING];
        !            79:        size_t size=vsnprintf(buf, MAX_LOG_STRING, fmt, args);
        !            80:        size=remove_crlf(buf, buf+size);
        !            81:        pa_ap_log_error(PA_APLOG_MARK, PA_APLOG_EMERG, 0, "%s", buf);
        !            82:        
        !            83:        // exit & try to produce core dump
        !            84:        if(write_core)
        !            85:                abort();
        !            86:        else
        !            87:                exit(1);
        !            88: }
        !            89: 
        !            90: void SAPI::die(const char* fmt, ...) {
        !            91:        va_list args;
        !            92:        va_start(args, fmt);
        !            93:        die_or_abort(fmt, args, false/*write core?*/);
        !            94:        va_end(args);
        !            95: }
        !            96: 
        !            97: void SAPI::abort(const char* fmt, ...) {
        !            98:        va_list args;
        !            99:        va_start(args, fmt);
        !           100:        die_or_abort(fmt, args, true/*write core?*/);
        !           101:        va_end(args);
        !           102: }
        !           103: 
        !           104: char* SAPI::get_env(SAPI_Info& SAPI_info, const char* name) {
        !           105:        const char* dont_return_me=pa_ap_table_get(SAPI_info.r->subprocess_env, name);
        !           106:        return dont_return_me?pa_strdup(dont_return_me):0;
        !           107: }
        !           108: 
        !           109: #ifndef DOXYGEN
        !           110: struct SAPI_environment_append_info {
        !           111:        const char** cur;
        !           112: };
        !           113: #endif
        !           114: static const char* mk_env_pair(const char* key, const char* value) {
        !           115:        char *result=new(PointerFreeGC) char[strlen(key)+1/*=*/+strlen(value)+1/*0*/];
        !           116:        strcpy(result, key); strcat(result, "="); strcat(result, value);
        !           117:        return result;
        !           118: }
        !           119: static int SAPI_environment_append(void *d, const char* k, const char* val) {
        !           120:        if( k && val ) {
        !           121:                SAPI_environment_append_info& info=
        !           122:                        *static_cast<SAPI_environment_append_info *>(d);
        !           123:                *info.cur++=mk_env_pair(k, val);
        !           124:        }
        !           125:        return 1/*true*/;
        !           126: }
        !           127: const char* const* SAPI::environment(SAPI_Info& SAPI_info) {
        !           128:        const pa_table *t=SAPI_info.r->subprocess_env;
        !           129:        const char** result=new(UseGC) const char*[pa_ap_table_size(t)+1/*0*/];
        !           130:        SAPI_environment_append_info info={result};
        !           131:        pa_ap_table_do(SAPI_environment_append, &info, t, 0); *info.cur=0; // mark EOE
        !           132:        return result;
        !           133: }
        !           134: 
        !           135: size_t SAPI::read_post(SAPI_Info& SAPI_info, char *buf, size_t max_bytes) {
        !           136: /*    pa_ap_log_error(PA_APLOG_MARK, PA_APLOG_DEBUG, SAPI_info.r->server, 
        !           137: "mod_parser3: SAPI::read_post(max=%u)", max_bytes);
        !           138:        */
        !           139:        int retval;
        !           140:        if((retval = pa_ap_setup_client_block(SAPI_info.r, PA_REQUEST_CHUNKED_ERROR)))
        !           141:                return 0;
        !           142:        if(!pa_ap_should_client_block(SAPI_info.r))
        !           143:                return 0;
        !           144:        
        !           145:        uint total_read_bytes=0;
        !           146:        void (*handler)(int)=pa_signal(PA_SIGPIPE, PA_SIG_IGN);
        !           147:        while (total_read_bytes<max_bytes) {
        !           148:                pa_ap_hard_timeout("Read POST information", SAPI_info.r); /* start timeout timer */
        !           149:                uint read_bytes=
        !           150:                        pa_ap_get_client_block(SAPI_info.r, buf+total_read_bytes, max_bytes-total_read_bytes);
        !           151:                pa_ap_reset_timeout(SAPI_info.r);
        !           152:                if (read_bytes<=0)
        !           153:                        break;
        !           154:                total_read_bytes+=read_bytes;
        !           155:        }
        !           156:        pa_signal(PA_SIGPIPE, handler);
        !           157:        return total_read_bytes;
        !           158: }
        !           159: 
        !           160: /// @test location provide with protocol. think about internal redirects
        !           161: void SAPI::add_header_attribute(SAPI_Info& SAPI_info,
        !           162:                                const char* dont_store_key, const char* dont_store_value) {
        !           163:        if(strcasecmp(dont_store_key, "location")==0) 
        !           164:                *SAPI_info.r->status=302;
        !           165:        
        !           166:        if(strcasecmp(dont_store_key, HTTP_CONTENT_TYPE)==0) {
        !           167:        /* r->content_type, *not* r->headers_out("Content-type").  If you don't
        !           168:        * set it, it will be filled in with the server's default type (typically
        !           169:        * "text/plain").  You *must* also ensure that r->content_type is lower
        !           170:        * case.
        !           171:                */
        !           172:                *SAPI_info.r->content_type = pa_ap_pstrdup(SAPI_info.r->pool, dont_store_value);
        !           173:        } else if(strcasecmp(dont_store_key, HTTP_STATUS)==0) 
        !           174:                *SAPI_info.r->status=atoi(dont_store_value);
        !           175:        else
        !           176:                pa_ap_table_addn(SAPI_info.r->headers_out, 
        !           177:                pa_ap_pstrdup(SAPI_info.r->pool, capitalize(dont_store_key)), 
        !           178:                pa_ap_pstrdup(SAPI_info.r->pool, dont_store_value));
        !           179: }
        !           180: 
        !           181: void SAPI::send_header(SAPI_Info& SAPI_info) {
        !           182:        pa_ap_hard_timeout("Send header", SAPI_info.r);
        !           183:        pa_ap_send_http_header(SAPI_info.r);
        !           184:        pa_ap_kill_timeout(SAPI_info.r);
        !           185: }
        !           186: 
        !           187: size_t SAPI::send_body(SAPI_Info& SAPI_info, const void *buf, size_t size) {
        !           188:        pa_ap_hard_timeout("Send body", SAPI_info.r);
        !           189:        size = (size_t)pa_ap_rwrite(buf, size, SAPI_info.r);
        !           190:        pa_ap_kill_timeout(SAPI_info.r);
        !           191:        return size;
        !           192: }
        !           193: 
        !           194: //@}
        !           195: 
        !           196: #if !defined(PA_DEBUG_DISABLE_GC) && !defined(WIN32)
        !           197: extern long GC_large_alloc_warn_suppressed; 
        !           198: #endif
        !           199: 
        !           200: /**
        !           201: main workhorse
        !           202: 
        !           203:        @todo intelligent cache-control
        !           204: */
        !           205: static void real_parser_handler(SAPI_Info& SAPI_info, Parser_module_config *dcfg) {
        !           206:        // collect garbage from prev request
        !           207: #if !defined(PA_DEBUG_DISABLE_GC) && !defined(WIN32)
        !           208:        {
        !           209:                int saved=GC_dont_gc;
        !           210:                GC_dont_gc=0;
        !           211:                GC_gcollect();
        !           212:                GC_dont_gc=saved;
        !           213:                GC_large_alloc_warn_suppressed=0;
        !           214:        }
        !           215: #endif
        !           216: 
        !           217:        // populate env
        !           218:        pa_ap_add_common_vars(SAPI_info.r);
        !           219:        pa_ap_add_cgi_vars(SAPI_info.r);
        !           220:        
        !           221:        // Request info
        !           222:        Request_info request_info;  memset(&request_info, 0, sizeof(request_info));
        !           223:        
        !           224:        request_info.document_root=SAPI::get_env(SAPI_info, "DOCUMENT_ROOT");
        !           225:        request_info.path_translated=SAPI_info.r->filename;
        !           226:        request_info.method=SAPI_info.r->method;
        !           227:        request_info.query_string=SAPI_info.r->args;
        !           228:        request_info.uri=SAPI::get_env(SAPI_info, "REQUEST_URI");
        !           229:        request_info.content_type=SAPI::get_env(SAPI_info, "CONTENT_TYPE");
        !           230:        const char* content_length=SAPI::get_env(SAPI_info, "CONTENT_LENGTH");
        !           231:        request_info.content_length=content_length?atoi(content_length):0;
        !           232:        request_info.cookie=SAPI::get_env(SAPI_info, "HTTP_COOKIE");
        !           233:        request_info.mail_received=false;
        !           234:        
        !           235:        //_asm int 3;
        !           236:        // prepare to process request
        !           237:        Request request(
        !           238:                SAPI_info,
        !           239:                request_info,
        !           240:                String::Language(String::L_HTML|String::L_OPTIMIZE_BIT),
        !           241:                dcfg->parser_status_allowed?true:false
        !           242:                );
        !           243:        
        !           244:        // process the request
        !           245:        request.core(
        !           246:                dcfg->parser_config_filespec, true, // /path/to/config
        !           247:                SAPI_info.r->header_only!=0);
        !           248: }
        !           249: 
        !           250: #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
        !           251: static const Exception 
        !           252: call_real_parser_handler__do_PEH_return_it(
        !           253:        SAPI_Info& SAPI_info, Parser_module_config *dcfg) 
        !           254: {
        !           255:        try {
        !           256:                real_parser_handler(SAPI_info, dcfg);
        !           257:        } catch(const Exception& e) {
        !           258:                return e;
        !           259:        }
        !           260: 
        !           261:        return Exception();
        !           262: }
        !           263: static void call_real_parser_handler__supress_system_exception(
        !           264:        SAPI_Info& SAPI_info, Parser_module_config *dcfg) 
        !           265: {
        !           266:        Exception parser_exception;
        !           267:        LPEXCEPTION_POINTERS system_exception=0;
        !           268: 
        !           269:        __try {
        !           270:                parser_exception=call_real_parser_handler__do_PEH_return_it(
        !           271:                        SAPI_info, dcfg);
        !           272:        } __except (
        !           273:                (system_exception=GetExceptionInformation()), 
        !           274:                EXCEPTION_EXECUTE_HANDLER) 
        !           275:        {
        !           276: 
        !           277:                if(system_exception)
        !           278:                        if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
        !           279:                                throw Exception("system",
        !           280:                                        0,
        !           281:                                        "0x%08X at 0x%08X", er->ExceptionCode,  er->ExceptionAddress);
        !           282:                        else
        !           283:                                throw Exception("system", 
        !           284:                                        0, 
        !           285:                                        "<no exception record>");
        !           286:                else
        !           287:                        throw Exception("system", 
        !           288:                                0, 
        !           289:                                "<no exception information>");
        !           290:        }
        !           291: 
        !           292:        if(parser_exception)
        !           293:                throw Exception(parser_exception);
        !           294: }
        !           295: #endif
        !           296: 
        !           297: /// @test r->finfo.st_mode check seems to work only on win32
        !           298: int pa_parser_handler(pa_request_rec *r, Parser_module_config *dcfg) {
        !           299:        //_asm int 3;
        !           300: 
        !           301:        // SAPI info
        !           302:        SAPI_Info SAPI_info; SAPI_info.r=r;
        !           303:        
        !           304:        //_asm int 3;
        !           305:        if(r->finfo->st_mode == 0) 
        !           306:                return PA_HTTP_NOT_FOUND;
        !           307:        
        !           308:                /* A flag which modules can set, to indicate that the data being
        !           309:                * returned is volatile, and clients should be told not to cache it.
        !           310:        */
        !           311:        //      r->no_cache=1;
        !           312:        
        !           313:        try { // global try
        !           314: #ifdef PA_SUPPRESS_SYSTEM_EXCEPTION
        !           315:                call_real_parser_handler__supress_system_exception(
        !           316: #else
        !           317:                real_parser_handler(
        !           318: #endif
        !           319:                        SAPI_info, dcfg);
        !           320: 
        !           321:                // successful finish
        !           322:        } catch(const Exception& e) { // global problem 
        !           323:                // don't allocate anything on pool here:
        !           324:                //   possible pool' exception not catch-ed now
        !           325:                //   and there could be out-of-memory exception
        !           326:                char buf[MAX_STRING];
        !           327:                snprintf(buf, MAX_STRING, "Unhandled exception %s",
        !           328:                        e.comment());
        !           329:                // log it
        !           330:                SAPI::log(SAPI_info, "%s", buf);
        !           331:                
        !           332:                //
        !           333:                int content_length=strlen(buf);
        !           334:                
        !           335:                // prepare header
        !           336:                // capitalized headers are used for preventing malloc during capitalization
        !           337:                SAPI::add_header_attribute(SAPI_info, HTTP_CONTENT_TYPE_CAPITALIZED, "text/plain");
        !           338:                // don't use 'format' function because it calls malloc
        !           339:                char content_length_cstr[MAX_NUMBER];
        !           340:                snprintf(content_length_cstr, MAX_NUMBER, "%u", content_length);
        !           341:                SAPI::add_header_attribute(SAPI_info, HTTP_CONTENT_LENGTH_CAPITALIZED, content_length_cstr);
        !           342:                
        !           343:                // send header
        !           344:                SAPI::send_header(SAPI_info);
        !           345:                
        !           346:                // send body
        !           347:                if(!r->header_only)
        !           348:                        SAPI::send_body(SAPI_info, buf, content_length);
        !           349:                
        !           350:                // unsuccessful finish
        !           351:        }
        !           352:        
        !           353:        /*
        !           354:        * We did what we wanted to do, so tell the rest of the server we
        !           355:        * succeeded.
        !           356:        */
        !           357:        return PA_OK;
        !           358: }

E-mail: