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