Annotation of parser3/src/targets/apache13/mod_parser3_main.C, revision 1.1.2.1

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

E-mail: