Commit e33b1f37 authored by William A. Rowe Jr's avatar William A. Rowe Jr
Browse files

mod_isapi: Simply backport the host of fixes for compilation on unix,

and resolve PR#'s 15993 29098 30022 16637 30033 28089
by pushing to trunk/ rev 416293 of modules/arch/win32/mod_isapi.[ch]
which compiles with the addition of [apr_]brigade_insert_file() as
cribbed from apr-util 1.x trunk.  delta previously posted at
  http://people.apache.org/~wrowe/mod_isapi-416293-to-httpd-2.0.patch
and broadly tested with positive results, with the exception of one
more patch incoming to handle ate == left edge case.

Previously reviewed by jerenkrantz, fielding, wrowe for httpd-2.0.
Code committed is identical.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.0.x@477376 13f79535-47bb-0310-9956-ffa450edef68
parent 5be6ed72
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -142,16 +142,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK:
        wrowe adds; even if ineffective for some oddball machine, this
                    patch is entirely harmless.

    * 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 with the addition of [apr_]brigade_insert_file() as
      cribbed from apr-util 1.x trunk.  Source + Binary posted at
        http://people.apache.org/~wrowe/mod_isapi-416293.zip
      and delta posted at
        http://people.apache.org/~wrowe/mod_isapi-416293-to-httpd-2.0.patch
      +1: wrowe 

    * mod_ssl: Solve POST incompatible w/ renegotiate HTTPS connection
      (This was already committed to 2.2.x, and the reports persist.)
        http://issues.apache.org/bugzilla/show_bug.cgi?id=12355
+258 −187
Original line number Diff line number Diff line
@@ -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,18 +711,37 @@ 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);
        cid->ecb->dwHttpStatusCode = cid->r->status;
        res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg,
                stat, head, NULL);
    }
    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
        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) {
            /* We tried every way to Sunday to get the status...
             * so now we fall back on dwHttpStatusCode if it appears
        /* 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.
@@ -728,10 +749,33 @@ static apr_ssize_t send_response_header(isapi_cid *cid,
        cid->r->status = cid->ecb->dwHttpStatusCode;
        cid->r->status_line = ap_get_status_line(cid->r->status);
    }
        else {
    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 {
        /* 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,41 @@ int APR_THREAD_FUNC WriteClient(isapi_cid *cid,
                            *size_arg, ERROR_WRITE_FAULT);
        }
    }
    return (rv == OK);
    return (rv == APR_SUCCESS);
}

/* A "safe" maximum bucket size, 1Gb */
#define MAX_BUCKET_SIZE (0x40000000)

apr_bucket *brigade_insert_file(apr_bucket_brigade *bb,
                                apr_file_t *f,
                                apr_off_t start,
                                apr_off_t length,
                                apr_pool_t *p)
{
    apr_bucket *e;

    if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) {
        e = apr_bucket_file_create(f, start, (apr_size_t)length, p, 
                                   bb->bucket_alloc);
    }
    else {
        /* Several buckets are needed. */        
        e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p, 
                                   bb->bucket_alloc);

        while (length > MAX_BUCKET_SIZE) {
            apr_bucket *ce;
            apr_bucket_copy(e, &ce);
            APR_BRIGADE_INSERT_TAIL(bb, ce);
            e->start += MAX_BUCKET_SIZE;
            length -= MAX_BUCKET_SIZE;
        }
        e->length = (apr_size_t)length; /* Resize just the last bucket */
    }
    
    APR_BRIGADE_INSERT_TAIL(bb, e);
    return e;
}

int APR_THREAD_FUNC ServerSupportFunction(isapi_cid    *cid,
@@ -822,6 +900,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 +960,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 +988,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);

        len = apr_cpystrn(file, subreq->filename, *buf_size) - file;
        if (!subreq->filename) {
            ap_destroy_sub_req(subreq);
            return 0;
        }

        len = (apr_uint32_t)strlen(r->filename);

        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 +1068,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 +1141,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);
        brigade_insert_file(bb, fd, tf->Offset, fsize, r->pool);

        if (tf->pTail && tf->TailLength) {
            sent += tf->TailLength;
@@ -1082,7 +1152,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 +1180,7 @@ int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid,
                }
            }
        }
        return (rv == OK);
        return (rv == APR_SUCCESS);
    }

    case HSE_REQ_REFRESH_ISAPI_ACL:
@@ -1282,10 +1352,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 +1652,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
@@ -1608,7 +1679,7 @@ static int isapi_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte
{
    apr_status_t rv;

    apr_pool_sub_make(&loaded.pool, pconf, NULL);
    apr_pool_create_ex(&loaded.pool, pconf, NULL, NULL);
    if (!loaded.pool) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, NULL,
                     "ISAPI: could not create the isapi cache pool");