From: Graham Leggett Date: Thu, 12 Oct 2006 22:21:03 +0000 (+0000) Subject: mod_isapi: Simply backport the host of fixes for compilation on unix, X-Git-Tag: 2.2.4~128 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=128eaed8ce0672bec44616ef1b9c85c53b9fb815;p=thirdparty%2Fapache%2Fhttpd.git mod_isapi: Simply backport the host of fixes for compilation on unix, PR#'s 15993 29098 30022 16637 30033 28089 by pushing to trunk/ rev 416293 of modules/arch/win32/mod_isapi.[ch] which compiles without changes. +1 wrowe , fielding, jerenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@463467 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 2af079aa08a..691ec1b5b94 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,20 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.4 + *) mod_isapi: Avoid double trailing slashes in HSE_REQ_MAP_URL_TO_PATH + support. Also corrects the slashes for Windows. PR 15993. [William Rowe] + + *) mod_isapi: Handle "HTTP/1.1 200 OK" style status lines correctly, the + token parser worked while the resulting length was misinterpreted. + PR 29098 [Brock Bland ] + + *) mod_isapi: Return 0 (failure) for more of the various ap_pass_brigade + attempts to stream the response at the client. PR 30022 [William Rowe] + + *) mod_isapi: Ensure we walk through all the methods the developer may have + employed to report their HTTP status result code. + PR 16637 30033 28089 [Matt Lewandowsky , William Rowe] + *) mod_echo: Fix precedence problem in if statement. PR 40658. [Larry Cipriani ] diff --git a/modules/arch/win32/mod_isapi.c b/modules/arch/win32/mod_isapi.c index c977da14d78..5d18f24e872 100644 --- a/modules/arch/win32/mod_isapi.c +++ b/modules/arch/win32/mod_isapi.c @@ -630,6 +630,8 @@ static apr_ssize_t send_response_header(isapi_cid *cid, { int head_present = 1; int termarg; + int res; + int old_status; const char *termch; apr_size_t ate = 0; @@ -680,7 +682,7 @@ static apr_ssize_t send_response_header(isapi_cid *cid, * or the http/x.x xxx message format */ if (toklen && apr_isdigit(*stattok)) { - statlen -= toklen; + statlen = toklen; stat = stattok; } } @@ -709,29 +711,71 @@ static apr_ssize_t send_response_header(isapi_cid *cid, * * Parse them out, or die trying */ + old_status = cid->r->status; + if (stat) { - cid->r->status = ap_scan_script_header_err_strs(cid->r, NULL, - &termch, &termarg, stat, head, NULL); + res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, + stat, head, NULL); + } + else { + res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, + head, NULL); + } + + /* Set our status. */ + if (res) { + /* This is an immediate error result from the parser + */ + cid->r->status = res; + cid->r->status_line = ap_get_status_line(cid->r->status); + cid->ecb->dwHttpStatusCode = cid->r->status; + } + else if (cid->r->status) { + /* We have a status in r->status, so let's just use it. + * This is likely to be the Status: parsed above, and + * may also be a delayed error result from the parser. + * If it was filled in, status_line should also have + * been filled in. + */ + cid->ecb->dwHttpStatusCode = cid->r->status; + } + else if (cid->ecb->dwHttpStatusCode + && cid->ecb->dwHttpStatusCode != HTTP_OK) { + /* Now we fall back on dwHttpStatusCode if it appears + * ap_scan_script_header fell back on the default code. + * Any other results set dwHttpStatusCode to the decoded + * status value. + */ + cid->r->status = cid->ecb->dwHttpStatusCode; + cid->r->status_line = ap_get_status_line(cid->r->status); + } + else if (old_status) { + /* Well... either there is no dwHttpStatusCode or it's HTTP_OK. + * In any case, we don't have a good status to return yet... + * Perhaps the one we came in with will be better. Let's use it, + * if we were given one (note this is a pendantic case, it would + * normally be covered above unless the scan script code unset + * the r->status). Should there be a check here as to whether + * we are setting a valid response code? + */ + cid->r->status = old_status; + cid->r->status_line = ap_get_status_line(cid->r->status); cid->ecb->dwHttpStatusCode = cid->r->status; } else { - cid->r->status = ap_scan_script_header_err_strs(cid->r, NULL, - &termch, &termarg, head, NULL); - if (cid->ecb->dwHttpStatusCode && cid->r->status == HTTP_OK - && cid->ecb->dwHttpStatusCode != HTTP_OK) { - /* We tried every way to Sunday to get the status... - * so now we fall back on dwHttpStatusCode if it appears - * ap_scan_script_header fell back on the default code. - * Any other results set dwHttpStatusCode to the decoded - * status value. - */ - cid->r->status = cid->ecb->dwHttpStatusCode; - cid->r->status_line = ap_get_status_line(cid->r->status); - } - else { - cid->ecb->dwHttpStatusCode = cid->r->status; - } + /* None of dwHttpStatusCode, the parser's r->status nor the + * old value of r->status were helpful, and nothing was decoded + * from Status: string passed to us. Let's just say HTTP_OK + * and get the data out, this was the isapi dev's oversight. + */ + cid->r->status = HTTP_OK; + cid->r->status_line = ap_get_status_line(cid->r->status); + cid->ecb->dwHttpStatusCode = cid->r->status; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, cid->r, + "ISAPI: Could not determine HTTP response code; using %d", + cid->r->status); } + if (cid->r->status == HTTP_INTERNAL_SERVER_ERROR) { return -1; } @@ -809,7 +853,7 @@ int APR_THREAD_FUNC WriteClient(isapi_cid *cid, *size_arg, ERROR_WRITE_FAULT); } } - return (rv == OK); + return (rv == APR_SUCCESS); } int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, @@ -822,6 +866,7 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, conn_rec *c = r->connection; char *buf_data = (char*)buf_ptr; request_rec *subreq; + apr_status_t rv; switch (HSE_code) { case HSE_REQ_SEND_URL_REDIRECT_RESP: @@ -881,10 +926,10 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, APR_BRIGADE_INSERT_TAIL(bb, b); b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); - ap_pass_brigade(cid->r->output_filters, bb); + rv = ap_pass_brigade(cid->r->output_filters, bb); cid->response_sent = 1; + return (rv == APR_SUCCESS); } - return 1; } case HSE_REQ_DONE_WITH_SESSION: @@ -909,20 +954,33 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, /* Map a URL to a filename */ char *file = (char *)buf_data; apr_uint32_t len; - subreq = ap_sub_req_lookup_uri(apr_pstrndup(r->pool, file, *buf_size), - r, NULL); + subreq = ap_sub_req_lookup_uri( + apr_pstrndup(cid->r->pool, file, *buf_size), r, NULL); + + if (!subreq->filename) { + ap_destroy_sub_req(subreq); + return 0; + } + + len = (apr_uint32_t)strlen(r->filename); - len = apr_cpystrn(file, subreq->filename, *buf_size) - file; + if ((subreq->finfo.filetype == APR_DIR) + && (!subreq->path_info) + && (file[len - 1] != '/')) + file = apr_pstrcat(cid->r->pool, subreq->filename, "/", NULL); + else + file = apr_pstrcat(cid->r->pool, subreq->filename, + subreq->path_info, NULL); + ap_destroy_sub_req(subreq); + +#ifdef WIN32 + /* We need to make this a real Windows path name */ + apr_filepath_merge(&file, "", file, APR_FILEPATH_NATIVE, r->pool); +#endif + + *buf_size = apr_cpystrn(buf_data, file, *buf_size) - buf_data; - /* IIS puts a trailing slash on directories, Apache doesn't */ - if (subreq->finfo.filetype == APR_DIR) { - if (len < *buf_size - 1) { - file[len++] = '\\'; - file[len] = '\0'; - } - } - *buf_size = len; return 1; } @@ -976,7 +1034,6 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, HSE_TF_INFO *tf = (HSE_TF_INFO*)buf_data; apr_uint32_t sent = 0; apr_ssize_t ate = 0; - apr_status_t rv; apr_bucket_brigade *bb; apr_bucket *b; apr_file_t *fd; @@ -1050,28 +1107,7 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, } sent += (apr_uint32_t)fsize; -#if APR_HAS_LARGE_FILES - if (r->finfo.size > AP_MAX_SENDFILE) { - /* APR_HAS_LARGE_FILES issue; must split into mutiple buckets, - * no greater than MAX(apr_size_t), and more granular than that - * in case the brigade code/filters attempt to read it directly. - */ - b = apr_bucket_file_create(fd, tf->Offset, AP_MAX_SENDFILE, - r->pool, c->bucket_alloc); - while (fsize > AP_MAX_SENDFILE) { - apr_bucket *bc; - apr_bucket_copy(b, &bc); - APR_BRIGADE_INSERT_TAIL(bb, bc); - b->start += AP_MAX_SENDFILE; - fsize -= AP_MAX_SENDFILE; - } - b->length = (apr_size_t)fsize; /* Resize just the last bucket */ - } - else -#endif - b = apr_bucket_file_create(fd, tf->Offset, (apr_size_t)fsize, - r->pool, c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, b); + apr_brigade_insert_file(bb, fd, tf->Offset, fsize, r->pool); if (tf->pTail && tf->TailLength) { sent += tf->TailLength; @@ -1082,7 +1118,7 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); - ap_pass_brigade(r->output_filters, bb); + rv = ap_pass_brigade(r->output_filters, bb); cid->response_sent = 1; /* Use tf->pfnHseIO + tf->pContext, or if NULL, then use cid->fnIOComplete @@ -1110,7 +1146,7 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, } } } - return (rv == OK); + return (rv == APR_SUCCESS); } case HSE_REQ_REFRESH_ISAPI_ACL: @@ -1282,10 +1318,10 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, APR_BRIGADE_INSERT_TAIL(bb, b); b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); - ap_pass_brigade(cid->r->output_filters, bb); + rv = ap_pass_brigade(cid->r->output_filters, bb); cid->response_sent = 1; } - return 1; + return (rv == APR_SUCCESS); } case HSE_REQ_CLOSE_CONNECTION: /* Added after ISAPI 4.0 */ @@ -1582,7 +1618,8 @@ apr_status_t isapi_handler (request_rec *r) rv = ap_pass_brigade(r->output_filters, bb); cid->response_sent = 1; - return OK; /* NOT r->status or cid->r->status, even if it has changed. */ + return (rv == APR_SUCCESS); + /* NOT r->status or cid->r->status, even if it has changed. */ } /* As the client returned no error, and if we did not error out