Annotation of parser3/src/targets/apache13core/mod_parser3.C, revision 1.2

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

E-mail: