/* * the request handler... */ NSAPI_PUBLIC int WebObjectsRequest(pblock *pb, Session *sn, Request *rq) { HTTPRequest *req; HTTPResponse *resp = NULL; WOURLComponents wc = WOURLComponents_Initializer; const char *reqerr; const char *qs; int retval; char *uri; WOURLError urlerr; if (!adaptorEnabled) return REQ_NOACTION; /* spew debug info */ dump_pb(sn->client,"service.sn->client"); dump_pb(pb,"service.pb"); dump_pb(rq->vars,"service.rq->vars"); dump_pb(rq->reqpb,"service.rq->reqpb"); dump_pb(rq->headers,"service.rq->headers"); dump_pb(rq->srvhdrs,"service.rq->srvhdrs"); uri = pblock_findval("uri", rq->reqpb); WOLog(WO_INFO,"<WebObjects NSAPI> new request: %s", uri); urlerr = WOParseApplicationName(&wc, uri); if (urlerr != WOURLOK) { const char *_urlerr; _urlerr = WOURLstrerror(urlerr); WOLog(WO_INFO,"URL Parsing Error: %s", _urlerr); if (urlerr == WOURLInvalidApplicationName) { if (ac_authorizeAppListing(&wc)) { resp = WOAdaptorInfo(NULL, &wc); die_resp(sn, rq, resp); } else { die(sn, rq, _urlerr, HTTP_NOT_FOUND); } } die(sn, rq, _urlerr, HTTP_BAD_REQUEST); } /* * build the request .... */ req = req_new( pblock_findval("method", rq->reqpb), NULL); /* * validate the method */ reqerr = req_validateMethod(req); if (reqerr) { req_free(req); return die(sn,rq,reqerr, HTTP_BAD_REQUEST); } /* * copy the headers.. */ copyHeaders(pb, sn, rq, req); /* * get form data if any * assume that POSTs with content length will be reformatted to GETs later */ if (req->content_length > 0) { int len_remaining = req->content_length; char *buffer = WOMALLOC(req->content_length); char *data = buffer; int c; while (len_remaining-- > 0) { if ((c = netbuf_getc(sn->inbuf)) == IO_ERROR) { log_error(0,"WebObjects",sn,rq,"Error reading form data"); WOFREE(buffer); req_free(req); return die(sn,rq,INV_FORM_DATA, HTTP_BAD_REQUEST); } *data++ = c; } req->content = buffer; } /* Always get the query string */ qs = pblock_findval("query", rq->reqpb); wc.queryString.start = qs; wc.queryString.length = qs ? strlen(qs) : 0; /* * message the application & collect the response * * note that handleRequest free()'s the 'req' for us */ if (resp == NULL) { /* if no error so far... */ req->api_handle = rq; /* stash this in case it's needed */ resp = tr_handleRequest(req, uri, &wc, pblock_findval("protocol",rq->reqpb), NULL); } if (resp != NULL) { retval = sendResponse(sn, rq, resp); resp_free(resp); } else { retval = REQ_EXIT; /* no response from app - bail */ } req_free(req); #if defined(FINDLEAKS) showleaks(); #endif return retval; }
/* * the thing that gets called... */ __declspec(dllexport) DWORD __stdcall HttpExtensionProc(EXTENSION_CONTROL_BLOCK *p) { HTTPRequest *req; HTTPResponse *resp = NULL; WOURLComponents wc = WOURLComponents_Initializer; const char *reqerr; const char *qs; char *script_name; char *server_protocol; char *uri; WOURLError urlerr; if (!adaptorEnabled) { WOLog(WO_ERR, "WebObjects adaptor disabled."); return HSE_STATUS_ERROR; } // Deactivate IIS 7.x stream buffering // IIS 7.x (and above?) behaves differently from IIS 6 by introducing // output buffering ISAPI Extension output // This could cause interrupted and hence incomplete streaming output // This change does deactivate the output buffering in IIS 7.x // (see http://support.microsoft.com/kb/946086) and does not harm // when called within IIS 6 // p->ServerSupportFunction (p->ConnID, HSE_REQ_SET_FLUSH_FLAG, (LPVOID) TRUE, NULL, NULL ); /* * extract WebObjects request components from URI */ script_name = getHeader(p, CGI_SCRIPT_NAME); uri = WOMALLOC(strlen(p->lpszPathInfo) + strlen(script_name) + 1); strcpy(uri, script_name); strcat(uri, p->lpszPathInfo); WOLog(WO_INFO,"<WebObjects ISAPI> new request: %s", uri); WOFREE(script_name); urlerr = WOParseApplicationName(&wc, uri); if (urlerr != WOURLOK) { const char *_urlerr; _urlerr = WOURLstrerror(urlerr); WOLog(WO_INFO,"URL Parsing Error: %s", _urlerr); if (urlerr == WOURLInvalidApplicationName) { if (ac_authorizeAppListing(&wc)) { resp = WOAdaptorInfo(NULL, &wc); WOFREE(uri); /* this has to be freed before a return in this function */ return die_resp(p, resp); } else { WOFREE(uri); /* this has to be freed before a return in this function */ return die(p, _urlerr, HTTP_NOT_FOUND); } } WOFREE(uri); /* this has to be freed before a return in this function */ return die(p, _urlerr, HTTP_BAD_REQUEST); } /* * build the request... */ req = req_new(p->lpszMethod, NULL); req->api_handle = p; /* * get the headers.... */ copyHeaders(p, req); /* * validate the method */ reqerr = req_validateMethod(req); if (reqerr) { req_free(req); WOFREE(uri); /* this has to be freed before a return in this function */ return die(p,reqerr, HTTP_BAD_REQUEST); } /* * get form data if any * assume that POSTs with content length will be reformatted to GETs later */ req->content_length = p->cbTotalBytes; if (req->content_length > 0) { req_allocateContent(req, req->content_length, 1); req->getMoreContent = (req_getMoreContentCallback)readContentData; req->total_len_read = 0; if (req->content_buffer_size == 0) { WOFREE(uri); /* this has to be freed before a return in this function */ req_free(req); return die(p, ALLOCATION_FAILURE, HTTP_SERVER_ERROR); } if (readContentData(req, req->content, req->content_buffer_size, 1) == -1) { WOFREE(uri); /* this has to be freed before a return in this function */ req_free(req); return die(p, WOURLstrerror(WOURLInvalidPostData), HTTP_BAD_REQUEST); } } /* Always get the query string */ qs = p->lpszQueryString; wc.queryString.start = qs; wc.queryString.length = qs ? strlen(qs) : 0; /* * message the application & collect the response * * note that handleRequest free()'s the 'req' for us */ if (resp == NULL) { /* if no error so far... */ server_protocol = getHeader(p, CGI_SERVER_PROTOCOL); resp = tr_handleRequest(req, uri, &wc, server_protocol, NULL); WOFREE(server_protocol); } if (resp != NULL) { sendResponse(p, resp); resp_free(resp); } WOFREE(uri); /* this has to be freed before a return in this function */ req_free(req); #if defined(FINDLEAKS) showleaks(); #endif return HSE_STATUS_SUCCESS; }
/* * the thing that gets called... */ __declspec(dllexport) DWORD HttpExtensionProc(EXTENSION_CONTROL_BLOCK *p) { HTTPRequest *req; HTTPResponse *resp = NULL; WOURLComponents wc = WOURLComponents_Initializer; const char *reqerr; const char *qs; char *script_name; char *server_protocol; char *uri; WOURLError urlerr; if (!adaptorEnabled) { WOLog(WO_ERR, "WebObjects adaptor disabled."); return HSE_STATUS_ERROR; } /* * extract WebObjects request components from URI */ script_name = getHeader(p, CGI_SCRIPT_NAME); uri = WOMALLOC(strlen(p->lpszPathInfo) + strlen(script_name) + 1); strcpy(uri, script_name); strcat(uri, p->lpszPathInfo); WOLog(WO_INFO,"<WebObjects ISAPI> new request: %s", uri); WOFREE(script_name); urlerr = WOParseApplicationName(&wc, uri); if (urlerr != WOURLOK) { const char *_urlerr; _urlerr = WOURLstrerror(urlerr); WOLog(WO_INFO,"URL Parsing Error: %s", _urlerr); if (urlerr == WOURLInvalidApplicationName) { if (ac_authorizeAppListing(&wc)) { resp = WOAdaptorInfo(NULL, &wc); WOFREE(uri); /* this has to be freed before a return in this function */ return die_resp(p, resp); } else { WOFREE(uri); /* this has to be freed before a return in this function */ return die(p, _urlerr, HTTP_NOT_FOUND); } } WOFREE(uri); /* this has to be freed before a return in this function */ return die(p, _urlerr, HTTP_BAD_REQUEST); } /* * build the request... */ req = req_new(p->lpszMethod, NULL); /* * validate the method */ reqerr = req_validateMethod(req); if (reqerr) { req_free(req); WOFREE(uri); /* this has to be freed before a return in this function */ return die(p,reqerr, HTTP_BAD_REQUEST); } /* * get the headers.... */ copyHeaders(p, req); /* * get form data if any * assume that POSTs with content length will be reformatted to GETs later */ req->content_length = p->cbTotalBytes; if (req->content_length > 0) { char *buffer = WOMALLOC(req->content_length); if (p->cbAvailable > 0) memcpy(buffer, p->lpbData, p->cbAvailable); /* * IIS has a weird (or is it convenient?) data queuing mechanism... */ if (req->content_length > p->cbAvailable) { DWORD len; DWORD totalLength, fetchedLength; len = req->content_length - p->cbAvailable; totalLength = len; fetchedLength = 0; while (fetchedLength < totalLength) { len = totalLength - fetchedLength; if (p->ReadClient (p->ConnID,buffer + p->cbAvailable + fetchedLength, &len) != TRUE) { WOFREE(buffer); req_free(req); return die(p, INV_FORM_DATA, HTTP_BAD_REQUEST); } fetchedLength += len; } } req->content = buffer; if (req_HeaderForKey(req, CONTENT_LENGTH) == NULL) { char *length; length = (char *)WOMALLOC(32); if (length) { sprintf(length,"%d",req->content_length); req_addHeader(req, CONTENT_LENGTH, length, STR_FREEVALUE); } if (p->lpszContentType != NULL) req_addHeader(req, CONTENT_TYPE, p->lpszContentType, 0); } } /* Always get the query string */ qs = p->lpszQueryString; wc.queryString.start = qs; wc.queryString.length = qs ? strlen(qs) : 0; /* * message the application & collect the response * * note that handleRequest free()'s the 'req' for us */ if (resp == NULL) { /* if no error so far... */ req->api_handle = p; /* stash this... */ server_protocol = getHeader(p, CGI_SERVER_PROTOCOL); resp = tr_handleRequest(req, uri, &wc, server_protocol, NULL); WOFREE(server_protocol); } if (resp != NULL) { sendResponse(p, resp); resp_free(resp); } WOFREE(uri); /* this has to be freed before a return in this function */ req_free(req); #if defined(FINDLEAKS) showleaks(); #endif return HSE_STATUS_SUCCESS; }