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: