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: