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: