You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2006/11/20 23:39:23 UTC
svn commit: r477376 - in /httpd/httpd/branches/2.0.x: STATUS
modules/arch/win32/mod_isapi.c
Author: wrowe
Date: Mon Nov 20 14:39:22 2006
New Revision: 477376
URL: http://svn.apache.org/viewvc?view=rev&rev=477376
Log:
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.
Modified:
httpd/httpd/branches/2.0.x/STATUS
httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c
Modified: httpd/httpd/branches/2.0.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.0.x/STATUS?view=diff&rev=477376&r1=477375&r2=477376
==============================================================================
--- httpd/httpd/branches/2.0.x/STATUS (original)
+++ httpd/httpd/branches/2.0.x/STATUS Mon Nov 20 14:39:22 2006
@@ -142,16 +142,6 @@
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
Modified: httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c?view=diff&rev=477376&r1=477375&r2=477376
==============================================================================
--- httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c (original)
+++ httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c Mon Nov 20 14:39:22 2006
@@ -77,13 +77,13 @@
typedef struct isapi_loaded isapi_loaded;
-apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,
+apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,
const char *fpath, isapi_loaded** isa);
static void *create_isapi_dir_config(apr_pool_t *p, char *dummy)
{
isapi_dir_conf *dir = apr_palloc(p, sizeof(isapi_dir_conf));
-
+
dir->read_ahead_buflen = ISAPI_UNDEF;
dir->log_unsupported = ISAPI_UNDEF;
dir->log_to_errlog = ISAPI_UNDEF;
@@ -98,7 +98,7 @@
isapi_dir_conf *base = (isapi_dir_conf *) base_;
isapi_dir_conf *add = (isapi_dir_conf *) add_;
isapi_dir_conf *dir = apr_palloc(p, sizeof(isapi_dir_conf));
-
+
dir->read_ahead_buflen = (add->read_ahead_buflen == ISAPI_UNDEF)
? base->read_ahead_buflen
: add->read_ahead_buflen;
@@ -114,11 +114,11 @@
dir->fake_async = (add->fake_async == ISAPI_UNDEF)
? base->fake_async
: add->fake_async;
-
+
return dir;
}
-static const char *isapi_cmd_cachefile(cmd_parms *cmd, void *dummy,
+static const char *isapi_cmd_cachefile(cmd_parms *cmd, void *dummy,
const char *filename)
{
isapi_loaded *isa;
@@ -136,28 +136,28 @@
*/
fspec = ap_server_root_relative(cmd->pool, filename);
if (!fspec) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EBADPATH, cmd->server,
- "ISAPI: invalid module path, skipping %s", filename);
- return NULL;
- }
- if ((rv = apr_stat(&tmp, fspec, APR_FINFO_TYPE,
- cmd->temp_pool)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,
- "ISAPI: unable to stat, skipping %s", fspec);
- return NULL;
+ ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EBADPATH, cmd->server,
+ "ISAPI: invalid module path, skipping %s", filename);
+ return NULL;
+ }
+ if ((rv = apr_stat(&tmp, fspec, APR_FINFO_TYPE,
+ cmd->temp_pool)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,
+ "ISAPI: unable to stat, skipping %s", fspec);
+ return NULL;
}
if (tmp.filetype != APR_REG) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
- "ISAPI: not a regular file, skipping %s", fspec);
- return NULL;
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
+ "ISAPI: not a regular file, skipping %s", fspec);
+ return NULL;
}
/* Load the extention as cached (with null request_rec) */
- rv = isapi_lookup(cmd->pool, cmd->server, NULL, fspec, &isa);
+ rv = isapi_lookup(cmd->pool, cmd->server, NULL, fspec, &isa);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,
"ISAPI: unable to cache, skipping %s", fspec);
- return NULL;
+ return NULL;
}
return NULL;
@@ -165,26 +165,26 @@
static const command_rec isapi_cmds[] = {
AP_INIT_TAKE1("ISAPIReadAheadBuffer", ap_set_int_slot,
- (void *)APR_OFFSETOF(isapi_dir_conf, read_ahead_buflen),
+ (void *)APR_OFFSETOF(isapi_dir_conf, read_ahead_buflen),
OR_FILEINFO, "Maximum client request body to initially pass to the"
" ISAPI handler (default: 49152)"),
AP_INIT_FLAG("ISAPILogNotSupported", ap_set_flag_slot,
- (void *)APR_OFFSETOF(isapi_dir_conf, log_unsupported),
+ (void *)APR_OFFSETOF(isapi_dir_conf, log_unsupported),
OR_FILEINFO, "Log requests not supported by the ISAPI server"
" on or off (default: off)"),
AP_INIT_FLAG("ISAPIAppendLogToErrors", ap_set_flag_slot,
- (void *)APR_OFFSETOF(isapi_dir_conf, log_to_errlog),
+ (void *)APR_OFFSETOF(isapi_dir_conf, log_to_errlog),
OR_FILEINFO, "Send all Append Log requests to the error log"
" on or off (default: off)"),
AP_INIT_FLAG("ISAPIAppendLogToQuery", ap_set_flag_slot,
- (void *)APR_OFFSETOF(isapi_dir_conf, log_to_query),
+ (void *)APR_OFFSETOF(isapi_dir_conf, log_to_query),
OR_FILEINFO, "Append Log requests are concatinated to the query args"
" on or off (default: on)"),
AP_INIT_FLAG("ISAPIFakeAsync", ap_set_flag_slot,
- (void *)APR_OFFSETOF(isapi_dir_conf, fake_async),
+ (void *)APR_OFFSETOF(isapi_dir_conf, fake_async),
OR_FILEINFO, "Fake Asynchronous support for isapi callbacks"
" on or off [Experimental] (default: off)"),
- AP_INIT_ITERATE("ISAPICacheFile", isapi_cmd_cachefile, NULL,
+ AP_INIT_ITERATE("ISAPICacheFile", isapi_cmd_cachefile, NULL,
RSRC_CONF, "Cache the specified ISAPI extension in-process"),
{NULL}
};
@@ -222,7 +222,7 @@
/* All done with the DLL... get rid of it...
*
* If optionally cached, and we weren't asked to force the unload,
- * pass HSE_TERM_ADVISORY_UNLOAD, and if it returns 1, unload,
+ * pass HSE_TERM_ADVISORY_UNLOAD, and if it returns 1, unload,
* otherwise, leave it alone (it didn't choose to cooperate.)
*/
if (!isa->handle) {
@@ -245,7 +245,7 @@
{
isapi_loaded* isa = (isapi_loaded*) isa_;
- /* We must force the module to unload, we are about
+ /* We must force the module to unload, we are about
* to lose the isapi structure's allocation entirely.
*/
return isapi_unload(isa, 1);
@@ -261,13 +261,13 @@
* assure a given isapi can be fooled into behaving well.
*
* The tricky bit, they aren't really a per-dir sort of
- * config, they will always be constant across every
+ * config, they will always be constant across every
* reference to the .dll no matter what context (vhost,
* location, etc) they apply to.
*/
isa->report_version = 0x500; /* Revision 5.0 */
isa->timeout = 300 * 1000000; /* microsecs, not used */
-
+
rv = apr_dso_load(&isa->handle, isa->filename, p);
if (rv)
{
@@ -310,20 +310,20 @@
if (!(isa->GetExtensionVersion)(isa->isapi_version)) {
apr_status_t rv = apr_get_os_error();
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
- "ISAPI: failed call to GetExtensionVersion() in %s",
+ "ISAPI: failed call to GetExtensionVersion() in %s",
isa->filename);
apr_dso_unload(isa->handle);
isa->handle = NULL;
return rv;
}
- apr_pool_cleanup_register(p, isa, cleanup_isapi,
+ apr_pool_cleanup_register(p, isa, cleanup_isapi,
apr_pool_cleanup_null);
return APR_SUCCESS;
}
-apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,
+apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r,
const char *fpath, isapi_loaded** isa)
{
apr_status_t rv;
@@ -338,7 +338,7 @@
if (*isa) {
/* If we find this lock exists, use a set-aside copy of gainlock
- * to avoid race conditions on NULLing the in_progress variable
+ * to avoid race conditions on NULLing the in_progress variable
* when the load has completed. Release the global isapi hash
* lock so other requests can proceed, then rdlock for completion
* of loading our desired dll or wrlock if we would like to retry
@@ -355,10 +355,10 @@
return rv;
}
-
+
if ((*isa)->last_load_rv == APR_SUCCESS) {
apr_thread_mutex_unlock(loaded.lock);
- if ((rv = apr_thread_rwlock_rdlock(gainlock))
+ if ((rv = apr_thread_rwlock_rdlock(gainlock))
!= APR_SUCCESS) {
return rv;
}
@@ -368,7 +368,7 @@
}
if (apr_time_now() > (*isa)->last_load_time + ISAPI_RETRY) {
-
+
/* Remember last_load_time before releasing the global
* hash lock to avoid colliding with another thread
* that hit this exception at the same time as our
@@ -378,13 +378,13 @@
apr_time_t check_time = (*isa)->last_load_time;
apr_thread_mutex_unlock(loaded.lock);
- if ((rv = apr_thread_rwlock_wrlock(gainlock))
+ if ((rv = apr_thread_rwlock_wrlock(gainlock))
!= APR_SUCCESS) {
return rv;
}
/* If last_load_time is unchanged, we still own this
- * retry, otherwise presume another thread provided
+ * retry, otherwise presume another thread provided
* our retry (for good or ill). Relock the global
* hash for updating last_load_ vars, so their update
* is always atomic to the global lock.
@@ -416,7 +416,7 @@
}
/* If the module was not found, it's time to create a hash key entry
- * before releasing the hash lock to avoid multiple threads from
+ * before releasing the hash lock to avoid multiple threads from
* loading the same module.
*/
key = apr_pstrdup(loaded.pool, fpath);
@@ -437,8 +437,8 @@
}
apr_hash_set(loaded.hash, key, APR_HASH_KEY_STRING, *isa);
-
- /* Now attempt to load the isapi on our own time,
+
+ /* Now attempt to load the isapi on our own time,
* allow other isapi processing to resume.
*/
apr_thread_mutex_unlock(loaded.lock);
@@ -457,7 +457,7 @@
}
else if (!r && (rv != APR_SUCCESS)) {
/* We must leave a rwlock around for requests to retry
- * loading this dll after timeup... since we were in
+ * loading this dll after timeup... since we were in
* the setup code we had avoided creating this lock.
*/
apr_thread_rwlock_create(&(*isa)->in_progress, loaded.pool);
@@ -485,7 +485,7 @@
apr_thread_mutex_t *completed;
};
-int APR_THREAD_FUNC GetServerVariable (isapi_cid *cid,
+int APR_THREAD_FUNC GetServerVariable (isapi_cid *cid,
char *variable_name,
void *buf_ptr,
apr_uint32_t *buf_size)
@@ -495,10 +495,10 @@
char *buf_data = (char*)buf_ptr;
apr_uint32_t len;
- if (!strcmp(variable_name, "ALL_HTTP"))
+ if (!strcmp(variable_name, "ALL_HTTP"))
{
- /* crlf delimited, colon split, comma separated and
- * null terminated list of HTTP_ vars
+ /* crlf delimited, colon split, comma separated and
+ * null terminated list of HTTP_ vars
*/
const apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts;
@@ -509,13 +509,13 @@
len += strlen(elts[i].key) + strlen(elts[i].val) + 3;
}
}
-
+
if (*buf_size < len + 1) {
*buf_size = len + 1;
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INSUFFICIENT_BUFFER));
return 0;
}
-
+
for (i = 0; i < arr->nelts; i++) {
if (!strncmp(elts[i].key, "HTTP_", 5)) {
strcpy(buf_data, elts[i].key);
@@ -532,10 +532,10 @@
*buf_size = len + 1;
return 1;
}
-
- if (!strcmp(variable_name, "ALL_RAW"))
+
+ if (!strcmp(variable_name, "ALL_RAW"))
{
- /* crlf delimited, colon split, comma separated and
+ /* crlf delimited, colon split, comma separated and
* null terminated list of the raw request header
*/
const apr_array_header_t *arr = apr_table_elts(r->headers_in);
@@ -545,13 +545,13 @@
for (len = 0, i = 0; i < arr->nelts; i++) {
len += strlen(elts[i].key) + strlen(elts[i].val) + 4;
}
-
+
if (*buf_size < len + 1) {
*buf_size = len + 1;
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INSUFFICIENT_BUFFER));
return 0;
}
-
+
for (i = 0; i < arr->nelts; i++) {
strcpy(buf_data, elts[i].key);
buf_data += strlen(elts[i].key);
@@ -566,7 +566,7 @@
*buf_size = len + 1;
return 1;
}
-
+
/* Not a special case */
result = apr_table_get(r->subprocess_env, variable_name);
@@ -587,8 +587,8 @@
return 0;
}
-int APR_THREAD_FUNC ReadClient(isapi_cid *cid,
- void *buf_data,
+int APR_THREAD_FUNC ReadClient(isapi_cid *cid,
+ void *buf_data,
apr_uint32_t *buf_size)
{
request_rec *r = cid->r;
@@ -612,7 +612,7 @@
return (res >= 0);
}
-/* Common code invoked for both HSE_REQ_SEND_RESPONSE_HEADER and
+/* Common code invoked for both HSE_REQ_SEND_RESPONSE_HEADER and
* the newer HSE_REQ_SEND_RESPONSE_HEADER_EX ServerSupportFunction(s)
* as well as other functions that write responses and presume that
* the support functions above are optional.
@@ -622,14 +622,16 @@
* get a proper count of bytes consumed. The argument passed to stat
* isn't counted as the head bytes are.
*/
-static apr_ssize_t send_response_header(isapi_cid *cid,
+static apr_ssize_t send_response_header(isapi_cid *cid,
const char *stat,
- const char *head,
+ const char *head,
apr_size_t statlen,
apr_size_t headlen)
{
int head_present = 1;
int termarg;
+ int res;
+ int old_status;
const char *termch;
apr_size_t ate = 0;
@@ -676,11 +678,11 @@
while (toklen && apr_isspace(*stattok)) {
++stattok; --toklen;
}
- /* Now decide if we follow the xxx message
- * or the http/x.x xxx message format
+ /* Now decide if we follow the xxx message
+ * or the http/x.x xxx message format
*/
if (toklen && apr_isdigit(*stattok)) {
- statlen -= toklen;
+ statlen = toklen;
stat = stattok;
}
}
@@ -702,48 +704,90 @@
head = apr_pstrndup(cid->r->pool, head, headlen);
}
}
-
- /* Seems IIS does not enforce the requirement for \r\n termination
- * on HSE_REQ_SEND_RESPONSE_HEADER, but we won't panic...
+
+ /* Seems IIS does not enforce the requirement for \r\n termination
+ * on HSE_REQ_SEND_RESPONSE_HEADER, but we won't panic...
* ap_scan_script_header_err_strs handles this aspect for us.
*
- * Parse them out, or die trying
+ * 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;
}
- /* If only Status was passed, we consumed nothing
+ /* If only Status was passed, we consumed nothing
*/
if (!head_present)
return 0;
cid->headers_set = 1;
- /* If all went well, tell the caller we consumed the headers complete
+ /* If all went well, tell the caller we consumed the headers complete
*/
if (!termch)
return(ate + headlen);
@@ -801,18 +845,52 @@
if ((flags & HSE_IO_ASYNC) && cid->completion) {
if (rv == OK) {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
*size_arg, ERROR_SUCCESS);
}
else {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
*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,
+int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid,
apr_uint32_t HSE_code,
void *buf_ptr,
apr_uint32_t *buf_size,
@@ -822,6 +900,7 @@
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:
@@ -876,15 +955,15 @@
apr_bucket_brigade *bb;
apr_bucket *b;
bb = apr_brigade_create(cid->r->pool, c->bucket_alloc);
- b = apr_bucket_transient_create((char*) data_type + ate,
+ b = apr_bucket_transient_create((char*) data_type + ate,
headlen - ate, c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, b);
+ 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);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ 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 @@
/* 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;
}
@@ -933,7 +1025,7 @@
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
-
+
case HSE_APPEND_LOG_PARAMETER:
/* Log buf_data, of buf_size bytes, in the URI Query (cs-uri-query) field
*/
@@ -949,10 +1041,10 @@
"ISAPI: %s: %s", cid->r->filename,
(char*) buf_data);
return 1;
-
+
case HSE_REQ_IO_COMPLETION:
- /* Emulates a completion port... Record callback address and
- * user defined arg, we will call this after any async request
+ /* Emulates a completion port... Record callback address and
+ * user defined arg, we will call this after any async request
* (e.g. transmitfile) as if the request executed async.
* Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
* to HSE_REQ_IO_COMPLETION, and buf_data may be set to NULL.
@@ -976,7 +1068,6 @@
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;
@@ -990,12 +1081,12 @@
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
}
-
+
/* Presume the handle was opened with the CORRECT semantics
- * for TransmitFile
+ * for TransmitFile
*/
- if ((rv = apr_os_file_put(&fd, &tf->hFile,
- APR_READ | APR_XTHREAD, r->pool))
+ if ((rv = apr_os_file_put(&fd, &tf->hFile,
+ APR_READ | APR_XTHREAD, r->pool))
!= APR_SUCCESS) {
return 0;
}
@@ -1010,7 +1101,7 @@
}
fsize = fi.size - tf->Offset;
}
-
+
/* apr_dupfile_oshandle (&fd, tf->hFile, r->pool); */
bb = apr_brigade_create(r->pool, c->bucket_alloc);
@@ -1024,12 +1115,12 @@
* (handled after this case).
*/
if ((tf->dwFlags & HSE_IO_SEND_HEADERS) && tf->pszStatusCode) {
- ate = send_response_header(cid, tf->pszStatusCode,
+ ate = send_response_header(cid, tf->pszStatusCode,
(char*)tf->pHead,
strlen(tf->pszStatusCode),
tf->HeadLength);
}
- else if (!cid->headers_set && tf->pHead && tf->HeadLength
+ else if (!cid->headers_set && tf->pHead && tf->HeadLength
&& *(char*)tf->pHead) {
ate = send_response_header(cid, NULL, (char*)tf->pHead,
0, tf->HeadLength);
@@ -1042,7 +1133,7 @@
}
if (tf->pHead && (apr_size_t)ate < tf->HeadLength) {
- b = apr_bucket_transient_create((char*)tf->pHead + ate,
+ b = apr_bucket_transient_create((char*)tf->pHead + ate,
tf->HeadLength - ate,
c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
@@ -1050,39 +1141,18 @@
}
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;
- b = apr_bucket_transient_create((char*)tf->pTail,
+ b = apr_bucket_transient_create((char*)tf->pTail,
tf->TailLength, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
}
-
+
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
@@ -1091,26 +1161,26 @@
if (tf->dwFlags & HSE_IO_ASYNC) {
if (tf->pfnHseIO) {
if (rv == OK) {
- tf->pfnHseIO(cid->ecb, tf->pContext,
+ tf->pfnHseIO(cid->ecb, tf->pContext,
ERROR_SUCCESS, sent);
}
else {
- tf->pfnHseIO(cid->ecb, tf->pContext,
+ tf->pfnHseIO(cid->ecb, tf->pContext,
ERROR_WRITE_FAULT, sent);
}
}
else if (cid->completion) {
if (rv == OK) {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
sent, ERROR_SUCCESS);
}
else {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
sent, ERROR_WRITE_FAULT);
}
}
}
- return (rv == OK);
+ return (rv == APR_SUCCESS);
}
case HSE_REQ_REFRESH_ISAPI_ACL:
@@ -1131,9 +1201,9 @@
apr_uint32_t read = 0;
int res;
if (!cid->dconf.fake_async) {
- if (cid->dconf.log_unsupported)
+ if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
- "ISAPI: asynchronous I/O not supported: %s",
+ "ISAPI: asynchronous I/O not supported: %s",
r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
@@ -1151,11 +1221,11 @@
if ((*data_type & HSE_IO_ASYNC) && cid->completion) {
if (res >= 0) {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
read, ERROR_SUCCESS);
}
else {
- cid->completion(cid->ecb, cid->completion_arg,
+ cid->completion(cid->ecb, cid->completion_arg,
read, ERROR_READ_FAULT);
}
}
@@ -1178,8 +1248,8 @@
char* test_uri = apr_pstrndup(r->pool, (char *)buf_data, *buf_size);
subreq = ap_sub_req_lookup_uri(test_uri, r, NULL);
- info->cchMatchingURL = strlen(test_uri);
- info->cchMatchingPath = apr_cpystrn(info->lpszPath, subreq->filename,
+ info->cchMatchingURL = strlen(test_uri);
+ info->cchMatchingPath = apr_cpystrn(info->lpszPath, subreq->filename,
sizeof(info->lpszPath)) - info->lpszPath;
/* Mapping started with assuming both strings matched.
@@ -1187,8 +1257,8 @@
* terminating slashes for directory matches.
*/
if (subreq->path_info && *subreq->path_info) {
- apr_cpystrn(info->lpszPath + info->cchMatchingPath,
- subreq->path_info,
+ apr_cpystrn(info->lpszPath + info->cchMatchingPath,
+ subreq->path_info,
sizeof(info->lpszPath) - info->cchMatchingPath);
info->cchMatchingURL -= strlen(subreq->path_info);
if (subreq->finfo.filetype == APR_DIR
@@ -1208,18 +1278,18 @@
/* If the matched isn't a file, roll match back to the prior slash */
if (subreq->finfo.filetype == APR_NOFILE) {
while (info->cchMatchingPath && info->cchMatchingURL) {
- if (info->lpszPath[info->cchMatchingPath - 1] == '/')
+ if (info->lpszPath[info->cchMatchingPath - 1] == '/')
break;
--info->cchMatchingPath;
--info->cchMatchingURL;
}
}
-
+
/* Paths returned with back slashes */
for (test_uri = info->lpszPath; *test_uri; ++test_uri)
if (*test_uri == '/')
*test_uri = '\\';
-
+
/* is a combination of:
* HSE_URL_FLAGS_READ 0x001 Allow read
* HSE_URL_FLAGS_WRITE 0x002 Allow write
@@ -1234,7 +1304,7 @@
*
* XxX: As everywhere, EXEC flags could use some work...
* and this could go further with more flags, as desired.
- */
+ */
info->dwFlags = (subreq->finfo.protection & APR_UREAD ? 0x001 : 0)
| (subreq->finfo.protection & APR_UWRITE ? 0x002 : 0)
| (subreq->finfo.protection & APR_UEXECUTE ? 0x204 : 0);
@@ -1254,7 +1324,7 @@
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction "
"HSE_REQ_GET_CERT_INFO_EX "
- "is not supported: %s", r->filename);
+ "is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
@@ -1264,9 +1334,9 @@
/* Ignore shi->fKeepConn - we don't want the advise
*/
- apr_ssize_t ate = send_response_header(cid, shi->pszStatus,
+ apr_ssize_t ate = send_response_header(cid, shi->pszStatus,
shi->pszHeader,
- shi->cchStatus,
+ shi->cchStatus,
shi->cchHeader);
if (ate < 0) {
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
@@ -1276,16 +1346,16 @@
apr_bucket_brigade *bb;
apr_bucket *b;
bb = apr_brigade_create(cid->r->pool, c->bucket_alloc);
- b = apr_bucket_transient_create(shi->pszHeader + ate,
+ b = apr_bucket_transient_create(shi->pszHeader + ate,
shi->cchHeader - ate,
c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, b);
+ 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);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ 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 */
@@ -1341,14 +1411,14 @@
const char *val;
apr_uint32_t read;
int res;
-
- if(strcmp(r->handler, "isapi-isa")
+
+ if(strcmp(r->handler, "isapi-isa")
&& strcmp(r->handler, "isapi-handler")) {
/* Hang on to the isapi-isa for compatibility with older docs
* (wtf did '-isa' mean in the first place?) but introduce
* a newer and clearer "isapi-handler" name.
*/
- return DECLINED;
+ return DECLINED;
}
dconf = ap_get_module_config(r->per_dir_config, &isapi_module);
e = r->subprocess_env;
@@ -1372,7 +1442,7 @@
return HTTP_NOT_FOUND;
}
- if (isapi_lookup(r->pool, r->server, r, r->filename, &isa)
+ if (isapi_lookup(r->pool, r->server, r, r->filename, &isa)
!= APR_SUCCESS) {
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -1390,7 +1460,7 @@
* NULL or zero out most fields.
*/
cid = apr_pcalloc(r->pool, sizeof(isapi_cid));
-
+
/* Fixup defaults for dconf */
cid->dconf.read_ahead_buflen = (dconf->read_ahead_buflen == ISAPI_UNDEF)
? 49152 : dconf->read_ahead_buflen;
@@ -1408,7 +1478,7 @@
cid->isa = isa;
cid->r = r;
r->status = 0;
-
+
cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
cid->ecb->dwVersion = isa->report_version;
cid->ecb->dwHttpStatusCode = 0;
@@ -1420,7 +1490,7 @@
cid->ecb->lpszPathInfo = (char*) apr_table_get(e, "PATH_INFO");
cid->ecb->lpszPathTranslated = (char*) apr_table_get(e, "PATH_TRANSLATED");
cid->ecb->lpszContentType = (char*) apr_table_get(e, "CONTENT_TYPE");
-
+
/* Set up the callbacks */
cid->ecb->GetServerVariable = GetServerVariable;
cid->ecb->WriteClient = WriteClient;
@@ -1493,8 +1563,8 @@
* unlocked the mutex.
*/
if (cid->dconf.fake_async) {
- rv = apr_thread_mutex_create(&cid->completed,
- APR_THREAD_MUTEX_UNNESTED,
+ rv = apr_thread_mutex_create(&cid->completed,
+ APR_THREAD_MUTEX_UNNESTED,
r->pool);
if (cid->completed && (rv == APR_SUCCESS)) {
rv = apr_thread_mutex_lock(cid->completed);
@@ -1551,14 +1621,14 @@
}
break;
- case HSE_STATUS_ERROR:
+ case HSE_STATUS_ERROR:
/* end response if we have yet to do so.
*/
r->status = HTTP_INTERNAL_SERVER_ERROR;
break;
default:
- /* TODO: log unrecognized retval for debugging
+ /* TODO: log unrecognized retval for debugging
*/
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: return code %d from HttpExtensionProc() "
@@ -1582,9 +1652,10 @@
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
* ourselves, trust dwHttpStatusCode to say something relevant.
*/
@@ -1608,13 +1679,13 @@
{
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");
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, NULL,
+ "ISAPI: could not create the isapi cache pool");
return APR_EGENERAL;
}
-
+
loaded.hash = apr_hash_make(loaded.pool);
if (!loaded.hash) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
@@ -1622,7 +1693,7 @@
return APR_EGENERAL;
}
- rv = apr_thread_mutex_create(&loaded.lock, APR_THREAD_MUTEX_DEFAULT,
+ rv = apr_thread_mutex_create(&loaded.lock, APR_THREAD_MUTEX_DEFAULT,
loaded.pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, rv, 0, NULL,
Re: svn commit: r477376 - in /httpd/httpd/branches/2.0.x: STATUS
modules/arch/win32/mod_isapi.c
Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
FYI - mod_isapi simply wasn't running correctly. Although the STATUS file
on 2.0 has mostly festered, I took the maintainer's liberty of applying the
very same platform specific code change that Roy and Justin reviewed for 2.2
byte for byte to the 2.0 tree, rather than persisting the 'temporary' test
binaries over at p.a.o/~wrowe/. There is one last minor fix to apply and this
should be solid with one exception related to keep-alive disconnections that
someone observed over at users@.
Of course - I'm not subverting review - please feel free to continue review
of this proposal from svn and this diff.
Bill
wrowe@apache.org wrote:
> Author: wrowe
> Date: Mon Nov 20 14:39:22 2006
> New Revision: 477376
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=477376
> Log:
> 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.
>
> Modified:
> httpd/httpd/branches/2.0.x/STATUS
> httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c
>
> Modified: httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.0.x/modules/arch/win32/mod_isapi.c?view=diff&rev=477376&r1=477375&r2=477376