diff options
author | Bill Stoddard <stoddard@apache.org> | 2000-04-15 19:23:08 +0000 |
---|---|---|
committer | Bill Stoddard <stoddard@apache.org> | 2000-04-15 19:23:08 +0000 |
commit | 16e366cbfeec4227946d1a1640710eff4862b02d (patch) | |
tree | b7d006790b84f12f4dd7c67408942b42c344c681 | |
parent | f76bc22f67c0c23120b18d76fecd919f7aa86e6e (diff) | |
download | httpd-16e366cbfeec4227946d1a1640710eff4862b02d.tar.gz |
Win32: First cut at getting mod_isapi working under 2.0
Submitted by: William Rowe
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84976 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | ApacheCore.dsp | 4 | ||||
-rw-r--r-- | httpd.dsp | 4 | ||||
-rw-r--r-- | modules/arch/win32/mod_isapi.c | 550 | ||||
-rw-r--r-- | os/win32/mod_isapi.c | 550 | ||||
-rw-r--r-- | os/win32/modules.c | 6 |
5 files changed, 573 insertions, 541 deletions
diff --git a/ApacheCore.dsp b/ApacheCore.dsp index 2989a94c44..113bb49cdf 100644 --- a/ApacheCore.dsp +++ b/ApacheCore.dsp @@ -196,6 +196,10 @@ SOURCE=.\modules\standard\mod_include.c # End Source File # Begin Source File +SOURCE=.\os\win32\mod_isapi.c +# End Source File +# Begin Source File + SOURCE=.\modules\standard\mod_log_config.c # End Source File # Begin Source File @@ -196,6 +196,10 @@ SOURCE=.\modules\standard\mod_include.c # End Source File # Begin Source File +SOURCE=.\os\win32\mod_isapi.c +# End Source File +# Begin Source File + SOURCE=.\modules\standard\mod_log_config.c # End Source File # Begin Source File diff --git a/modules/arch/win32/mod_isapi.c b/modules/arch/win32/mod_isapi.c index 592b5ec9f6..11b3442611 100644 --- a/modules/arch/win32/mod_isapi.c +++ b/modules/arch/win32/mod_isapi.c @@ -75,6 +75,7 @@ * the ISA is in. */ +#include "ap_config.h" #include "httpd.h" #include "http_config.h" #include "http_core.h" @@ -82,6 +83,7 @@ #include "http_request.h" #include "http_log.h" #include "util_script.h" +#include "apr_portable.h" /* We use the exact same header file as the original */ #include <HttpExt.h> @@ -103,13 +105,13 @@ typedef struct { /* Declare the ISAPI functions */ BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, - LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer); + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer); BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, - DWORD dwReserved); + DWORD dwReserved); BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize); BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, - LPVOID lpvBuffer, LPDWORD lpdwSize, - LPDWORD lpdwDataType); + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType); /* The optimiser blows it totally here. What happens is that autos are addressed relative to the @@ -119,9 +121,12 @@ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, */ #pragma optimize("y",off) -int isapi_handler (request_rec *r) { +int isapi_handler (request_rec *r) +{ + ap_status_t rv; + LPEXTENSION_CONTROL_BLOCK ecb = - ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); + ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO)); HINSTANCE isapi_handle; @@ -136,48 +141,55 @@ int isapi_handler (request_rec *r) { /* Use similar restrictions as CGIs */ if (!(ap_allow_options(r) & OPT_EXECCGI)) - return FORBIDDEN; + return FORBIDDEN; - if (r->finfo.st_mode == 0) - return NOT_FOUND; + if (r->finfo.protection == 0) + return NOT_FOUND; - if (S_ISDIR(r->finfo.st_mode)) - return FORBIDDEN; + if (S_ISDIR(r->finfo.protection)) + return FORBIDDEN; /* Load the module */ if (!(isapi_handle = LoadLibraryEx(r->filename, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "Could not load DLL: %s", r->filename); - return SERVER_ERROR; + LOAD_WITH_ALTERED_SEARCH_PATH))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL: %s", r->filename); + return SERVER_ERROR; } if (!(isapi_version = - (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "DLL could not load GetExtensionVersion(): %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL %s symbol GetExtensionVersion()", + r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } if (!(isapi_entry = - (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "DLL could not load HttpExtensionProc(): %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL %s symbol HttpExtensionProc()", + r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } + /* TerminateExtension() is an optional interface */ + isapi_term = (void *)(GetProcAddress(isapi_handle, "TerminateExtension")); /* Run GetExtensionVersion() */ if (!(*isapi_version)(pVer)) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "ISAPI GetExtensionVersion() failed: %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ALERT, SERVER_ERROR, r, + "ISAPI %s GetExtensionVersion() call failed", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } /* Set up variables */ @@ -202,51 +214,51 @@ int isapi_handler (request_rec *r) { /* Set up client input */ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return retval; + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return retval; } if (ap_should_client_block(r)) { - /* Unlike IIS, which limits this to 48k, we read the whole - * sucker in. I suppose this could be bad for memory if someone - * uploaded the complete works of Shakespeare. Well, WebSite - * does the same thing. - */ - long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); - long read; - - /* Actually, let's cap it at 48k, until we figure out what - * to do with this... we don't want a Content-Length: 1000000000 - * taking out the machine. - */ - - if (to_read > 49152) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return HTTP_REQUEST_ENTITY_TOO_LARGE; - } - - ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); - - if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return SERVER_ERROR; - } - - /* Although its not to spec, IIS seems to null-terminate - * its lpdData string. So we will too. To make sure - * cbAvailable matches cbTotalBytes, we'll up the latter - * and equalize them. - */ - ecb->cbAvailable = ecb->cbTotalBytes = read + 1; - ecb->lpbData[read] = '\0'; - } + /* Unlike IIS, which limits this to 48k, we read the whole + * sucker in. I suppose this could be bad for memory if someone + * uploaded the complete works of Shakespeare. Well, WebSite + * does the same thing. + */ + long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); + long read; + + /* Actually, let's cap it at 48k, until we figure out what + * to do with this... we don't want a Content-Length: 1000000000 + * taking out the machine. + */ + + if (to_read > 49152) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return HTTP_REQUEST_ENTITY_TOO_LARGE; + } + + ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); + + if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Although its not to spec, IIS seems to null-terminate + * its lpdData string. So we will too. To make sure + * cbAvailable matches cbTotalBytes, we'll up the latter + * and equalize them. + */ + ecb->cbAvailable = ecb->cbTotalBytes = read + 1; + ecb->lpbData[read] = '\0'; + } else { - ecb->cbTotalBytes = 0; - ecb->cbAvailable = 0; - ecb->lpbData = NULL; + ecb->cbTotalBytes = 0; + ecb->cbAvailable = 0; + ecb->lpbData = NULL; } /* Set up the callbacks */ @@ -261,77 +273,81 @@ int isapi_handler (request_rec *r) { /* Set the status (for logging) */ if (ecb->dwHttpStatusCode) - r->status = ecb->dwHttpStatusCode; + r->status = ecb->dwHttpStatusCode; /* Check for a log message - and log it */ if (ecb->lpszLogData && strcmp(ecb->lpszLogData, "")) - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "%s: %s", ecb->lpszLogData, r->filename); + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "ISAPI %s: %s", r->filename, ecb->lpszLogData); /* All done with the DLL... get rid of it */ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); + FreeLibrary(isapi_handle); switch(retval) { case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: - /* Ignore the keepalive stuff; Apache handles it just fine without - * the ISA's "advice". - */ + /* Ignore the keepalive stuff; Apache handles it just fine without + * the ISA's "advice". + */ + + if (cid->status) /* We have a special status to return */ + return cid->status; - if (cid->status) /* We have a special status to return */ - return cid->status; + return OK; - return OK; - case HSE_STATUS_PENDING: /* We don't support this */ - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); + case HSE_STATUS_PENDING: /* We don't support this */ + rv = APR_ENOTIMPL; + ap_log_rerror(APLOG_MARK, APLOG_WARNING, SERVER_ERROR, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); case HSE_STATUS_ERROR: default: - return SERVER_ERROR; + + return SERVER_ERROR; } } #pragma optimize("",on) BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, - LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) { + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) +{ request_rec *r = ((isapi_cid *)hConn)->r; ap_table_t *e = r->subprocess_env; const char *result; - + /* Mostly, we just grab it from the environment, but there are * a couple of special cases */ if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) { - /* We don't support NT users, so this is always the same as - * REMOTE_USER - */ - result = ap_table_get(e, "REMOTE_USER"); + /* We don't support NT users, so this is always the same as + * REMOTE_USER + */ + result = ap_table_get(e, "REMOTE_USER"); } else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) { - /* Apache doesn't support secure requests inherently, so - * we have no way of knowing. We'll be conservative, and say - * all requests are insecure. - */ - result = "0"; + /* Apache doesn't support secure requests inherently, so + * we have no way of knowing. We'll be conservative, and say + * all requests are insecure. + */ + result = "0"; } else if (!strcasecmp(lpszVariableName, "URL")) { - result = r->uri; + result = r->uri; } else { - result = ap_table_get(e, lpszVariableName); + result = ap_table_get(e, lpszVariableName); } if (result) { - if (strlen(result) > *lpdwSizeofBuffer) { - *lpdwSizeofBuffer = strlen(result); - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - strncpy(lpvBuffer, result, *lpdwSizeofBuffer); - return TRUE; + if (strlen(result) > *lpdwSizeofBuffer) { + *lpdwSizeofBuffer = strlen(result); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + strncpy(lpvBuffer, result, *lpdwSizeofBuffer); + return TRUE; } /* Didn't find it */ @@ -340,231 +356,227 @@ BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, } BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, - DWORD dwReserved) { + DWORD dwReserved) +{ request_rec *r = ((isapi_cid *)ConnID)->r; - int writ; /* written, actually, but why shouldn't I make up words? */ + int writ; /* written, actually, but why shouldn't I make up words? */ /* We only support synchronous writing */ if (dwReserved && dwReserved != HSE_IO_SYNC) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + ap_log_rerror(APLOG_MARK, APLOG_WARNING, ERROR_INVALID_PARAMETER, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } if ((writ = ap_rwrite(Buffer, *lpwdwBytes, r)) == EOF) { - SetLastError(ERROR); /* XXX: Find the right error code */ - return FALSE; + SetLastError(ERROR); /* TODO: Find the right error code */ + return FALSE; } - + *lpwdwBytes = writ; return TRUE; } -BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) { +BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) +{ /* Doesn't need to do anything; we've read all the data already */ return TRUE; } /* XXX: There is an O(n^2) attack possible here. */ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, - LPVOID lpvBuffer, LPDWORD lpdwSize, - LPDWORD lpdwDataType) { + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType) +{ isapi_cid *cid = (isapi_cid *)hConn; request_rec *subreq, *r = cid->r; char *data; switch (dwHSERequest) { case HSE_REQ_SEND_URL_REDIRECT_RESP: - /* Set the status to be returned when the HttpExtensionProc() - * is done. - */ - ap_table_set (r->headers_out, "Location", lpvBuffer); - cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; - return TRUE; + /* Set the status to be returned when the HttpExtensionProc() + * is done. + */ + ap_table_set (r->headers_out, "Location", lpvBuffer); + cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; + return TRUE; case HSE_REQ_SEND_URL: - /* Read any additional input */ + /* Read any additional input */ + + if (r->remaining > 0) { + char argsbuffer[HUGE_STRING_LEN]; + + while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); + } - if (r->remaining > 0) { - char argsbuffer[HUGE_STRING_LEN]; + /* Reset the method to GET */ + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; - while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); - } - - /* Reset the method to GET */ - r->method = ap_pstrdup(r->pool, "GET"); - r->method_number = M_GET; + /* Don't let anyone think there's still data */ + ap_table_unset(r->headers_in, "Content-Length"); - /* Don't let anyone think there's still data */ - ap_table_unset(r->headers_in, "Content-Length"); - - ap_internal_redirect((char *)lpvBuffer, r); - return TRUE; + ap_internal_redirect((char *)lpvBuffer, r); + return TRUE; case HSE_REQ_SEND_RESPONSE_HEADER: - r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); - sscanf(r->status_line, "%d", &r->status); - cid->ecb->dwHttpStatusCode = r->status; - - /* Now fill in the HTTP headers, and the rest of it. Ick. - * lpdwDataType contains a string that has headers (in MIME - * format), a blank like, then (possibly) data. We need - * to parse it. - * - * Easy case first: - */ - if (!lpdwDataType) { - ap_send_http_header(r); - return TRUE; - } - - /* Make a copy - don't disturb the original */ - data = ap_pstrdup(r->pool, (char *)lpdwDataType); - - /* We *should* break before this while loop ends */ - while (*data) { - char *value, *lf = strchr(data, '\n'); - int p; + r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); + sscanf(r->status_line, "%d", &r->status); + cid->ecb->dwHttpStatusCode = r->status; + + /* Now fill in the HTTP headers, and the rest of it. Ick. + * lpdwDataType contains a string that has headers (in MIME + * format), a blank like, then (possibly) data. We need + * to parse it. + * + * Easy case first: + */ + if (!lpdwDataType) { + ap_send_http_header(r); + return TRUE; + } + + /* Make a copy - don't disturb the original */ + data = ap_pstrdup(r->pool, (char *)lpdwDataType); + + /* We *should* break before this while loop ends */ + while (*data) { + char *value, *lf = strchr(data, '\n'); + int p; #ifdef RELAX_HEADER_RULE - if (lf) - *lf = '\0'; + if (lf) + *lf = '\0'; #else - if (!lf) { /* Huh? Invalid data, I think */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "ISA sent invalid headers: %s", r->filename); - SetLastError(ERROR); /* XXX: Find right error */ - return FALSE; - } - - /* Get rid of \n and \r */ - *lf = '\0'; + if (!lf) { /* Huh? Invalid data, I think */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers: %s", r->filename); + SetLastError(ERROR); /* XXX: Find right error */ + return FALSE; + } + + /* Get rid of \n and \r */ + *lf = '\0'; #endif - p = strlen(data); - if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; - - /* End of headers */ - if (*data == '\0') { + p = strlen(data); + if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; + + /* End of headers */ + if (*data == '\0') { #ifdef RELAX_HEADER_RULE - if (lf) + if (lf) #endif - data = lf + 1; /* Reset data */ - break; - } - - if (!(value = strchr(data, ':'))) { - SetLastError(ERROR); /* XXX: Find right error */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "ISA sent invalid headers", r->filename); - return FALSE; - } - - *value++ = '\0'; - while (*value && ap_isspace(*value)) ++value; - - /* Check all the special-case headers. Similar to what - * ap_scan_script_header_err() does (see that function for - * more detail) - */ - - if (!strcasecmp(data, "Content-Type")) { - char *tmp; - /* Nuke trailing whitespace */ - - char *endp = value + strlen(value) - 1; - while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; - - tmp = ap_pstrdup (r->pool, value); - ap_str_tolower(tmp); - r->content_type = tmp; - } - else if (!strcasecmp(data, "Content-Length")) { - ap_table_set(r->headers_out, data, value); - } - else if (!strcasecmp(data, "Transfer-Encoding")) { - ap_table_set(r->headers_out, data, value); - } - else if (!strcasecmp(data, "Set-Cookie")) { - ap_table_add(r->err_headers_out, data, value); - } - else { - ap_table_merge(r->err_headers_out, data, value); - } - - /* Reset data */ + data = lf + 1; /* Reset data */ + break; + } + + if (!(value = strchr(data, ':'))) { + SetLastError(ERROR); /* TODO: Find right error */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, SERVER_ERROR, r, + "ISA sent invalid headers", r->filename); + return FALSE; + } + + *value++ = '\0'; + while (*value && ap_isspace(*value)) ++value; + + /* Check all the special-case headers. Similar to what + * ap_scan_script_header_err() does (see that function for + * more detail) + */ + + if (!strcasecmp(data, "Content-Type")) { + char *tmp; + /* Nuke trailing whitespace */ + + char *endp = value + strlen(value) - 1; + while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; + + tmp = ap_pstrdup (r->pool, value); + ap_str_tolower(tmp); + r->content_type = tmp; + } + else if (!strcasecmp(data, "Content-Length")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Transfer-Encoding")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Set-Cookie")) { + ap_table_add(r->err_headers_out, data, value); + } + else { + ap_table_merge(r->err_headers_out, data, value); + } + + /* Reset data */ #ifdef RELAX_HEADER_RULE - if (!lf) { - data += p; - break; - } + if (!lf) { + data += p; + break; + } #endif - data = lf + 1; - } - - /* All the headers should be set now */ + data = lf + 1; + } - ap_send_http_header(r); + /* All the headers should be set now */ - /* Any data left should now be sent directly */ - ap_rputs(data, r); + ap_send_http_header(r); - return TRUE; + /* Any data left should now be sent directly */ + ap_rputs(data, r); + + return TRUE; case HSE_REQ_MAP_URL_TO_PATH: - /* Map a URL to a filename */ - subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, - *lpdwSize), r); + /* Map a URL to a filename */ + subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, + *lpdwSize), r); + + GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); - GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); + /* IIS puts a trailing slash on directories, Apache doesn't */ - /* IIS puts a trailing slash on directories, Apache doesn't */ + if (S_ISDIR (subreq->finfo.protection)) { + int l = strlen((char *)lpvBuffer); - if (S_ISDIR (subreq->finfo.st_mode)) { - int l = strlen((char *)lpvBuffer); + ((char *)lpvBuffer)[l] = '\\'; + ((char *)lpvBuffer)[l + 1] = '\0'; + } - ((char *)lpvBuffer)[l] = '\\'; - ((char *)lpvBuffer)[l + 1] = '\0'; - } - - return TRUE; + return TRUE; case HSE_REQ_DONE_WITH_SESSION: - /* Do nothing... since we don't support async I/O, they'll - * return from HttpExtensionProc soon - */ - return TRUE; + /* Do nothing... since we don't support async I/O, they'll + * return from HttpExtensionProc soon + */ + return TRUE; /* We don't support all this async I/O, Microsoft-specific stuff */ case HSE_REQ_IO_COMPLETION: case HSE_REQ_TRANSMIT_FILE: - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); + ap_log_rerror(APLOG_MARK, APLOG_WARNING, SERVER_ERROR, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } } handler_rec isapi_handlers[] = { -{ "isapi-isa", isapi_handler }, -{ NULL} + { "isapi-isa", isapi_handler }, + { NULL} }; module isapi_module = { - STANDARD_MODULE_STUFF, - NULL, /* initializer */ - NULL, /* create per-dir config */ - NULL, /* merge per-dir config */ - NULL, /* server config */ - NULL, /* merge server config */ - NULL, /* command ap_table_t */ - isapi_handlers, /* handlers */ - NULL, /* filename translation */ - NULL, /* check_user_id */ - NULL, /* check auth */ - NULL, /* check access */ - NULL, /* type_checker */ - NULL, /* logger */ - NULL /* header parser */ + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command ap_table_t */ + isapi_handlers, /* handlers */ + NULL /* register hooks */ }; diff --git a/os/win32/mod_isapi.c b/os/win32/mod_isapi.c index 592b5ec9f6..11b3442611 100644 --- a/os/win32/mod_isapi.c +++ b/os/win32/mod_isapi.c @@ -75,6 +75,7 @@ * the ISA is in. */ +#include "ap_config.h" #include "httpd.h" #include "http_config.h" #include "http_core.h" @@ -82,6 +83,7 @@ #include "http_request.h" #include "http_log.h" #include "util_script.h" +#include "apr_portable.h" /* We use the exact same header file as the original */ #include <HttpExt.h> @@ -103,13 +105,13 @@ typedef struct { /* Declare the ISAPI functions */ BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, - LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer); + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer); BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, - DWORD dwReserved); + DWORD dwReserved); BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize); BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, - LPVOID lpvBuffer, LPDWORD lpdwSize, - LPDWORD lpdwDataType); + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType); /* The optimiser blows it totally here. What happens is that autos are addressed relative to the @@ -119,9 +121,12 @@ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, */ #pragma optimize("y",off) -int isapi_handler (request_rec *r) { +int isapi_handler (request_rec *r) +{ + ap_status_t rv; + LPEXTENSION_CONTROL_BLOCK ecb = - ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); + ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO)); HINSTANCE isapi_handle; @@ -136,48 +141,55 @@ int isapi_handler (request_rec *r) { /* Use similar restrictions as CGIs */ if (!(ap_allow_options(r) & OPT_EXECCGI)) - return FORBIDDEN; + return FORBIDDEN; - if (r->finfo.st_mode == 0) - return NOT_FOUND; + if (r->finfo.protection == 0) + return NOT_FOUND; - if (S_ISDIR(r->finfo.st_mode)) - return FORBIDDEN; + if (S_ISDIR(r->finfo.protection)) + return FORBIDDEN; /* Load the module */ if (!(isapi_handle = LoadLibraryEx(r->filename, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "Could not load DLL: %s", r->filename); - return SERVER_ERROR; + LOAD_WITH_ALTERED_SEARCH_PATH))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL: %s", r->filename); + return SERVER_ERROR; } if (!(isapi_version = - (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "DLL could not load GetExtensionVersion(): %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL %s symbol GetExtensionVersion()", + r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } if (!(isapi_entry = - (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "DLL could not load HttpExtensionProc(): %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { + rv = GetLastError(); + ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r, + "Could not load DLL %s symbol HttpExtensionProc()", + r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } + /* TerminateExtension() is an optional interface */ + isapi_term = (void *)(GetProcAddress(isapi_handle, "TerminateExtension")); /* Run GetExtensionVersion() */ if (!(*isapi_version)(pVer)) { - ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, - "ISAPI GetExtensionVersion() failed: %s", r->filename); - FreeLibrary(isapi_handle); - return SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ALERT, SERVER_ERROR, r, + "ISAPI %s GetExtensionVersion() call failed", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; } /* Set up variables */ @@ -202,51 +214,51 @@ int isapi_handler (request_rec *r) { /* Set up client input */ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return retval; + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return retval; } if (ap_should_client_block(r)) { - /* Unlike IIS, which limits this to 48k, we read the whole - * sucker in. I suppose this could be bad for memory if someone - * uploaded the complete works of Shakespeare. Well, WebSite - * does the same thing. - */ - long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); - long read; - - /* Actually, let's cap it at 48k, until we figure out what - * to do with this... we don't want a Content-Length: 1000000000 - * taking out the machine. - */ - - if (to_read > 49152) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return HTTP_REQUEST_ENTITY_TOO_LARGE; - } - - ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); - - if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { - if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); - return SERVER_ERROR; - } - - /* Although its not to spec, IIS seems to null-terminate - * its lpdData string. So we will too. To make sure - * cbAvailable matches cbTotalBytes, we'll up the latter - * and equalize them. - */ - ecb->cbAvailable = ecb->cbTotalBytes = read + 1; - ecb->lpbData[read] = '\0'; - } + /* Unlike IIS, which limits this to 48k, we read the whole + * sucker in. I suppose this could be bad for memory if someone + * uploaded the complete works of Shakespeare. Well, WebSite + * does the same thing. + */ + long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); + long read; + + /* Actually, let's cap it at 48k, until we figure out what + * to do with this... we don't want a Content-Length: 1000000000 + * taking out the machine. + */ + + if (to_read > 49152) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return HTTP_REQUEST_ENTITY_TOO_LARGE; + } + + ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); + + if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Although its not to spec, IIS seems to null-terminate + * its lpdData string. So we will too. To make sure + * cbAvailable matches cbTotalBytes, we'll up the latter + * and equalize them. + */ + ecb->cbAvailable = ecb->cbTotalBytes = read + 1; + ecb->lpbData[read] = '\0'; + } else { - ecb->cbTotalBytes = 0; - ecb->cbAvailable = 0; - ecb->lpbData = NULL; + ecb->cbTotalBytes = 0; + ecb->cbAvailable = 0; + ecb->lpbData = NULL; } /* Set up the callbacks */ @@ -261,77 +273,81 @@ int isapi_handler (request_rec *r) { /* Set the status (for logging) */ if (ecb->dwHttpStatusCode) - r->status = ecb->dwHttpStatusCode; + r->status = ecb->dwHttpStatusCode; /* Check for a log message - and log it */ if (ecb->lpszLogData && strcmp(ecb->lpszLogData, "")) - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "%s: %s", ecb->lpszLogData, r->filename); + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "ISAPI %s: %s", r->filename, ecb->lpszLogData); /* All done with the DLL... get rid of it */ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); - FreeLibrary(isapi_handle); + FreeLibrary(isapi_handle); switch(retval) { case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: - /* Ignore the keepalive stuff; Apache handles it just fine without - * the ISA's "advice". - */ + /* Ignore the keepalive stuff; Apache handles it just fine without + * the ISA's "advice". + */ + + if (cid->status) /* We have a special status to return */ + return cid->status; - if (cid->status) /* We have a special status to return */ - return cid->status; + return OK; - return OK; - case HSE_STATUS_PENDING: /* We don't support this */ - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); + case HSE_STATUS_PENDING: /* We don't support this */ + rv = APR_ENOTIMPL; + ap_log_rerror(APLOG_MARK, APLOG_WARNING, SERVER_ERROR, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); case HSE_STATUS_ERROR: default: - return SERVER_ERROR; + + return SERVER_ERROR; } } #pragma optimize("",on) BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, - LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) { + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) +{ request_rec *r = ((isapi_cid *)hConn)->r; ap_table_t *e = r->subprocess_env; const char *result; - + /* Mostly, we just grab it from the environment, but there are * a couple of special cases */ if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) { - /* We don't support NT users, so this is always the same as - * REMOTE_USER - */ - result = ap_table_get(e, "REMOTE_USER"); + /* We don't support NT users, so this is always the same as + * REMOTE_USER + */ + result = ap_table_get(e, "REMOTE_USER"); } else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) { - /* Apache doesn't support secure requests inherently, so - * we have no way of knowing. We'll be conservative, and say - * all requests are insecure. - */ - result = "0"; + /* Apache doesn't support secure requests inherently, so + * we have no way of knowing. We'll be conservative, and say + * all requests are insecure. + */ + result = "0"; } else if (!strcasecmp(lpszVariableName, "URL")) { - result = r->uri; + result = r->uri; } else { - result = ap_table_get(e, lpszVariableName); + result = ap_table_get(e, lpszVariableName); } if (result) { - if (strlen(result) > *lpdwSizeofBuffer) { - *lpdwSizeofBuffer = strlen(result); - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - strncpy(lpvBuffer, result, *lpdwSizeofBuffer); - return TRUE; + if (strlen(result) > *lpdwSizeofBuffer) { + *lpdwSizeofBuffer = strlen(result); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + strncpy(lpvBuffer, result, *lpdwSizeofBuffer); + return TRUE; } /* Didn't find it */ @@ -340,231 +356,227 @@ BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, } BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, - DWORD dwReserved) { + DWORD dwReserved) +{ request_rec *r = ((isapi_cid *)ConnID)->r; - int writ; /* written, actually, but why shouldn't I make up words? */ + int writ; /* written, actually, but why shouldn't I make up words? */ /* We only support synchronous writing */ if (dwReserved && dwReserved != HSE_IO_SYNC) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + ap_log_rerror(APLOG_MARK, APLOG_WARNING, ERROR_INVALID_PARAMETER, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } if ((writ = ap_rwrite(Buffer, *lpwdwBytes, r)) == EOF) { - SetLastError(ERROR); /* XXX: Find the right error code */ - return FALSE; + SetLastError(ERROR); /* TODO: Find the right error code */ + return FALSE; } - + *lpwdwBytes = writ; return TRUE; } -BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) { +BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) +{ /* Doesn't need to do anything; we've read all the data already */ return TRUE; } /* XXX: There is an O(n^2) attack possible here. */ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, - LPVOID lpvBuffer, LPDWORD lpdwSize, - LPDWORD lpdwDataType) { + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType) +{ isapi_cid *cid = (isapi_cid *)hConn; request_rec *subreq, *r = cid->r; char *data; switch (dwHSERequest) { case HSE_REQ_SEND_URL_REDIRECT_RESP: - /* Set the status to be returned when the HttpExtensionProc() - * is done. - */ - ap_table_set (r->headers_out, "Location", lpvBuffer); - cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; - return TRUE; + /* Set the status to be returned when the HttpExtensionProc() + * is done. + */ + ap_table_set (r->headers_out, "Location", lpvBuffer); + cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; + return TRUE; case HSE_REQ_SEND_URL: - /* Read any additional input */ + /* Read any additional input */ + + if (r->remaining > 0) { + char argsbuffer[HUGE_STRING_LEN]; + + while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); + } - if (r->remaining > 0) { - char argsbuffer[HUGE_STRING_LEN]; + /* Reset the method to GET */ + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; - while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); - } - - /* Reset the method to GET */ - r->method = ap_pstrdup(r->pool, "GET"); - r->method_number = M_GET; + /* Don't let anyone think there's still data */ + ap_table_unset(r->headers_in, "Content-Length"); - /* Don't let anyone think there's still data */ - ap_table_unset(r->headers_in, "Content-Length"); - - ap_internal_redirect((char *)lpvBuffer, r); - return TRUE; + ap_internal_redirect((char *)lpvBuffer, r); + return TRUE; case HSE_REQ_SEND_RESPONSE_HEADER: - r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); - sscanf(r->status_line, "%d", &r->status); - cid->ecb->dwHttpStatusCode = r->status; - - /* Now fill in the HTTP headers, and the rest of it. Ick. - * lpdwDataType contains a string that has headers (in MIME - * format), a blank like, then (possibly) data. We need - * to parse it. - * - * Easy case first: - */ - if (!lpdwDataType) { - ap_send_http_header(r); - return TRUE; - } - - /* Make a copy - don't disturb the original */ - data = ap_pstrdup(r->pool, (char *)lpdwDataType); - - /* We *should* break before this while loop ends */ - while (*data) { - char *value, *lf = strchr(data, '\n'); - int p; + r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); + sscanf(r->status_line, "%d", &r->status); + cid->ecb->dwHttpStatusCode = r->status; + + /* Now fill in the HTTP headers, and the rest of it. Ick. + * lpdwDataType contains a string that has headers (in MIME + * format), a blank like, then (possibly) data. We need + * to parse it. + * + * Easy case first: + */ + if (!lpdwDataType) { + ap_send_http_header(r); + return TRUE; + } + + /* Make a copy - don't disturb the original */ + data = ap_pstrdup(r->pool, (char *)lpdwDataType); + + /* We *should* break before this while loop ends */ + while (*data) { + char *value, *lf = strchr(data, '\n'); + int p; #ifdef RELAX_HEADER_RULE - if (lf) - *lf = '\0'; + if (lf) + *lf = '\0'; #else - if (!lf) { /* Huh? Invalid data, I think */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "ISA sent invalid headers: %s", r->filename); - SetLastError(ERROR); /* XXX: Find right error */ - return FALSE; - } - - /* Get rid of \n and \r */ - *lf = '\0'; + if (!lf) { /* Huh? Invalid data, I think */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers: %s", r->filename); + SetLastError(ERROR); /* XXX: Find right error */ + return FALSE; + } + + /* Get rid of \n and \r */ + *lf = '\0'; #endif - p = strlen(data); - if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; - - /* End of headers */ - if (*data == '\0') { + p = strlen(data); + if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; + + /* End of headers */ + if (*data == '\0') { #ifdef RELAX_HEADER_RULE - if (lf) + if (lf) #endif - data = lf + 1; /* Reset data */ - break; - } - - if (!(value = strchr(data, ':'))) { - SetLastError(ERROR); /* XXX: Find right error */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "ISA sent invalid headers", r->filename); - return FALSE; - } - - *value++ = '\0'; - while (*value && ap_isspace(*value)) ++value; - - /* Check all the special-case headers. Similar to what - * ap_scan_script_header_err() does (see that function for - * more detail) - */ - - if (!strcasecmp(data, "Content-Type")) { - char *tmp; - /* Nuke trailing whitespace */ - - char *endp = value + strlen(value) - 1; - while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; - - tmp = ap_pstrdup (r->pool, value); - ap_str_tolower(tmp); - r->content_type = tmp; - } - else if (!strcasecmp(data, "Content-Length")) { - ap_table_set(r->headers_out, data, value); - } - else if (!strcasecmp(data, "Transfer-Encoding")) { - ap_table_set(r->headers_out, data, value); - } - else if (!strcasecmp(data, "Set-Cookie")) { - ap_table_add(r->err_headers_out, data, value); - } - else { - ap_table_merge(r->err_headers_out, data, value); - } - - /* Reset data */ + data = lf + 1; /* Reset data */ + break; + } + + if (!(value = strchr(data, ':'))) { + SetLastError(ERROR); /* TODO: Find right error */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, SERVER_ERROR, r, + "ISA sent invalid headers", r->filename); + return FALSE; + } + + *value++ = '\0'; + while (*value && ap_isspace(*value)) ++value; + + /* Check all the special-case headers. Similar to what + * ap_scan_script_header_err() does (see that function for + * more detail) + */ + + if (!strcasecmp(data, "Content-Type")) { + char *tmp; + /* Nuke trailing whitespace */ + + char *endp = value + strlen(value) - 1; + while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; + + tmp = ap_pstrdup (r->pool, value); + ap_str_tolower(tmp); + r->content_type = tmp; + } + else if (!strcasecmp(data, "Content-Length")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Transfer-Encoding")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Set-Cookie")) { + ap_table_add(r->err_headers_out, data, value); + } + else { + ap_table_merge(r->err_headers_out, data, value); + } + + /* Reset data */ #ifdef RELAX_HEADER_RULE - if (!lf) { - data += p; - break; - } + if (!lf) { + data += p; + break; + } #endif - data = lf + 1; - } - - /* All the headers should be set now */ + data = lf + 1; + } - ap_send_http_header(r); + /* All the headers should be set now */ - /* Any data left should now be sent directly */ - ap_rputs(data, r); + ap_send_http_header(r); - return TRUE; + /* Any data left should now be sent directly */ + ap_rputs(data, r); + + return TRUE; case HSE_REQ_MAP_URL_TO_PATH: - /* Map a URL to a filename */ - subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, - *lpdwSize), r); + /* Map a URL to a filename */ + subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, + *lpdwSize), r); + + GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); - GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); + /* IIS puts a trailing slash on directories, Apache doesn't */ - /* IIS puts a trailing slash on directories, Apache doesn't */ + if (S_ISDIR (subreq->finfo.protection)) { + int l = strlen((char *)lpvBuffer); - if (S_ISDIR (subreq->finfo.st_mode)) { - int l = strlen((char *)lpvBuffer); + ((char *)lpvBuffer)[l] = '\\'; + ((char *)lpvBuffer)[l + 1] = '\0'; + } - ((char *)lpvBuffer)[l] = '\\'; - ((char *)lpvBuffer)[l + 1] = '\0'; - } - - return TRUE; + return TRUE; case HSE_REQ_DONE_WITH_SESSION: - /* Do nothing... since we don't support async I/O, they'll - * return from HttpExtensionProc soon - */ - return TRUE; + /* Do nothing... since we don't support async I/O, they'll + * return from HttpExtensionProc soon + */ + return TRUE; /* We don't support all this async I/O, Microsoft-specific stuff */ case HSE_REQ_IO_COMPLETION: case HSE_REQ_TRANSMIT_FILE: - ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, - "ISAPI asynchronous I/O not supported: %s", r->filename); + ap_log_rerror(APLOG_MARK, APLOG_WARNING, SERVER_ERROR, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } } handler_rec isapi_handlers[] = { -{ "isapi-isa", isapi_handler }, -{ NULL} + { "isapi-isa", isapi_handler }, + { NULL} }; module isapi_module = { - STANDARD_MODULE_STUFF, - NULL, /* initializer */ - NULL, /* create per-dir config */ - NULL, /* merge per-dir config */ - NULL, /* server config */ - NULL, /* merge server config */ - NULL, /* command ap_table_t */ - isapi_handlers, /* handlers */ - NULL, /* filename translation */ - NULL, /* check_user_id */ - NULL, /* check auth */ - NULL, /* check access */ - NULL, /* type_checker */ - NULL, /* logger */ - NULL /* header parser */ + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command ap_table_t */ + isapi_handlers, /* handlers */ + NULL /* register hooks */ }; diff --git a/os/win32/modules.c b/os/win32/modules.c index 8c624c2e80..bf89eb0e9b 100644 --- a/os/win32/modules.c +++ b/os/win32/modules.c @@ -25,7 +25,7 @@ extern module asis_module; extern module imap_module; extern module action_module; extern module setenvif_module; -//extern module isapi_module; +extern module isapi_module; module *ap_prelinked_modules[] = { &core_module, @@ -47,7 +47,7 @@ module *ap_prelinked_modules[] = { &imap_module, &action_module, &setenvif_module, -// &isapi_module, + &isapi_module, NULL }; module *ap_preloaded_modules[] = { @@ -70,6 +70,6 @@ module *ap_preloaded_modules[] = { &imap_module, &action_module, &setenvif_module, -// &isapi_module, + &isapi_module, NULL }; |