Annotation of parser3/src/targets/isapi/parser3isapi.C, revision 1.1
1.1 ! paf 1: #ifndef _MSC_VER
! 2: # error compile ISAPI module with MSVC
! 3: #endif
! 4:
! 5: #include <windows.h>
! 6: #include <process.h>
! 7:
! 8: #include <httpext.h>
! 9: #include <httpfilt.h>
! 10: #include <httpext.h>
! 11:
! 12: #include "pa_globals.h"
! 13: #include "pa_request.h"
! 14: #include "pa_version.h"
! 15:
! 16: #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION")
! 17: #define ISAPI_SERVER_VAR_BUF_SIZE 0x400
! 18:
! 19: //@{
! 20: /// service func decl
! 21: static const char *get_env(Pool& pool, const char *name) {
! 22: LPEXTENSION_CONTROL_BLOCK lpECB=static_cast<LPEXTENSION_CONTROL_BLOCK>(pool.context());
! 23:
! 24: char *variable_buf=(char *)pool.malloc(MAX_STRING);
! 25: DWORD variable_len = MAX_STRING-1;
! 26:
! 27: if(lpECB->GetServerVariable(lpECB->ConnID, const_cast<char *>(name),
! 28: variable_buf, &variable_len)) {
! 29: variable_buf[variable_len]=0;
! 30: return variable_buf;
! 31: }
! 32:
! 33: variable_buf=(char *)pool.malloc(variable_len+1);
! 34:
! 35: if(lpECB->GetServerVariable(lpECB->ConnID, const_cast<char *>(name),
! 36: variable_buf, &variable_len)) {
! 37: variable_buf[variable_len]=0;
! 38: return variable_buf;
! 39: }
! 40:
! 41: return 0;
! 42: }
! 43:
! 44: static uint read_post(Pool& pool, char *buf, uint max_bytes) {
! 45: LPEXTENSION_CONTROL_BLOCK lpECB=static_cast<LPEXTENSION_CONTROL_BLOCK>(pool.context());
! 46:
! 47: // todo: timeout
! 48: DWORD read_from_buf=0;
! 49: DWORD read_from_input=0;
! 50: DWORD total_read=0;
! 51:
! 52: read_from_buf=min(lpECB->cbAvailable, max_bytes);
! 53: memcpy(buf, lpECB->lpbData, read_from_buf);
! 54: total_read+=read_from_buf;
! 55:
! 56: if(read_from_buf<max_bytes &&
! 57: read_from_buf<lpECB->cbTotalBytes) {
! 58: DWORD cbRead=0, cbSize;
! 59:
! 60: read_from_input=min(max_bytes-read_from_buf, lpECB->cbTotalBytes-read_from_buf);
! 61: while(cbRead < read_from_input) {
! 62: cbSize=read_from_input - cbRead;
! 63: if(!lpECB->ReadClient(lpECB->ConnID, buf+read_from_buf+cbRead, &cbSize) ||
! 64: cbSize==0)
! 65: break;
! 66: cbRead+=cbSize;
! 67: }
! 68: total_read+=cbRead;
! 69: }
! 70: return total_read;
! 71: }
! 72:
! 73: static void add_header_attribute(Pool& pool, const char *key, const char *value) {
! 74: LPEXTENSION_CONTROL_BLOCK lpECB=static_cast<LPEXTENSION_CONTROL_BLOCK>(pool.context());
! 75: String *header=static_cast<String *>(pool.tag());
! 76: if(!header)
! 77: pool.set_tag(header=new(pool) String(pool));
! 78:
! 79: header->APPEND_CONST(key);
! 80: header->APPEND_CONST(": ");
! 81: header->APPEND_CONST(value);
! 82: header->APPEND_CONST("\r\n");
! 83: }
! 84:
! 85: static void send_header(Pool& pool) {
! 86: LPEXTENSION_CONTROL_BLOCK lpECB=static_cast<LPEXTENSION_CONTROL_BLOCK>(pool.context());
! 87: String *header=static_cast<String *>(pool.tag());
! 88: if(!header) // never
! 89: return;
! 90:
! 91: header->APPEND_CONST("\r\n");
! 92: HSE_SEND_HEADER_EX_INFO header_info;
! 93:
! 94: int http_response_code=200; // todo: dig from headers
! 95:
! 96: char status_buf[MAX_STATUS_LENGTH];
! 97: switch(http_response_code) {
! 98: case 200:
! 99: header_info.pszStatus="200 OK";
! 100: break;
! 101: case 302:
! 102: header_info.pszStatus="302 Moved Temporarily";
! 103: break;
! 104: case 401:
! 105: header_info.pszStatus="401 Authorization Required";
! 106: break;
! 107: default:
! 108: snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", http_response_code);
! 109: header_info.pszStatus=status_buf;
! 110: break;
! 111: }
! 112: header_info.cchStatus=strlen(header_info.pszStatus);
! 113: header_info.pszHeader=header->cstr();
! 114: header_info.cchHeader=header->size();
! 115:
! 116: lpECB->dwHttpStatusCode=http_response_code;
! 117:
! 118: lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX,
! 119: &header_info, NULL, NULL);
! 120: }
! 121:
! 122: static void send_body(Pool& pool, const char *buf, size_t size) {
! 123: LPEXTENSION_CONTROL_BLOCK lpECB=static_cast<LPEXTENSION_CONTROL_BLOCK>(pool.context());
! 124:
! 125: DWORD num_bytes=size;
! 126: lpECB->WriteClient(lpECB->ConnID, const_cast<char *>(buf), &num_bytes, HSE_IO_SYNC);
! 127: }
! 128: //@}
! 129:
! 130: /// Service funcs
! 131: Service_funcs service_funcs={
! 132: get_env,
! 133: read_post,
! 134: add_header_attribute,
! 135: send_header,
! 136: send_body
! 137: };
! 138:
! 139: //
! 140:
! 141: static void parser_init() {
! 142: static bool globals_inited=false;
! 143: if(globals_inited)
! 144: return;
! 145: globals_inited=true;
! 146:
! 147: static Pool pool; // global pool
! 148: PTRY {
! 149: // init global variables
! 150: globals_init(pool);
! 151:
! 152: //...
! 153: } PCATCH(e) { // global problem
! 154: const char *body=e.comment();
! 155: // TODO: somehow report that error
! 156: }
! 157: PEND_CATCH
! 158: }
! 159:
! 160: /// ISAPI //
! 161: BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) {
! 162: pVer->dwExtensionVersion = HSE_VERSION;
! 163: strncpy(pVer->lpszExtensionDesc, "Parser " PARSER_VERSION, HSE_MAX_EXT_DLL_NAME_LEN);
! 164: return TRUE;
! 165: }
! 166:
! 167: static BOOL exception_handler(LPEXCEPTION_POINTERS *e,LPEXCEPTION_POINTERS ep) {
! 168: *e=ep;
! 169: return TRUE;
! 170: }
! 171:
! 172: /// ISAPI // main workhorse
! 173: DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) {
! 174: Pool pool;
! 175: pool.set_context(lpECB);
! 176:
! 177: // TODO r->no_cache=1;
! 178:
! 179: bool header_only=strcasecmp(lpECB->lpszMethod, "HEAD")==0;
! 180: PTRY { // global try
! 181: // must be first in PTRY{}PCATCH
! 182: LPEXCEPTION_POINTERS e;
! 183: __try {
! 184:
! 185: const char *filespec_to_process=lpECB->lpszPathTranslated;
! 186:
! 187: // Request info
! 188: Request::Info request_info;
! 189:
! 190: const char *document_root=0; // todo: get from somewhere?
! 191: if(!document_root) {
! 192: static char fake_document_root[MAX_STRING];
! 193: strncpy(fake_document_root, filespec_to_process, MAX_STRING);
! 194: rsplit(fake_document_root, '/'); rsplit(fake_document_root, '\\');// strip filename
! 195: document_root=fake_document_root;
! 196: }
! 197: request_info.document_root=document_root;
! 198: request_info.path_translated=filespec_to_process;
! 199: request_info.method=lpECB->lpszMethod;
! 200: request_info.query_string=lpECB->lpszQueryString;
! 201: request_info.uri=lpECB->lpszPathInfo;//todo: check for ?zzz included?
! 202: request_info.content_type=lpECB->lpszContentType;
! 203: request_info.content_length=lpECB->cbTotalBytes;
! 204: {// cookie
! 205: char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
! 206: DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE-1;
! 207:
! 208: if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) {
! 209: variable_buf[variable_len]=0;
! 210: request_info.cookie=variable_buf;
! 211: } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
! 212: char *tmp_variable_buf=(char *)pool.malloc(variable_len+1);
! 213:
! 214: if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) {
! 215: tmp_variable_buf[variable_len] = 0;
! 216: request_info.cookie=tmp_variable_buf;
! 217: } else {
! 218: request_info.cookie=0;
! 219: }
! 220: }
! 221: }
! 222:
! 223: // prepare to process request
! 224: Request request(pool,
! 225: request_info,
! 226: String::UL_HTML_TYPO
! 227: );
! 228:
! 229:
! 230: // some root-controlled location
! 231: char *root_auto_path;
! 232: // c:\windows
! 233: root_auto_path=(char *)pool.malloc(MAX_STRING);
! 234: GetWindowsDirectory(root_auto_path, MAX_STRING);
! 235: strcat(root_auto_path, "/");
! 236:
! 237: // process the request
! 238: request.core(
! 239: root_auto_path, true, // /path/to/admin/auto.p
! 240: 0/*parser_site_auto_path*/, false, // /path/to/site/auto.p
! 241: header_only);
! 242:
! 243: // successful finish
! 244:
! 245: // must be last in PTRY{}PCATCH
! 246: } __except(exception_handler(&e, GetExceptionInformation())) {
! 247: // converting C++ exception into Parser exception
! 248:
! 249: if(_exception_code()==EXCEPTION_STACK_OVERFLOW)
! 250: PTHROW(0, 0,
! 251: 0,
! 252: "Stack overflow");
! 253: else if(_exception_code()==EXCEPTION_ACCESS_VIOLATION)
! 254: PTHROW(0, 0,
! 255: 0,
! 256: "Access violation at %p",
! 257: e->ExceptionRecord->ExceptionAddress);
! 258: else
! 259: PTHROW(0, 0,
! 260: 0,
! 261: "Exception %#X at %p",
! 262: e->ExceptionRecord->ExceptionCode,
! 263: e->ExceptionRecord->ExceptionAddress);
! 264: }
! 265: // no further code here
! 266: } PCATCH(e) { // global problem
! 267: const char *body=e.comment();
! 268: int content_length=strlen(body);
! 269:
! 270: // prepare header
! 271: (*service_funcs.add_header_attribute)(pool, "content-type", "text/plain");
! 272: char content_length_cstr[MAX_NUMBER];
! 273: snprintf(content_length_cstr, MAX_NUMBER, "%d", content_length);
! 274: (*service_funcs.add_header_attribute)(pool, "content-length",
! 275: content_length_cstr);
! 276:
! 277: // send header
! 278: (*service_funcs.send_header)(pool);
! 279:
! 280: // send body
! 281: if(!header_only)
! 282: (*service_funcs.send_body)(pool, body, content_length);
! 283:
! 284: // unsuccessful finish
! 285: _endthread();
! 286: }
! 287: PEND_CATCH
! 288:
! 289: return HSE_STATUS_SUCCESS;
! 290: }
! 291:
! 292:
! 293: BOOL APIENTRY DllMain(HANDLE hModule,
! 294: DWORD ul_reason_for_call,
! 295: LPVOID lpReserved
! 296: ) {
! 297: switch (ul_reason_for_call) {
! 298: case DLL_PROCESS_ATTACH:
! 299: parser_init();
! 300: break;
! 301: case DLL_THREAD_ATTACH:
! 302: break;
! 303: case DLL_THREAD_DETACH:
! 304: break;
! 305: case DLL_PROCESS_DETACH:
! 306: break;
! 307: }
! 308: return TRUE;
! 309: }
E-mail: