Annotation of parser3/src/targets/isapi/parser3isapi.C, revision 1.9
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:
1.9 ! paf 10: #include "pa_sapi.h"
1.1 paf 11: #include "pa_globals.h"
12: #include "pa_request.h"
13: #include "pa_version.h"
14:
15: #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION")
16:
17: //@{
1.9 ! paf 18: /// SAPI funcs decl
1.8 paf 19: struct sapi_func_context {
1.3 paf 20: LPEXTENSION_CONTROL_BLOCK lpECB;
21: String *header;
22: DWORD http_response_code;
23: };
24:
1.9 ! paf 25: const char *SAPI::get_env(Pool& pool, const char *name) {
1.8 paf 26: sapi_func_context& ctx=*static_cast<sapi_func_context *>(pool.context());
1.1 paf 27:
28: char *variable_buf=(char *)pool.malloc(MAX_STRING);
29: DWORD variable_len = MAX_STRING-1;
30:
1.3 paf 31: if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast<char *>(name),
1.1 paf 32: variable_buf, &variable_len)) {
33: variable_buf[variable_len]=0;
34: return variable_buf;
1.7 paf 35: } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
36: variable_buf=(char *)pool.malloc(variable_len+1);
37:
38: if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast<char *>(name),
39: variable_buf, &variable_len)) {
40: variable_buf[variable_len]=0;
41: return variable_buf;
42: }
1.1 paf 43: }
1.7 paf 44:
1.1 paf 45: return 0;
46: }
47:
1.9 ! paf 48: uint SAPI::read_post(Pool& pool, char *buf, uint max_bytes) {
1.8 paf 49: sapi_func_context& ctx=*static_cast<sapi_func_context *>(pool.context());
1.1 paf 50:
51: DWORD read_from_buf=0;
52: DWORD read_from_input=0;
53: DWORD total_read=0;
54:
1.3 paf 55: read_from_buf=min(ctx.lpECB->cbAvailable, max_bytes);
56: memcpy(buf, ctx.lpECB->lpbData, read_from_buf);
1.1 paf 57: total_read+=read_from_buf;
58:
59: if(read_from_buf<max_bytes &&
1.3 paf 60: read_from_buf<ctx.lpECB->cbTotalBytes) {
1.1 paf 61: DWORD cbRead=0, cbSize;
62:
1.3 paf 63: read_from_input=min(max_bytes-read_from_buf,
64: ctx.lpECB->cbTotalBytes-read_from_buf);
1.1 paf 65: while(cbRead < read_from_input) {
66: cbSize=read_from_input - cbRead;
1.3 paf 67: if(!ctx.lpECB->ReadClient(ctx.lpECB->ConnID,
68: buf+read_from_buf+cbRead, &cbSize) ||
1.1 paf 69: cbSize==0)
70: break;
71: cbRead+=cbSize;
72: }
73: total_read+=cbRead;
74: }
75: return total_read;
76: }
77:
1.9 ! paf 78: void SAPI::add_header_attribute(Pool& pool, const char *key, const char *value) {
1.8 paf 79: sapi_func_context& ctx=*static_cast<sapi_func_context *>(pool.context());
1.3 paf 80:
81: if(strcasecmp(key, "location")==0)
82: ctx.http_response_code=302;
83:
84: if(strcasecmp(key, "status")==0)
85: ctx.http_response_code=atoi(value);
86: else {
87: ctx.header->APPEND_CONST(key);
88: ctx.header->APPEND_CONST(": ");
89: ctx.header->APPEND_CONST(value);
90: ctx.header->APPEND_CONST("\n");
91: }
1.1 paf 92: }
93:
1.3 paf 94: /// @todo intelligent cache-control
1.9 ! paf 95: void SAPI::send_header(Pool& pool) {
1.8 paf 96: sapi_func_context& ctx=*static_cast<sapi_func_context *>(pool.context());
1.1 paf 97:
1.6 paf 98: ctx.header->APPEND_CONST(
1.8 paf 99: "Expires: Fri, 23 Mar 2001 09:32:23 GMT\n"
1.6 paf 100: "\n");
1.1 paf 101: HSE_SEND_HEADER_EX_INFO header_info;
102:
103: char status_buf[MAX_STATUS_LENGTH];
1.3 paf 104: switch(ctx.http_response_code) {
1.1 paf 105: case 200:
106: header_info.pszStatus="200 OK";
107: break;
108: case 302:
109: header_info.pszStatus="302 Moved Temporarily";
110: break;
1.8 paf 111: case 401:// useless untill parser auth mech
1.1 paf 112: header_info.pszStatus="401 Authorization Required";
1.8 paf 113: break;
1.1 paf 114: default:
1.3 paf 115: snprintf(status_buf, MAX_STATUS_LENGTH,
116: "%d Undescribed", ctx.http_response_code);
1.1 paf 117: header_info.pszStatus=status_buf;
118: break;
119: }
120: header_info.cchStatus=strlen(header_info.pszStatus);
1.3 paf 121: header_info.pszHeader=ctx.header->cstr();
122: header_info.cchHeader=ctx.header->size();
1.5 paf 123: header_info.fKeepConn=true;
1.1 paf 124:
1.3 paf 125: ctx.lpECB->dwHttpStatusCode=ctx.http_response_code;
1.1 paf 126:
1.3 paf 127: ctx.lpECB->ServerSupportFunction(ctx.lpECB->ConnID,
128: HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
1.1 paf 129: }
130:
1.9 ! paf 131: void SAPI::send_body(Pool& pool, const char *buf, size_t size) {
1.8 paf 132: sapi_func_context& ctx=*static_cast<sapi_func_context *>(pool.context());
1.1 paf 133:
134: DWORD num_bytes=size;
1.3 paf 135: ctx.lpECB->WriteClient(ctx.lpECB->ConnID,
136: const_cast<char *>(buf), &num_bytes, HSE_IO_SYNC);
1.1 paf 137: }
138: //@}
139:
140: //
141:
142: static void parser_init() {
143: static bool globals_inited=false;
144: if(globals_inited)
145: return;
146: globals_inited=true;
147:
148: static Pool pool; // global pool
149: PTRY {
150: // init global variables
1.9 ! paf 151: pa_globals_init(pool);
1.1 paf 152:
153: //...
154: } PCATCH(e) { // global problem
155: const char *body=e.comment();
156: // TODO: somehow report that error
157: }
158: PEND_CATCH
159: }
160:
161: /// ISAPI //
162: BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) {
163: pVer->dwExtensionVersion = HSE_VERSION;
164: strncpy(pVer->lpszExtensionDesc, "Parser " PARSER_VERSION, HSE_MAX_EXT_DLL_NAME_LEN);
165: return TRUE;
166: }
167:
1.6 paf 168: /**
169: ISAPI // main workhorse
170:
171: @todo
172: think of a better way than @c APPL_PHYSICAL_PATH
173: of obtaining the @c DOCUMENT_ROOT
174: because this only gets "the place where last IIS Application was set"
175: and if someone would redefine Application settings below the /
176: all ^table:load[/test] would open not /test but /below/test
177: */
1.1 paf 178: DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) {
179: Pool pool;
1.2 paf 180:
1.1 paf 181: bool header_only=strcasecmp(lpECB->lpszMethod, "HEAD")==0;
182: PTRY { // global try
1.8 paf 183: sapi_func_context ctx={
1.3 paf 184: lpECB,
185: new(pool) String(pool),
186: 200
187: };
188: pool.set_context(&ctx);
189:
1.2 paf 190: // Request info
191: Request::Info request_info;
192:
1.9 ! paf 193: if(!(request_info.document_root=SAPI::get_env(pool, "APPL_PHYSICAL_PATH")))
1.6 paf 194: PTHROW(0, 0,
195: 0,
1.7 paf 196: "can not get server variable APPL_PHYSICAL_PATH (error #%lu)",
1.6 paf 197: GetLastError()); // never
198:
199: request_info.path_translated=lpECB->lpszPathTranslated;
1.2 paf 200: request_info.method=lpECB->lpszMethod;
201: request_info.query_string=lpECB->lpszQueryString;
202: if(lpECB->lpszQueryString && *lpECB->lpszQueryString) {
1.7 paf 203: char *reconstructed_uri=(char *)malloc(
204: strlen(lpECB->lpszPathInfo)+1/*'?'*/+
205: strlen(lpECB->lpszQueryString)+1/*0*/);
206: strcpy(reconstructed_uri, lpECB->lpszPathInfo);
1.2 paf 207: strcat(reconstructed_uri, "?");
1.7 paf 208: strcat(reconstructed_uri, lpECB->lpszQueryString);
1.2 paf 209: request_info.uri=reconstructed_uri;
210: } else
211: request_info.uri=lpECB->lpszPathInfo;
212:
213: request_info.content_type=lpECB->lpszContentType;
214: request_info.content_length=lpECB->cbTotalBytes;
1.9 ! paf 215: request_info.cookie=SAPI::get_env(pool, "HTTP_COOKIE");
1.2 paf 216:
217: // prepare to process request
218: Request request(pool,
219: request_info,
220: String::UL_HTML_TYPO
221: );
222:
223: // some root-controlled location
1.7 paf 224: // c:\windows
225: // must be dynamic: rethrowing from request.core
226: // may return 'source' which can be inside of 'root auto.p@exeception'
227: char *root_auto_path=(char *)pool.malloc(MAX_STRING);
1.2 paf 228: GetWindowsDirectory(root_auto_path, MAX_STRING);
1.4 paf 229:
1.2 paf 230: // process the request
231: request.core(
232: root_auto_path, false/*may be abcent*/, // /path/to/admin/auto.p
233: 0/*parser_site_auto_path*/, false, // /path/to/site/auto.p
234: header_only);
235:
236: // successful finish
1.1 paf 237: } PCATCH(e) { // global problem
238: const char *body=e.comment();
239: int content_length=strlen(body);
240:
241: // prepare header
1.9 ! paf 242: SAPI::add_header_attribute(pool, "content-type", "text/plain");
1.1 paf 243: char content_length_cstr[MAX_NUMBER];
1.6 paf 244: snprintf(content_length_cstr, MAX_NUMBER, "%lu", content_length);
1.9 ! paf 245: SAPI::add_header_attribute(pool, "content-length", content_length_cstr);
1.1 paf 246:
247: // send header
1.9 ! paf 248: SAPI::send_header(pool);
1.1 paf 249:
250: // send body
251: if(!header_only)
1.9 ! paf 252: SAPI::send_body(pool, body, content_length);
1.1 paf 253:
254: // unsuccessful finish
255: _endthread();
256: }
257: PEND_CATCH
258:
1.6 paf 259: return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
1.1 paf 260: }
261:
262:
263: BOOL APIENTRY DllMain(HANDLE hModule,
264: DWORD ul_reason_for_call,
265: LPVOID lpReserved
266: ) {
267: switch (ul_reason_for_call) {
268: case DLL_PROCESS_ATTACH:
269: parser_init();
270: break;
271: case DLL_THREAD_ATTACH:
272: break;
273: case DLL_THREAD_DETACH:
274: break;
275: case DLL_PROCESS_DETACH:
276: break;
277: }
278: return TRUE;
279: }
E-mail: